diff options
2179 files changed, 29058 insertions, 16875 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c650df6a0ec..7a46d123c5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,7 +109,7 @@ jobs: # intensive jobs to run on free runners, which however also have # less disk space. - name: free up disk space - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be + run: src/ci/scripts/free-disk-space.sh if: matrix.free_disk # Rust Log Analyzer can't currently detect the PR number of a GitHub diff --git a/.gitignore b/.gitignore index f84a3704ca9..ddc8dad95e8 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,7 @@ __pycache__/ node_modules package-lock.json package.json +/src/doc/rustc-dev-guide/mermaid.min.js ## Rustdoc GUI tests tests/rustdoc-gui/src/**.lock diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eeff563d8ec..a5ddff595f5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,6 +12,15 @@ Documentation for contributing to the compiler or tooling is located in the [Gui Development][rustc-dev-guide], commonly known as the [rustc-dev-guide]. Documentation for the standard library in the [Standard library developers Guide][std-dev-guide], commonly known as the [std-dev-guide]. +## Making changes to subtrees and submodules + +For submodules, changes need to be made against the repository corresponding the +submodule, and not the main `rust-lang/rust` repository. + +For subtrees, prefer sending a PR against the subtree's repository if it does +not need to be made against the main `rust-lang/rust` repostory (e.g. a +rustc-dev-guide change that does not accompany a compiler change). + ## About the [rustc-dev-guide] The [rustc-dev-guide] is meant to help document how rustc –the Rust compiler– works, diff --git a/Cargo.lock b/Cargo.lock index 71178bd3407..979198cece8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -734,7 +734,7 @@ dependencies = [ "tracing-subscriber", "unified-diff", "walkdir", - "windows", + "windows 0.59.0", ] [[package]] @@ -1525,7 +1525,6 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", - "serde", ] [[package]] @@ -1535,6 +1534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "foldhash", + "serde", ] [[package]] @@ -3537,6 +3537,7 @@ dependencies = [ "ar_archive_writer", "arrayvec", "bitflags", + "bstr", "cc", "either", "itertools", @@ -3575,7 +3576,7 @@ dependencies = [ "thorin-dwp", "tracing", "wasm-encoder 0.219.1", - "windows", + "windows 0.59.0", ] [[package]] @@ -3633,7 +3634,7 @@ dependencies = [ "tempfile", "thin-vec", "tracing", - "windows", + "windows 0.59.0", ] [[package]] @@ -3695,7 +3696,7 @@ dependencies = [ "shlex", "time", "tracing", - "windows", + "windows 0.59.0", ] [[package]] @@ -3748,7 +3749,7 @@ dependencies = [ "termcolor", "termize", "tracing", - "windows", + "windows 0.59.0", ] [[package]] @@ -4260,7 +4261,6 @@ dependencies = [ "rustc_serialize", "rustc_type_ir", "rustc_type_ir_macros", - "smallvec", "tracing", ] @@ -4481,7 +4481,7 @@ dependencies = [ "smallvec", "termize", "tracing", - "windows", + "windows 0.59.0", ] [[package]] @@ -5184,7 +5184,7 @@ checksum = "355dbe4f8799b304b05e1b0f05fc59b2a18d36645cf169607da45bde2f69a1be" dependencies = [ "core-foundation-sys", "libc", - "windows", + "windows 0.57.0", ] [[package]] @@ -5880,9 +5880,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasi-preview1-component-adapter-provider" -version = "24.0.1" +version = "29.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f76d9fa52234153eeb40b088de91a8c13dc28a912cf6f31cd89ca4bac9024e0" +checksum = "dcd9f21bbde82ba59e415a8725e6ad0d0d7e9e460b1a3ccbca5bdee952c1a324" [[package]] name = "wasm-bindgen" @@ -5944,9 +5944,9 @@ dependencies = [ [[package]] name = "wasm-component-ld" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2b05c3820968b335f10e703218459e4fd2cc91fdfc8f7936a993f1aacaa0938" +checksum = "580305a8e3f1b7a79859a8db897de643533b2851c5eb080fe5800233f16dec88" dependencies = [ "anyhow", "clap", @@ -5954,7 +5954,7 @@ dependencies = [ "libc", "tempfile", "wasi-preview1-component-adapter-provider", - "wasmparser 0.219.1", + "wasmparser 0.223.0", "wat", "windows-sys 0.59.0", "winsplit", @@ -5991,9 +5991,9 @@ dependencies = [ [[package]] name = "wasm-metadata" -version = "0.219.1" +version = "0.223.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af5a8e37a5e996861e1813f8de30911c47609c9ff51a7284f7dbd754dc3a9f3" +checksum = "5c730c3379d3d20e5a0245b0724b924483e853588ca8fba547c1e21f19e7d735" dependencies = [ "anyhow", "indexmap", @@ -6001,8 +6001,9 @@ dependencies = [ "serde_derive", "serde_json", "spdx", - "wasm-encoder 0.219.1", - "wasmparser 0.219.1", + "url", + "wasm-encoder 0.223.0", + "wasmparser 0.223.0", ] [[package]] @@ -6011,12 +6012,8 @@ version = "0.219.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c771866898879073c53b565a6c7b49953795159836714ac56a5befb581227c5" dependencies = [ - "ahash", "bitflags", - "hashbrown 0.14.5", "indexmap", - "semver", - "serde", ] [[package]] @@ -6035,8 +6032,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5a99faceb1a5a84dd6084ec4bfa4b2ab153b5793b43fd8f58b89232634afc35" dependencies = [ "bitflags", + "hashbrown 0.15.2", "indexmap", "semver", + "serde", ] [[package]] @@ -6113,6 +6112,16 @@ dependencies = [ ] [[package]] +name = "windows" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1" +dependencies = [ + "windows-core 0.59.0", + "windows-targets 0.53.0", +] + +[[package]] name = "windows-bindgen" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6141,13 +6150,26 @@ version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", "windows-targets 0.52.6", ] [[package]] +name = "windows-core" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce" +dependencies = [ + "windows-implement 0.59.0", + "windows-interface 0.59.0", + "windows-result 0.3.0", + "windows-strings", + "windows-targets 0.53.0", +] + +[[package]] name = "windows-implement" version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6159,6 +6181,17 @@ dependencies = [ ] [[package]] +name = "windows-implement" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] name = "windows-interface" version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6170,6 +6203,17 @@ dependencies = [ ] [[package]] +name = "windows-interface" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] name = "windows-metadata" version = "0.58.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6185,6 +6229,24 @@ dependencies = [ ] [[package]] +name = "windows-result" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08106ce80268c4067c0571ca55a9b4e9516518eaa1a1fe9b37ca403ae1d1a34" +dependencies = [ + "windows-targets 0.53.0", +] + +[[package]] +name = "windows-strings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b888f919960b42ea4e11c2f408fadb55f78a9f236d5eef084103c8ce52893491" +dependencies = [ + "windows-targets 0.53.0", +] + +[[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6235,7 +6297,7 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", @@ -6243,6 +6305,22 @@ dependencies = [ ] [[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6255,6 +6333,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6267,6 +6351,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6279,12 +6369,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6297,6 +6399,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6309,6 +6417,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6321,6 +6435,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6333,6 +6453,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] name = "winnow" version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6349,9 +6475,9 @@ checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956" [[package]] name = "wit-component" -version = "0.219.1" +version = "0.223.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1673163c0cb14a6a19ddbf44dd4efe6f015ec1ebb8156710ac32501f19fba2" +checksum = "c10ed2aeee4c8ec5715875f62f4a3de3608d6987165c116810d8c2908aa9d93b" dependencies = [ "anyhow", "bitflags", @@ -6360,17 +6486,17 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "wasm-encoder 0.219.1", + "wasm-encoder 0.223.0", "wasm-metadata", - "wasmparser 0.219.1", + "wasmparser 0.223.0", "wit-parser", ] [[package]] name = "wit-parser" -version = "0.219.1" +version = "0.223.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a86f669283257e8e424b9a4fc3518e3ade0b95deb9fbc0f93a1876be3eda598" +checksum = "92772f4dcacb804b275981eea1d920b12b377993b53307f1e33d87404e080281" dependencies = [ "anyhow", "id-arena", @@ -6381,7 +6507,7 @@ dependencies = [ "serde_derive", "serde_json", "unicode-xid", - "wasmparser 0.219.1", + "wasmparser 0.223.0", ] [[package]] diff --git a/RELEASES.md b/RELEASES.md index c4b36ed988b..2da6ed3f100 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -359,7 +359,7 @@ Language - [`addr_of(_mut)!` macros and the newly stabilized `&raw (const|mut)` are now safe to use with all static items](https://github.com/rust-lang/rust/pull/125834) - [size_of_val_raw: for length 0 this is safe to call](https://github.com/rust-lang/rust/pull/126152/) - [Reorder trait bound modifiers *after* `for<...>` binder in trait bounds](https://github.com/rust-lang/rust/pull/127054/) -- [Stabilize opaque type precise capturing (RFC 3617)](https://github.com/rust-lang/rust/pull/127672) +- [Stabilize `+ use<'lt>` opaque type precise capturing (RFC 3617)](https://github.com/rust-lang/rust/pull/127672) - [Stabilize `&raw const` and `&raw mut` operators (RFC 2582)](https://github.com/rust-lang/rust/pull/127679) - [Stabilize unsafe extern blocks (RFC 3484)](https://github.com/rust-lang/rust/pull/127921) - [Stabilize nested field access in `offset_of!`](https://github.com/rust-lang/rust/pull/128284) @@ -573,6 +573,7 @@ Libraries - [Replace sort implementations with stable `driftsort` and unstable `ipnsort`.](https://github.com/rust-lang/rust/pull/124032/) All `slice::sort*` and `slice::select_nth*` methods are expected to see significant performance improvements. See the [research project](https://github.com/Voultapher/sort-research-rs) for more details. - [Document behavior of `create_dir_all` with respect to empty paths.](https://github.com/rust-lang/rust/pull/125112/) - [Fix interleaved output in the default panic hook when multiple threads panic simultaneously.](https://github.com/rust-lang/rust/pull/127397/) +- Fix `Command`'s batch files argument escaping not working when file name has trailing whitespace or periods (CVE-2024-43402). <a id="1.81.0-Stabilized-APIs"></a> diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8e73df63ef5..ad942e9b494 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -28,6 +28,7 @@ use rustc_data_structures::packed::Pu128; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::tagged_ptr::Tag; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; pub use rustc_span::AttrId; use rustc_span::source_map::{Spanned, respan}; @@ -99,7 +100,7 @@ pub struct Path { impl PartialEq<Symbol> for Path { #[inline] fn eq(&self, symbol: &Symbol) -> bool { - self.segments.len() == 1 && { self.segments[0].ident.name == *symbol } + matches!(&self.segments[..], [segment] if segment.ident.name == *symbol) } } @@ -120,13 +121,13 @@ impl Path { } pub fn is_global(&self) -> bool { - !self.segments.is_empty() && self.segments[0].ident.name == kw::PathRoot + self.segments.first().is_some_and(|segment| segment.ident.name == kw::PathRoot) } /// If this path is a single identifier with no arguments, does not ensure /// that the path resolves to a const param, the caller should check this. pub fn is_potential_trivial_const_arg(&self) -> bool { - self.segments.len() == 1 && self.segments[0].args.is_none() + matches!(self.segments[..], [PathSegment { args: None, .. }]) } } @@ -287,6 +288,7 @@ impl ParenthesizedArgs { } } +use crate::AstDeref; pub use crate::node_id::{CRATE_NODE_ID, DUMMY_NODE_ID, NodeId}; /// Modifiers on a trait bound like `~const`, `?` and `!`. @@ -2165,6 +2167,14 @@ impl Ty { } final_ty } + + pub fn is_maybe_parenthesised_infer(&self) -> bool { + match &self.kind { + TyKind::Infer => true, + TyKind::Paren(inner) => inner.ast_deref().is_maybe_parenthesised_infer(), + _ => false, + } + } } #[derive(Clone, Encodable, Decodable, Debug)] @@ -2269,10 +2279,32 @@ impl TyKind { /// Syntax used to declare a trait object. #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] +#[repr(u8)] pub enum TraitObjectSyntax { - Dyn, - DynStar, - None, + // SAFETY: When adding new variants make sure to update the `Tag` impl. + Dyn = 0, + DynStar = 1, + None = 2, +} + +/// SAFETY: `TraitObjectSyntax` only has 3 data-less variants which means +/// it can be represented with a `u2`. We use `repr(u8)` to guarantee the +/// discriminants of the variants are no greater than `3`. +unsafe impl Tag for TraitObjectSyntax { + const BITS: u32 = 2; + + fn into_usize(self) -> usize { + self as u8 as usize + } + + unsafe fn from_usize(tag: usize) -> Self { + match tag { + 0 => TraitObjectSyntax::Dyn, + 1 => TraitObjectSyntax::DynStar, + 2 => TraitObjectSyntax::None, + _ => unreachable!(), + } + } } #[derive(Clone, Encodable, Decodable, Debug)] diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index 51f18580013..df2f4b88712 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -302,7 +302,7 @@ impl AttrItem { impl MetaItem { /// For a single-segment meta item, returns its name; otherwise, returns `None`. pub fn ident(&self) -> Option<Ident> { - if self.path.segments.len() == 1 { Some(self.path.segments[0].ident) } else { None } + if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None } } pub fn name_or_empty(&self) -> Symbol { diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs index ab1413d6080..12cbb3b2a15 100644 --- a/compiler/rustc_ast/src/entry.rs +++ b/compiler/rustc_ast/src/entry.rs @@ -18,12 +18,6 @@ pub enum EntryPointType { /// fn main() {} /// ``` RustcMainAttr, - /// This is a function with the `#[start]` attribute. - /// ```ignore (clashes with test entrypoint) - /// #[start] - /// fn main() {} - /// ``` - Start, /// This function is **not** an entrypoint but simply named `main` (not at the root). /// This is only used for diagnostics. /// ``` @@ -40,9 +34,7 @@ pub fn entry_point_type( at_root: bool, name: Option<Symbol>, ) -> EntryPointType { - if attr::contains_name(attrs, sym::start) { - EntryPointType::Start - } else if attr::contains_name(attrs, sym::rustc_main) { + if attr::contains_name(attrs, sym::rustc_main) { EntryPointType::RustcMainAttr } else if let Some(name) = name && name == sym::main diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index aa88e8369d5..3459d39131a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1813,10 +1813,10 @@ pub fn walk_flat_map_stmt<T: MutVisitor>( .into_iter() .map(|kind| Stmt { id, kind, span }) .collect(); - match stmts.len() { - 0 => {} - 1 => vis.visit_span(&mut stmts[0].span), - 2.. => panic!( + match &mut stmts[..] { + [] => {} + [stmt] => vis.visit_span(&mut stmt.span), + _ => panic!( "cloning statement `NodeId`s is prohibited by default, \ the visitor should implement custom statement visiting" ), diff --git a/compiler/rustc_ast/src/util/comments.rs b/compiler/rustc_ast/src/util/comments.rs index f39142f08ba..e12818623d8 100644 --- a/compiler/rustc_ast/src/util/comments.rs +++ b/compiler/rustc_ast/src/util/comments.rs @@ -39,7 +39,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { let mut i = 0; let mut j = lines.len(); // first line of all-stars should be omitted - if !lines.is_empty() && lines[0].chars().all(|c| c == '*') { + if lines.first().is_some_and(|line| line.chars().all(|c| c == '*')) { i += 1; } @@ -97,7 +97,7 @@ pub fn beautify_doc_string(data: Symbol, kind: CommentKind) -> Symbol { return None; } } - if lines.is_empty() { None } else { Some(lines[0][..i].into()) } + Some(lines.first()?[..i].to_string()) } let data_s = data.as_str(); diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 266e77c0e02..f9fe4938ca8 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -72,7 +72,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if let Some(local_sig_id) = def_id.as_local() { // The value may be missing due to recursive delegation. // Error will be emitted later during HIR ty lowering. - self.resolver.delegation_fn_sigs.get(&local_sig_id).map_or(false, |sig| sig.has_self) + self.resolver.delegation_fn_sigs.get(&local_sig_id).is_some_and(|sig| sig.has_self) } else { match self.tcx.def_kind(def_id) { DefKind::Fn => false, diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index a76ca6772e5..f31e2c65c79 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -2159,7 +2159,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let path = hir::ExprKind::Path(hir::QPath::TypeRelative( self.arena.alloc(self.ty(span, hir::TyKind::Path(qpath))), self.arena.alloc(hir::PathSegment::new( - Ident::new(name, span), + Ident::new(name, self.lower_span(span)), self.next_id(), Res::Err, )), diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 29d4fb9ef25..f8fb21d5cd0 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -1,3 +1,4 @@ +use intravisit::InferKind; use rustc_data_structures::sorted_map::SortedMap; use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap}; @@ -78,24 +79,31 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { // Make sure that the DepNode of some node coincides with the HirId // owner of that node. - if cfg!(debug_assertions) && hir_id.owner != self.owner { - span_bug!( - span, - "inconsistent HirId at `{:?}` for `{:?}`: \ + if cfg!(debug_assertions) { + if hir_id.owner != self.owner { + span_bug!( + span, + "inconsistent HirId at `{:?}` for `{node:?}`: \ current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})", - self.tcx.sess.source_map().span_to_diagnostic_string(span), - node, - self.tcx - .definitions_untracked() - .def_path(self.owner.def_id) - .to_string_no_crate_verbose(), - self.owner, - self.tcx - .definitions_untracked() - .def_path(hir_id.owner.def_id) - .to_string_no_crate_verbose(), - hir_id.owner, - ) + self.tcx.sess.source_map().span_to_diagnostic_string(span), + self.tcx + .definitions_untracked() + .def_path(self.owner.def_id) + .to_string_no_crate_verbose(), + self.owner, + self.tcx + .definitions_untracked() + .def_path(hir_id.owner.def_id) + .to_string_no_crate_verbose(), + hir_id.owner, + ) + } + if self.tcx.sess.opts.incremental.is_some() + && span.parent().is_none() + && !span.is_dummy() + { + span_bug!(span, "span without a parent: {:#?}, {node:?}", span.data()) + } } self.nodes[hir_id.local_id] = ParentedNode { parent: self.parent_node, node }; @@ -258,14 +266,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { }); } - fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir>) { - self.insert(const_arg.span(), const_arg.hir_id, Node::ConstArg(const_arg)); - - self.with_parent(const_arg.hir_id, |this| { - intravisit::walk_const_arg(this, const_arg); - }); - } - fn visit_expr(&mut self, expr: &'hir Expr<'hir>) { self.insert(expr.span, expr.hir_id, Node::Expr(expr)); @@ -295,22 +295,41 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { intravisit::walk_path_segment(self, path_segment); } - fn visit_ty(&mut self, ty: &'hir Ty<'hir>) { - self.insert(ty.span, ty.hir_id, Node::Ty(ty)); + fn visit_ty(&mut self, ty: &'hir Ty<'hir, AmbigArg>) { + self.insert(ty.span, ty.hir_id, Node::Ty(ty.as_unambig_ty())); self.with_parent(ty.hir_id, |this| { intravisit::walk_ty(this, ty); }); } - fn visit_infer(&mut self, inf: &'hir InferArg) { - self.insert(inf.span, inf.hir_id, Node::Infer(inf)); + fn visit_const_arg(&mut self, const_arg: &'hir ConstArg<'hir, AmbigArg>) { + self.insert( + const_arg.as_unambig_ct().span(), + const_arg.hir_id, + Node::ConstArg(const_arg.as_unambig_ct()), + ); - self.with_parent(inf.hir_id, |this| { - intravisit::walk_inf(this, inf); + self.with_parent(const_arg.hir_id, |this| { + intravisit::walk_ambig_const_arg(this, const_arg); }); } + fn visit_infer( + &mut self, + inf_id: HirId, + inf_span: Span, + kind: InferKind<'hir>, + ) -> Self::Result { + match kind { + InferKind::Ty(ty) => self.insert(inf_span, inf_id, Node::Ty(ty)), + InferKind::Const(ct) => self.insert(inf_span, inf_id, Node::ConstArg(ct)), + InferKind::Ambig(inf) => self.insert(inf_span, inf_id, Node::Infer(inf)), + } + + self.visit_id(inf_id); + } + fn visit_trait_ref(&mut self, tr: &'hir TraitRef<'hir>) { self.insert(tr.path.span, tr.hir_ref_id, Node::TraitRef(tr)); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 61d7da429f8..74870d74150 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1092,6 +1092,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // this as a special case. return self.lower_fn_body(decl, |this| { if attrs.iter().any(|a| a.name_or_empty() == sym::rustc_intrinsic) { + let span = this.lower_span(span); let empty_block = hir::Block { hir_id: this.next_id(), stmts: &[], diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 0e28590bd66..b9f1a4220b8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -48,6 +48,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; @@ -1083,17 +1084,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)), ast::GenericArg::Type(ty) => { + // We cannot just match on `TyKind::Infer` as `(_)` is represented as + // `TyKind::Paren(TyKind::Infer)` and should also be lowered to `GenericArg::Infer` + if ty.is_maybe_parenthesised_infer() { + return GenericArg::Infer(hir::InferArg { + hir_id: self.lower_node_id(ty.id), + span: self.lower_span(ty.span), + }); + } + match &ty.kind { - TyKind::Infer if self.tcx.features().generic_arg_infer() => { - return GenericArg::Infer(hir::InferArg { - hir_id: self.lower_node_id(ty.id), - span: self.lower_span(ty.span), - }); - } // We parse const arguments as path types as we cannot distinguish them during // parsing. We try to resolve that ambiguity by attempting resolution in both the // type and value namespaces. If we resolved the path in the value namespace, we // transform it into a generic const argument. + // + // FIXME: Should we be handling `(PATH_TO_CONST)`? TyKind::Path(None, path) => { if let Some(res) = self .resolver @@ -1110,15 +1116,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let ct = self.lower_const_path_to_const_arg(path, res, ty.id, ty.span); - return GenericArg::Const(ct); + return GenericArg::Const(ct.try_as_ambig_ct().unwrap()); } } } _ => {} } - GenericArg::Type(self.lower_ty(ty, itctx)) + GenericArg::Type(self.lower_ty(ty, itctx).try_as_ambig_ty().unwrap()) + } + ast::GenericArg::Const(ct) => { + GenericArg::Const(self.lower_anon_const_to_const_arg(ct).try_as_ambig_ct().unwrap()) } - ast::GenericArg::Const(ct) => GenericArg::Const(self.lower_anon_const_to_const_arg(ct)), } } @@ -1158,7 +1166,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let lifetime_bound = this.elided_dyn_bound(t.span); (bounds, lifetime_bound) }); - let kind = hir::TyKind::TraitObject(bounds, lifetime_bound, TraitObjectSyntax::None); + let kind = hir::TyKind::TraitObject( + bounds, + TaggedRef::new(lifetime_bound, TraitObjectSyntax::None), + ); return hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.next_id() }; } @@ -1185,7 +1196,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> { let kind = match &t.kind { - TyKind::Infer => hir::TyKind::Infer, + TyKind::Infer => hir::TyKind::Infer(()), TyKind::Err(guar) => hir::TyKind::Err(*guar), TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), @@ -1309,7 +1320,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); (bounds, lifetime_bound) }); - hir::TyKind::TraitObject(bounds, lifetime_bound, *kind) + hir::TyKind::TraitObject(bounds, TaggedRef::new(lifetime_bound, *kind)) } TyKind::ImplTrait(def_node_id, bounds) => { let span = t.span; @@ -2041,7 +2052,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) .stash(c.value.span, StashKey::UnderscoreForArrayLengths); } - let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span)); + let ct_kind = hir::ConstArgKind::Infer(self.lower_span(c.value.span), ()); self.arena.alloc(hir::ConstArg { hir_id: self.lower_node_id(c.id), kind: ct_kind }) } _ => self.lower_anon_const_to_const_arg(c), @@ -2365,8 +2376,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir_id = self.next_id(); hir::TyKind::TraitObject( arena_vec![self; principal], - self.elided_dyn_bound(span), - TraitObjectSyntax::None, + TaggedRef::new(self.elided_dyn_bound(span), TraitObjectSyntax::None), ) } _ => hir::TyKind::Path(hir::QPath::Resolved(None, path)), diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index abd314ae74c..3c78ed0497d 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -375,24 +375,24 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { expr: &Expr, allow_paths: bool, ) -> &'hir hir::PatExpr<'hir> { + let span = self.lower_span(expr.span); let err = |guar| hir::PatExprKind::Lit { - lit: self.arena.alloc(respan(self.lower_span(expr.span), LitKind::Err(guar))), + lit: self.arena.alloc(respan(span, LitKind::Err(guar))), negated: false, }; let kind = match &expr.kind { ExprKind::Lit(lit) => { - hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: false } + hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: false } } ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)), ExprKind::IncludedBytes(bytes) => hir::PatExprKind::Lit { - lit: self.arena.alloc(respan( - self.lower_span(expr.span), - LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked), - )), + lit: self + .arena + .alloc(respan(span, LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked))), negated: false, }, ExprKind::Err(guar) => err(*guar), - ExprKind::Dummy => span_bug!(expr.span, "lowered ExprKind::Dummy"), + ExprKind::Dummy => span_bug!(span, "lowered ExprKind::Dummy"), ExprKind::Path(qself, path) if allow_paths => hir::PatExprKind::Path(self.lower_qpath( expr.id, qself, @@ -403,21 +403,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None, )), ExprKind::Unary(UnOp::Neg, inner) if let ExprKind::Lit(lit) = &inner.kind => { - hir::PatExprKind::Lit { lit: self.lower_lit(lit, expr.span), negated: true } + hir::PatExprKind::Lit { lit: self.lower_lit(lit, span), negated: true } } _ => { let pattern_from_macro = expr.is_approximately_pattern(); let guar = self.dcx().emit_err(ArbitraryExpressionInPattern { - span: expr.span, + span, pattern_from_macro_note: pattern_from_macro, }); err(guar) } }; - self.arena.alloc(hir::PatExpr { - hir_id: self.lower_node_id(expr.id), - span: expr.span, - kind, - }) + self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind }) } } diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs index 043144a5464..75abff7461b 100644 --- a/compiler/rustc_ast_lowering/src/path.rs +++ b/compiler/rustc_ast_lowering/src/path.rs @@ -525,7 +525,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])), }; - let args = smallvec![GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span, inputs)))]; + let args = smallvec![GenericArg::Type( + self.arena.alloc(self.ty_tup(*inputs_span, inputs)).try_as_ambig_ty().unwrap() + )]; // If we have a bound like `async Fn() -> T`, make sure that we mark the // `Output = T` associated type bound with the right feature gates. diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 94746212138..80b99f94485 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -83,7 +83,7 @@ impl<'a> PostExpansionVisitor<'a> { feature_err_issue(&self.sess, feature, span, GateIssue::Language, explain).emit(); } Err(abi::AbiDisabled::Unrecognized) => { - if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) { + if self.sess.opts.pretty.is_none_or(|ppm| ppm.needs_hir()) { self.sess.dcx().span_delayed_bug( span, format!( @@ -230,18 +230,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - ast::ItemKind::Fn(..) => { - if attr::contains_name(&i.attrs, sym::start) { - gate!( - &self, - start, - i.span, - "`#[start]` functions are experimental and their signature may change \ - over time" - ); - } - } - ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) => { for attr in attr::filter_by_name(&i.attrs, sym::repr) { for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) { diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index def6b16ee8a..b4027a096c5 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -35,13 +35,25 @@ pub enum InstructionSetAttr { ArmT32, } -#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)] +#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, HashStable_Generic, Default)] pub enum OptimizeAttr { - None, + /// No `#[optimize(..)]` attribute + #[default] + Default, + /// `#[optimize(none)]` + DoNotOptimize, + /// `#[optimize(speed)]` Speed, + /// `#[optimize(size)]` Size, } +impl OptimizeAttr { + pub fn do_not_optimize(&self) -> bool { + matches!(self, Self::DoNotOptimize) + } +} + #[derive(Clone, Debug, Encodable, Decodable)] pub enum DiagnosticAttribute { // tidy-alphabetical-start diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 124f0aa3eff..28c381160b8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -166,7 +166,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &impl AttributeExt) -> Vec<ReprAttr // the `check_mod_attrs` pass, but this pass doesn't always run // (e.g. if we only pretty-print the source), so we have to gate // the `span_delayed_bug` call as follows: - if sess.opts.pretty.map_or(true, |pp| pp.needs_analysis()) { + if sess.opts.pretty.is_none_or(|pp| pp.needs_analysis()) { dcx.span_delayed_bug(item.span(), "unrecognized representation hint"); } } diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index ada20e5c614..c00e6dde919 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -92,6 +92,9 @@ borrowck_lifetime_constraints_error = borrowck_limitations_implies_static = due to current limitations in the borrow checker, this implies a `'static` lifetime +borrowck_long_type_consider_verbose = consider using `--verbose` to print the full type name to the console +borrowck_long_type_full_path = the full type name has been written to '{$path}' + borrowck_move_closure_suggestion = consider adding 'move' keyword before the nested closure diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index da59f9f9ebd..07dcbba019a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -39,7 +39,9 @@ use rustc_trait_selection::error_reporting::traits::FindExprBySpan; use rustc_trait_selection::error_reporting::traits::call_kind::CallKind; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; -use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; +use rustc_trait_selection::traits::{ + Obligation, ObligationCause, ObligationCtxt, supertrait_def_ids, +}; use tracing::{debug, instrument}; use super::explain_borrow::{BorrowExplanation, LaterUseKind}; @@ -287,6 +289,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { None => "value".to_owned(), }; if needs_note { + let mut path = None; + let ty = self.infcx.tcx.short_ty_string(ty, &mut path); if let Some(local) = place.as_local() { let span = self.body.local_decls[local].source_info.span; err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { @@ -302,6 +306,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { place: ¬e_msg, }); }; + if let Some(path) = path { + err.subdiagnostic(crate::session_diagnostics::LongTypePath { + path: path.display().to_string(), + }); + } } if let UseSpans::FnSelfUse { @@ -658,8 +667,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { clause.as_trait_clause().is_some_and(|tc| { tc.self_ty().skip_binder().is_param(param.index) && tc.polarity() == ty::PredicatePolarity::Positive - && tcx - .supertrait_def_ids(tc.def_id()) + && supertrait_def_ids(tcx, tc.def_id()) .flat_map(|trait_did| tcx.associated_items(trait_did).in_definition_order()) .any(|item| item.fn_has_self_parameter) }) @@ -2480,7 +2488,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // To support cases like `|| { v.call(|this| v.get()) }` // FIXME: actually support such cases (need to figure out how to move from the // capture place to original local). - && self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span)) + && self.res.as_ref().is_none_or(|(prev_res, _)| prev_res.span.contains(ex.span)) { self.res = Some((ex, closure)); } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 5c0c1d0eb86..2656e0bb6a4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -131,10 +131,10 @@ impl<'tcx> BorrowExplanation<'tcx> { && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span) { suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err); - } else if path_span.map_or(true, |path_span| path_span == var_or_use_span) { + } else if path_span.is_none_or(|path_span| path_span == var_or_use_span) { // We can use `var_or_use_span` if either `path_span` is not present, or both // spans are the same. - if borrow_span.map_or(true, |sp| !sp.overlaps(var_or_use_span)) { + if borrow_span.is_none_or(|sp| !sp.overlaps(var_or_use_span)) { err.span_label( var_or_use_span, format!("{borrow_desc}borrow later {message}"), diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index beacbdbd3fa..14a900f38e9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -596,12 +596,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, place_ty, expr, None); } + let mut path = None; + let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty: place_ty, + ty, place: &place_desc, span, }); + if let Some(path) = path { + err.subdiagnostic(crate::session_diagnostics::LongTypePath { + path: path.display().to_string(), + }); + } } else { binds_to.sort(); binds_to.dedup(); @@ -628,12 +635,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, place_ty, expr, Some(use_spans)); } + let mut path = None; + let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty: place_ty, + ty, place: &place_desc, span: use_span, }); + if let Some(path) = path { + err.subdiagnostic(crate::session_diagnostics::LongTypePath { + path: path.display().to_string(), + }); + } use_spans.args_subdiag(err, |args_span| { crate::session_diagnostics::CaptureArgLabel::MoveOutPlace { @@ -831,12 +845,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, bind_to.ty, expr, None); } + let mut path = None; + let ty = self.infcx.tcx.short_ty_string(bind_to.ty, &mut path); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty: bind_to.ty, + ty, place: place_desc, span: binding_span, }); + if let Some(path) = path { + err.subdiagnostic(crate::session_diagnostics::LongTypePath { + path: path.display().to_string(), + }); + } } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index f0baa20648c..3c4e4c29197 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -8,7 +8,7 @@ use rustc_hir::QPath::Resolved; use rustc_hir::WherePredicateKind::BoundPredicate; use rustc_hir::def::Res::Def; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::VisitorExt; use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate}; use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound}; use rustc_middle::bug; @@ -887,7 +887,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if alias_ty.span.desugaring_kind().is_some() { // Skip `async` desugaring `impl Future`. } - if let TyKind::TraitObject(_, lt, _) = alias_ty.kind { + if let TyKind::TraitObject(_, lt) = alias_ty.kind { if lt.ident.name == kw::Empty { spans_suggs.push((lt.ident.span.shrink_to_hi(), " + 'a".to_string())); } else { @@ -987,7 +987,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { for found_did in found_dids { let mut traits = vec![]; let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); - hir_v.visit_ty(self_ty); + hir_v.visit_ty_unambig(self_ty); debug!("trait spans found: {:?}", traits); for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 9349b46ec5b..ccd13badad7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -432,7 +432,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // must highlight the variable. // NOTE(eddyb) this is handled in/by the sole caller // (`give_name_if_anonymous_region_appears_in_arguments`). - hir::TyKind::Infer => None, + hir::TyKind::Infer(()) => None, _ => Some(argument_hir_ty), } @@ -615,7 +615,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } (GenericArgKind::Type(ty), hir::GenericArg::Type(hir_ty)) => { - search_stack.push((ty, hir_ty)); + search_stack.push((ty, hir_ty.as_unambig_ty())); } (GenericArgKind::Const(_ct), hir::GenericArg::Const(_hir_ct)) => { diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index a6d80149034..40e801d0388 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -1,7 +1,9 @@ use std::io; -use rustc_middle::mir::pretty::{PrettyPrintMirOptions, dump_mir_with_options}; -use rustc_middle::mir::{Body, ClosureRegionRequirements, PassWhere}; +use rustc_middle::mir::pretty::{ + PassWhere, PrettyPrintMirOptions, create_dump_file, dump_enabled, dump_mir_to_writer, +}; +use rustc_middle::mir::{Body, ClosureRegionRequirements}; use rustc_middle::ty::TyCtxt; use rustc_session::config::MirIncludeSpans; @@ -10,9 +12,6 @@ use crate::polonius::{LocalizedOutlivesConstraint, LocalizedOutlivesConstraintSe use crate::{BorrowckInferCtxt, RegionInferenceContext}; /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information. -// Note: this currently duplicates most of NLL MIR, with some additions for the localized outlives -// constraints. This is ok for now as this dump will change in the near future to an HTML file to -// become more useful. pub(crate) fn dump_polonius_mir<'tcx>( infcx: &BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, @@ -26,12 +25,100 @@ pub(crate) fn dump_polonius_mir<'tcx>( return; } + if !dump_enabled(tcx, "polonius", body.source.def_id()) { + return; + } + let localized_outlives_constraints = localized_outlives_constraints .expect("missing localized constraints with `-Zpolonius=next`"); - // We want the NLL extra comments printed by default in NLL MIR dumps (they were removed in - // #112346). Specifying `-Z mir-include-spans` on the CLI still has priority: for example, - // they're always disabled in mir-opt tests to make working with blessed dumps easier. + let _: io::Result<()> = try { + let mut file = create_dump_file(tcx, "html", false, "polonius", &0, body)?; + emit_polonius_dump( + tcx, + body, + regioncx, + borrow_set, + localized_outlives_constraints, + closure_region_requirements, + &mut file, + )?; + }; +} + +/// The polonius dump consists of: +/// - the NLL MIR +/// - the list of polonius localized constraints +/// - a mermaid graph of the CFG +fn emit_polonius_dump<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + regioncx: &RegionInferenceContext<'tcx>, + borrow_set: &BorrowSet<'tcx>, + localized_outlives_constraints: LocalizedOutlivesConstraintSet, + closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>, + out: &mut dyn io::Write, +) -> io::Result<()> { + // Prepare the HTML dump file prologue. + writeln!(out, "<!DOCTYPE html>")?; + writeln!(out, "<html>")?; + writeln!(out, "<head><title>Polonius MIR dump</title></head>")?; + writeln!(out, "<body>")?; + + // Section 1: the NLL + Polonius MIR. + writeln!(out, "<div>")?; + writeln!(out, "Raw MIR dump")?; + writeln!(out, "<code><pre>")?; + emit_html_mir( + tcx, + body, + regioncx, + borrow_set, + localized_outlives_constraints, + closure_region_requirements, + out, + )?; + writeln!(out, "</pre></code>")?; + writeln!(out, "</div>")?; + + // Section 2: mermaid visualization of the CFG. + writeln!(out, "<div>")?; + writeln!(out, "Control-flow graph")?; + writeln!(out, "<code><pre class='mermaid'>")?; + emit_mermaid_cfg(body, out)?; + writeln!(out, "</pre></code>")?; + writeln!(out, "</div>")?; + + // Finalize the dump with the HTML epilogue. + writeln!( + out, + "<script src='https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js'></script>" + )?; + writeln!(out, "<script>")?; + writeln!(out, "mermaid.initialize({{ startOnLoad: false, maxEdges: 100 }});")?; + writeln!(out, "mermaid.run({{ querySelector: '.mermaid' }})")?; + writeln!(out, "</script>")?; + writeln!(out, "</body>")?; + writeln!(out, "</html>")?; + + Ok(()) +} + +/// Emits the polonius MIR, as escaped HTML. +fn emit_html_mir<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + regioncx: &RegionInferenceContext<'tcx>, + borrow_set: &BorrowSet<'tcx>, + localized_outlives_constraints: LocalizedOutlivesConstraintSet, + closure_region_requirements: &Option<ClosureRegionRequirements<'tcx>>, + out: &mut dyn io::Write, +) -> io::Result<()> { + // Buffer the regular MIR dump to be able to escape it. + let mut buffer = Vec::new(); + + // We want the NLL extra comments printed by default in NLL MIR dumps. Specifying `-Z + // mir-include-spans` on the CLI still has priority. let options = PrettyPrintMirOptions { include_extra_comments: matches!( tcx.sess.opts.unstable_opts.mir_include_spans, @@ -39,12 +126,12 @@ pub(crate) fn dump_polonius_mir<'tcx>( ), }; - dump_mir_with_options( + dump_mir_to_writer( tcx, - false, "polonius", &0, body, + &mut buffer, |pass_where, out| { emit_polonius_mir( tcx, @@ -57,7 +144,27 @@ pub(crate) fn dump_polonius_mir<'tcx>( ) }, options, - ); + )?; + + // Escape the handful of characters that need it. We don't need to be particularly efficient: + // we're actually writing into a buffered writer already. Note that MIR dumps are valid UTF-8. + let buffer = String::from_utf8_lossy(&buffer); + for ch in buffer.chars() { + let escaped = match ch { + '>' => ">", + '<' => "<", + '&' => "&", + '\'' => "'", + '"' => """, + _ => { + // The common case, no escaping needed. + write!(out, "{}", ch)?; + continue; + } + }; + write!(out, "{}", escaped)?; + } + Ok(()) } /// Produces the actual NLL + Polonius MIR sections to emit during the dumping process. @@ -102,3 +209,55 @@ fn emit_polonius_mir<'tcx>( Ok(()) } + +/// Emits a mermaid flowchart of the CFG blocks and edges, similar to the graphviz version. +fn emit_mermaid_cfg(body: &Body<'_>, out: &mut dyn io::Write) -> io::Result<()> { + use rustc_middle::mir::{TerminatorEdges, TerminatorKind}; + + // The mermaid chart type: a top-down flowchart. + writeln!(out, "flowchart TD")?; + + // Emit the block nodes. + for (block_idx, block) in body.basic_blocks.iter_enumerated() { + let block_idx = block_idx.as_usize(); + let cleanup = if block.is_cleanup { " (cleanup)" } else { "" }; + writeln!(out, "{block_idx}[\"bb{block_idx}{cleanup}\"]")?; + } + + // Emit the edges between blocks, from the terminator edges. + for (block_idx, block) in body.basic_blocks.iter_enumerated() { + let block_idx = block_idx.as_usize(); + let terminator = block.terminator(); + match terminator.edges() { + TerminatorEdges::None => {} + TerminatorEdges::Single(bb) => { + writeln!(out, "{block_idx} --> {}", bb.as_usize())?; + } + TerminatorEdges::Double(bb1, bb2) => { + if matches!(terminator.kind, TerminatorKind::FalseEdge { .. }) { + writeln!(out, "{block_idx} --> {}", bb1.as_usize())?; + writeln!(out, "{block_idx} -- imaginary --> {}", bb2.as_usize())?; + } else { + writeln!(out, "{block_idx} --> {}", bb1.as_usize())?; + writeln!(out, "{block_idx} -- unwind --> {}", bb2.as_usize())?; + } + } + TerminatorEdges::AssignOnReturn { return_, cleanup, .. } => { + for to_idx in return_ { + writeln!(out, "{block_idx} --> {}", to_idx.as_usize())?; + } + + if let Some(to_idx) = cleanup { + writeln!(out, "{block_idx} -- unwind --> {}", to_idx.as_usize())?; + } + } + TerminatorEdges::SwitchInt { targets, .. } => { + for to_idx in targets.all_targets() { + writeln!(out, "{block_idx} --> {}", to_idx.as_usize())?; + } + } + } + } + + Ok(()) +} diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 4be5d0dbf42..2c37d2bc123 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -459,17 +459,24 @@ pub(crate) enum OnClosureNote<'a> { } #[derive(Subdiagnostic)] -pub(crate) enum TypeNoCopy<'a, 'tcx> { +#[note(borrowck_long_type_full_path)] +#[note(borrowck_long_type_consider_verbose)] +pub(crate) struct LongTypePath { + pub(crate) path: String, +} + +#[derive(Subdiagnostic)] +pub(crate) enum TypeNoCopy<'a> { #[label(borrowck_ty_no_impl_copy)] Label { is_partial_move: bool, - ty: Ty<'tcx>, + ty: String, place: &'a str, #[primary_span] span: Span, }, #[note(borrowck_ty_no_impl_copy)] - Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, + Note { is_partial_move: bool, ty: String, place: &'a str }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 3903c45fda5..bffd9f38334 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -185,7 +185,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CustomTypeOp::new( |ocx| { let structurally_normalize = |ty| { - ocx.structurally_normalize( + ocx.structurally_normalize_ty( &ObligationCause::misc( location.to_locations().span(body), body.source.def_id().expect_local(), @@ -230,7 +230,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Boring, CustomTypeOp::new( |ocx| { - ocx.structurally_normalize( + ocx.structurally_normalize_ty( &ObligationCause::misc( location.to_locations().span(body), body.source.def_id().expect_local(), diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 49706db0e0b..82417a86dd9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -157,7 +157,7 @@ pub(crate) fn expand_deriving_coerce_pointee( { cx.dcx().emit_err(RequiresMaybeSized { span: pointee_ty_ident.span, - name: pointee_ty_ident.name.to_ident_string(), + name: pointee_ty_ident, }); return; } @@ -471,5 +471,5 @@ struct TooManyPointees { struct RequiresMaybeSized { #[primary_span] span: Span, - name: String, + name: Ident, } diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 6071d36f8eb..0918403b855 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -16,6 +16,7 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![feature(rustdoc_internals)] +#![feature(string_from_utf8_lossy_owned)] #![feature(try_blocks)] #![warn(unreachable_pub)] // tidy-alphabetical-end diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 123b96f6bca..d163da3ddea 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -13,7 +13,7 @@ use rustc_expand::base::{ use rustc_expand::module::DirOwnership; use rustc_lint_defs::BuiltinLintDiag; use rustc_parse::parser::{ForceCollect, Parser}; -use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal}; +use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal, utf8_error}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::source_map::SourceMap; use rustc_span::{Pos, Span, Symbol}; @@ -209,9 +209,10 @@ pub(crate) fn expand_include_str( let interned_src = Symbol::intern(src); MacEager::expr(cx.expr_str(cx.with_def_site_ctxt(bsp), interned_src)) } - Err(_) => { - let guar = cx.dcx().span_err(sp, format!("`{path}` wasn't a utf-8 file")); - DummyResult::any(sp, guar) + Err(utf8err) => { + let mut err = cx.dcx().struct_span_err(sp, format!("`{path}` wasn't a utf-8 file")); + utf8_error(cx.source_map(), path.as_str(), None, &mut err, utf8err, &bytes[..]); + DummyResult::any(sp, err.emit()) } }, Err(dummy) => dummy, @@ -273,7 +274,7 @@ fn load_binary_file( .and_then(|path| path.into_os_string().into_string().ok()); if let Some(new_path) = new_path { - err.span_suggestion( + err.span_suggestion_verbose( path_span, "there is a file with the same name in a different directory", format!("\"{}\"", new_path.replace('\\', "/").escape_debug()), diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 46446598943..31b068bd33d 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -204,11 +204,11 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { ast::mut_visit::walk_item(self, item); self.depth -= 1; - // Remove any #[rustc_main] or #[start] from the AST so it doesn't + // Remove any #[rustc_main] from the AST so it doesn't // clash with the one we're going to add, but mark it as // #[allow(dead_code)] to avoid printing warnings. match entry_point_type(&item, self.depth == 0) { - EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => { + EntryPointType::MainNamed | EntryPointType::RustcMainAttr => { let allow_dead_code = attr::mk_attr_nested_word( &self.sess.psess.attr_id_generator, ast::AttrStyle::Outer, @@ -217,8 +217,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> { sym::dead_code, self.def_site, ); - item.attrs - .retain(|attr| !attr.has_name(sym::rustc_main) && !attr.has_name(sym::start)); + item.attrs.retain(|attr| !attr.has_name(sym::rustc_main)); item.attrs.push(allow_dead_code); } EntryPointType::None | EntryPointType::OtherMain => {} diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index 8de419a0c4e..bcb2b4881eb 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -151,7 +151,7 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ apply_patches( &runner.dirs, "coretests", - &runner.stdlib_source.join("library/core/tests"), + &runner.stdlib_source.join("library/coretests"), &LIBCORE_TESTS_SRC.to_path(&runner.dirs), ); diff --git a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch deleted file mode 100644 index 161173d4765..00000000000 --- a/compiler/rustc_codegen_cranelift/patches/0022-coretests-Disable-not-compiling-tests.patch +++ /dev/null @@ -1,44 +0,0 @@ -From f6befc4bb51d84f5f1cf35938a168c953d421350 Mon Sep 17 00:00:00 2001 -From: bjorn3 <bjorn3@users.noreply.github.com> -Date: Sun, 24 Nov 2019 15:10:23 +0100 -Subject: [PATCH] [core] Disable not compiling tests - ---- - library/core/tests/Cargo.toml | 8 ++++++++ - library/core/tests/num/flt2dec/mod.rs | 1 - - library/core/tests/num/int_macros.rs | 2 ++ - library/core/tests/num/uint_macros.rs | 2 ++ - library/core/tests/ptr.rs | 2 ++ - library/core/tests/slice.rs | 2 ++ - 6 files changed, 16 insertions(+), 1 deletion(-) - create mode 100644 library/core/tests/Cargo.toml - -diff --git a/Cargo.toml b/Cargo.toml -new file mode 100644 -index 0000000..46fd999 ---- /dev/null -+++ b/Cargo.toml -@@ -0,0 +1,12 @@ -+[package] -+name = "coretests" -+version = "0.0.0" -+edition = "2021" -+ -+[lib] -+name = "coretests" -+path = "lib.rs" -+ -+[dependencies] -+rand = { version = "0.8.5", default-features = false } -+rand_xorshift = { version = "0.3.0", default-features = false } -diff --git a/lib.rs b/lib.rs -index 42a26ae..5ac1042 100644 ---- a/lib.rs -+++ b/lib.rs -@@ -1,3 +1,4 @@ -+#![cfg(test)] - // tidy-alphabetical-start - #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] - #![cfg_attr(test, feature(cfg_match))] --- -2.21.0 (Apple Git-122) diff --git a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch index 06840624cef..4a06dc3f7ef 100644 --- a/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch +++ b/compiler/rustc_codegen_cranelift/patches/0027-coretests-128bit-atomic-operations.patch @@ -10,21 +10,20 @@ Cranelift doesn't support them yet library/core/tests/atomic.rs | 4 --- 4 files changed, 4 insertions(+), 50 deletions(-) -diff --git a/lib.rs b/lib.rs +diff --git a/tests/lib.rs b/tests/lib.rs index 1e336bf..35e6f54 100644 ---- a/lib.rs -+++ b/lib.rs -@@ -2,6 +2,5 @@ - #![cfg(test)] +--- a/tests/lib.rs ++++ b/tests/lib.rs +@@ -2,5 +2,4 @@ // tidy-alphabetical-start -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] #![feature(array_chunks)] -diff --git a/atomic.rs b/atomic.rs +diff --git a/tests/atomic.rs b/tests/atomic.rs index b735957..ea728b6 100644 ---- a/atomic.rs -+++ b/atomic.rs +--- a/tests/atomic.rs ++++ b/tests/atomic.rs @@ -185,10 +185,6 @@ fn atomic_alignment() { assert_eq!(align_of::<AtomicU64>(), size_of::<AtomicU64>()); #[cfg(target_has_atomic = "64")] diff --git a/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch b/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch index b98326c54a6..5a38dffa24f 100644 --- a/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch +++ b/compiler/rustc_codegen_cranelift/patches/0028-coretests-Disable-long-running-tests.patch @@ -7,10 +7,10 @@ Subject: [PATCH] Disable long running tests library/core/tests/slice.rs | 2 ++ 1 file changed, 2 insertions(+) -diff --git a/slice.rs b/slice.rs +diff --git a/tests/slice.rs b/tests/slice.rs index 8402833..84592e0 100644 ---- a/slice.rs -+++ b/slice.rs +--- a/tests/slice.rs ++++ b/tests/slice.rs @@ -1809,6 +1809,7 @@ fn sort_unstable() { } } diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain index e4c3dd708fd..9c6aad3490d 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain +++ b/compiler/rustc_codegen_cranelift/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2025-01-10" +channel = "nightly-2025-01-20" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index e569da90cf7..41aa011e805 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -176,12 +176,11 @@ diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-supp index 9607ff02f96..b7d97caf9a2 100644 --- a/src/tools/run-make-support/src/external_deps/rustdoc.rs +++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs -@@ -34,8 +34,6 @@ pub fn bare() -> Self { +@@ -34,7 +34,6 @@ pub fn bare() -> Self { #[track_caller] pub fn new() -> Self { let mut cmd = setup_common(); -- let target_rpath_dir = env_var_os("TARGET_RPATH_DIR"); -- cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy())); +- cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR")); Self { cmd } } diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 2c99597922e..fdcd9caf4ac 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -126,7 +126,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { &mut self, name: &str, params: Vec<AbiParam>, - returns: Vec<AbiParam>, + mut returns: Vec<AbiParam>, args: &[Value], ) -> Cow<'_, [Value]> { // Pass i128 arguments by-ref on Windows. @@ -150,15 +150,19 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { (params, args.into()) }; - // Return i128 using a return area pointer on Windows and s390x. - let adjust_ret_param = - if self.tcx.sess.target.is_like_windows || self.tcx.sess.target.arch == "s390x" { - returns.len() == 1 && returns[0].value_type == types::I128 - } else { - false - }; + let ret_single_i128 = returns.len() == 1 && returns[0].value_type == types::I128; + if ret_single_i128 && self.tcx.sess.target.is_like_windows { + // Return i128 using the vector ABI on Windows + returns[0].value_type = types::I64X2; + + let ret = self.lib_call_unadjusted(name, params, returns, &args)[0]; - if adjust_ret_param { + // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128 + let ret_ptr = self.create_stack_slot(16, 16); + ret_ptr.store(self, ret, MemFlags::trusted()); + Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]) + } else if ret_single_i128 && self.tcx.sess.target.arch == "s390x" { + // Return i128 using a return area pointer on s390x. let mut params = params; let mut args = args.to_vec(); diff --git a/compiler/rustc_codegen_cranelift/src/cast.rs b/compiler/rustc_codegen_cranelift/src/cast.rs index 0b5cb1547fc..4463631c524 100644 --- a/compiler/rustc_codegen_cranelift/src/cast.rs +++ b/compiler/rustc_codegen_cranelift/src/cast.rs @@ -96,25 +96,9 @@ pub(crate) fn clif_int_or_float_cast( }, ); - if fx.tcx.sess.target.is_like_windows { - let ret = fx.lib_call( - &name, - vec![AbiParam::new(from_ty)], - vec![AbiParam::new(types::I64X2)], - &[from], - )[0]; - // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128 - let ret_ptr = fx.create_stack_slot(16, 16); - ret_ptr.store(fx, ret, MemFlags::trusted()); - ret_ptr.load(fx, types::I128, MemFlags::trusted()) - } else { - fx.lib_call( - &name, - vec![AbiParam::new(from_ty)], - vec![AbiParam::new(types::I128)], - &[from], - )[0] - } + fx.lib_call(&name, vec![AbiParam::new(from_ty)], vec![AbiParam::new(types::I128)], &[ + from, + ])[0] } else if to_ty == types::I8 || to_ty == types::I16 { // FIXME implement fcvt_to_*int_sat.i8/i16 let val = if to_signed { diff --git a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs index dcfd7ddabbc..df5a79086fa 100644 --- a/compiler/rustc_codegen_cranelift/src/codegen_i128.rs +++ b/compiler/rustc_codegen_cranelift/src/codegen_i128.rs @@ -33,28 +33,14 @@ pub(crate) fn maybe_codegen<'tcx>( (BinOp::Rem, true) => "__modti3", _ => unreachable!(), }; - if fx.tcx.sess.target.is_like_windows { - let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; - let ret = fx.lib_call( - name, - vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], - vec![AbiParam::new(types::I64X2)], - &args, - )[0]; - // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128 - let ret_place = CPlace::new_stack_slot(fx, lhs.layout()); - ret_place.to_ptr().store(fx, ret, MemFlags::trusted()); - Some(ret_place.to_cvalue(fx)) - } else { - let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; - let ret_val = fx.lib_call( - name, - vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], - vec![AbiParam::new(types::I128)], - &args, - )[0]; - Some(CValue::by_val(ret_val, lhs.layout())) - } + let args = [lhs.load_scalar(fx), rhs.load_scalar(fx)]; + let ret_val = fx.lib_call( + name, + vec![AbiParam::new(types::I128), AbiParam::new(types::I128)], + vec![AbiParam::new(types::I128)], + &args, + )[0]; + Some(CValue::by_val(ret_val, lhs.layout())) } BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne | BinOp::Cmp => None, BinOp::Shl | BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => None, diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index fe578e44770..27adf6318e2 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -333,9 +333,17 @@ fn make_module(sess: &Session, name: String) -> UnwindModule<ObjectModule> { let mut builder = ObjectBuilder::new(isa, name + ".o", cranelift_module::default_libcall_names()).unwrap(); + + // Disable function sections by default on MSVC as it causes significant slowdowns with link.exe. + // Maybe link.exe has exponential behavior when there are many sections with the same name? Also + // explicitly disable it on MinGW as rustc already disables it by default on MinGW and as such + // isn't tested. If rustc enables it in the future on MinGW, we can re-enable it too once it has + // been on MinGW. + let default_function_sections = sess.target.function_sections && !sess.target.is_like_windows; builder.per_function_section( - sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections), + sess.opts.unstable_opts.function_sections.unwrap_or(default_function_sections), ); + UnwindModule::new(ObjectModule::new(builder), true) } @@ -668,7 +676,7 @@ pub(crate) fn run_aot( .to_owned(); let cgus = if tcx.sess.opts.output_types.should_codegen() { - tcx.collect_and_partition_mono_items(()).1 + tcx.collect_and_partition_mono_items(()).codegen_units } else { // If only `--emit metadata` is used, we shouldn't perform any codegen. // Also `tcx.collect_and_partition_mono_items` may panic in that case. diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index 2e5813556aa..26f14532b45 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -1,4 +1,5 @@ //! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, +//! functions marked with the `#[rustc_intrinsic]` attribute //! and LLVM intrinsics that have symbol names starting with `llvm.`. macro_rules! intrinsic_args { diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index e6bf0d5b47e..f6843496895 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -1,7 +1,7 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use rustc_hir::LangItem; use rustc_middle::ty::{AssocKind, GenericArg}; -use rustc_session::config::{EntryFnType, sigpipe}; +use rustc_session::config::EntryFnType; use rustc_span::{DUMMY_SP, Ident}; use crate::prelude::*; @@ -14,10 +14,9 @@ pub(crate) fn maybe_create_entry_wrapper( is_jit: bool, is_primary_cgu: bool, ) { - let (main_def_id, (is_main_fn, sigpipe)) = match tcx.entry_fn(()) { + let (main_def_id, sigpipe) = match tcx.entry_fn(()) { Some((def_id, entry_ty)) => (def_id, match entry_ty { - EntryFnType::Main { sigpipe } => (true, sigpipe), - EntryFnType::Start => (false, sigpipe::DEFAULT), + EntryFnType::Main { sigpipe } => sigpipe, }), None => return, }; @@ -31,14 +30,13 @@ pub(crate) fn maybe_create_entry_wrapper( return; } - create_entry_fn(tcx, module, main_def_id, is_jit, is_main_fn, sigpipe); + create_entry_fn(tcx, module, main_def_id, is_jit, sigpipe); fn create_entry_fn( tcx: TyCtxt<'_>, m: &mut dyn Module, rust_main_def_id: DefId, ignore_lang_start_wrapper: bool, - is_main_fn: bool, sigpipe: u8, ) { let main_ret_ty = tcx.fn_sig(rust_main_def_id).no_bound_vars().unwrap().output(); @@ -94,8 +92,8 @@ pub(crate) fn maybe_create_entry_wrapper( let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func); - let result = if is_main_fn && ignore_lang_start_wrapper { - // regular main fn, but ignoring #[lang = "start"] as we are running in the jit + let result = if ignore_lang_start_wrapper { + // ignoring #[lang = "start"] as we are running in the jit // FIXME set program arguments somehow let call_inst = bcx.ins().call(main_func_ref, &[]); let call_results = bcx.func.dfg.inst_results(call_inst).to_owned(); @@ -133,7 +131,8 @@ pub(crate) fn maybe_create_entry_wrapper( types::I64 => bcx.ins().sextend(types::I64, res), _ => unimplemented!("16bit systems are not yet supported"), } - } else if is_main_fn { + } else { + // Regular main fn invoked via start lang item. let start_def_id = tcx.require_lang_item(LangItem::Start, None); let start_instance = Instance::expect_resolve( tcx, @@ -150,10 +149,6 @@ pub(crate) fn maybe_create_entry_wrapper( let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv, arg_sigpipe]); bcx.inst_results(call_inst)[0] - } else { - // using user-defined start fn - let call_inst = bcx.ins().call(main_func_ref, &[arg_argc, arg_argv]); - bcx.inst_results(call_inst)[0] }; bcx.ins().return_(&[result]); diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml index 73ec6b84a15..f96912e6b7a 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml @@ -13,14 +13,14 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: libgccjit_version: - - { gcc: "gcc-13.deb" } - - { gcc: "gcc-13-without-int128.deb" } + - { gcc: "gcc-15.deb" } + - { gcc: "gcc-15-without-int128.deb" } commands: [ "--std-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. @@ -108,13 +108,13 @@ jobs: cargo clippy --all-targets --features master -- -D warnings duplicates: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - run: python tools/check_intrinsics_duplicates.py build_system: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 - name: Test build system diff --git a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml index f33d9fcc582..d080bbfe91f 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml @@ -13,7 +13,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -56,12 +56,12 @@ jobs: - name: Download artifact if: matrix.libgccjit_version.gcc != 'libgccjit12.so' - run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb + run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb - name: Setup path to libgccjit if: matrix.libgccjit_version.gcc != 'libgccjit12.so' run: | - sudo dpkg --force-overwrite -i gcc-13.deb + sudo dpkg --force-overwrite -i gcc-15.deb echo 'gcc-path = "/usr/lib"' > config.toml echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV diff --git a/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml b/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml index 4c2ce91e86e..bb9e020dc6a 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml @@ -17,7 +17,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml index 07bb372b360..ed1fc02bd91 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml @@ -17,7 +17,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -47,17 +47,17 @@ jobs: - name: Install packages run: | sudo apt-get update - sudo apt-get install qemu qemu-user-static + sudo apt-get install qemu-system qemu-user-static - name: Download artifact - run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-13.deb + run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-15.deb - name: Download VM artifact run: curl -LO https://github.com/cross-cg-gcc-tools/vms/releases/latest/download/debian-m68k.img - name: Setup path to libgccjit run: | - sudo dpkg -i gcc-m68k-13.deb + sudo dpkg -i gcc-m68k-15.deb echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env diff --git a/compiler/rustc_codegen_gcc/.github/workflows/release.yml b/compiler/rustc_codegen_gcc/.github/workflows/release.yml index 60e0943c87d..886ce90b471 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/release.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/release.yml @@ -13,7 +13,7 @@ env: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false @@ -37,11 +37,11 @@ jobs: run: sudo apt-get install ninja-build ripgrep - name: Download artifact - run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-13.deb + run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb - name: Setup path to libgccjit run: | - sudo dpkg --force-overwrite -i gcc-13.deb + sudo dpkg --force-overwrite -i gcc-15.deb echo 'gcc-path = "/usr/lib/"' > config.toml - name: Set env @@ -76,4 +76,9 @@ jobs: - name: Run y.sh cargo build run: | EMBED_LTO_BITCODE=1 CHANNEL="release" ./y.sh cargo build --release --manifest-path tests/hello-world/Cargo.toml - # TODO: grep the asm output for "call my_func" and fail if it is found. + call_found=$(objdump -dj .text tests/hello-world/target/release/hello_world | grep -c "call .*mylib.*my_func" ) ||: + if [ $call_found -gt 0 ]; then + echo "ERROR: call my_func found in asm" + echo "Test is done with LTO enabled, hence inlining should occur across crates" + exit 1 + fi diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs index d0ced211a61..e98377f15a9 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/build.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs @@ -150,6 +150,8 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu "debug" }; + // We have a different environment variable than RUSTFLAGS to make sure those flags are only + // sent to rustc_codegen_gcc and not the LLVM backend. if let Ok(cg_rustflags) = std::env::var("CG_RUSTFLAGS") { rustflags.push(' '); rustflags.push_str(&cg_rustflags); @@ -184,8 +186,12 @@ pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Resu fn build_codegen(args: &mut BuildArg) -> Result<(), String> { let mut env = HashMap::new(); - env.insert("LD_LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); - env.insert("LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); + let gcc_path = + args.config_info.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ); + env.insert("LD_LIBRARY_PATH".to_string(), gcc_path.clone()); + env.insert("LIBRARY_PATH".to_string(), gcc_path); if args.config_info.no_default_features { env.insert("RUSTFLAGS".to_string(), "-Csymbol-mangling-version=v0".to_string()); diff --git a/compiler/rustc_codegen_gcc/build_system/src/config.rs b/compiler/rustc_codegen_gcc/build_system/src/config.rs index 37b4b68950e..4f9fcc97151 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/config.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/config.rs @@ -112,7 +112,7 @@ pub struct ConfigInfo { pub sysroot_panic_abort: bool, pub cg_backend_path: String, pub sysroot_path: String, - pub gcc_path: String, + pub gcc_path: Option<String>, config_file: Option<String>, // This is used in particular in rust compiler bootstrap because it doesn't run at the root // of the `cg_gcc` folder, making it complicated for us to get access to local files we need @@ -173,6 +173,14 @@ impl ConfigInfo { "--release-sysroot" => self.sysroot_release_channel = true, "--release" => self.channel = Channel::Release, "--sysroot-panic-abort" => self.sysroot_panic_abort = true, + "--gcc-path" => match args.next() { + Some(arg) if !arg.is_empty() => { + self.gcc_path = Some(arg.into()); + } + _ => { + return Err("Expected a value after `--gcc-path`, found nothing".to_string()); + } + }, "--cg_gcc-path" => match args.next() { Some(arg) if !arg.is_empty() => { self.cg_gcc_path = Some(arg.into()); @@ -260,8 +268,9 @@ impl ConfigInfo { create_symlink(&libgccjit_so, output_dir.join(&format!("{}.0", libgccjit_so_name)))?; } - self.gcc_path = output_dir.display().to_string(); - println!("Using `{}` as path for libgccjit", self.gcc_path); + let gcc_path = output_dir.display().to_string(); + println!("Using `{}` as path for libgccjit", gcc_path); + self.gcc_path = Some(gcc_path); Ok(()) } @@ -273,6 +282,15 @@ impl ConfigInfo { } pub fn setup_gcc_path(&mut self) -> Result<(), String> { + // If the user used the `--gcc-path` option, no need to look at `config.toml` content + // since we already have everything we need. + if let Some(gcc_path) = &self.gcc_path { + println!( + "`--gcc-path` was provided, ignoring config file. Using `{}` as path for libgccjit", + gcc_path + ); + return Ok(()); + } let config_file = match self.config_file.as_deref() { Some(config_file) => config_file.into(), None => self.compute_path("config.toml"), @@ -283,12 +301,15 @@ impl ConfigInfo { self.download_gccjit_if_needed()?; return Ok(()); } - self.gcc_path = match gcc_path { - Some(path) => path, - None => { - return Err(format!("missing `gcc-path` value from `{}`", config_file.display(),)); - } + let Some(gcc_path) = gcc_path else { + return Err(format!("missing `gcc-path` value from `{}`", config_file.display())); }; + println!( + "GCC path retrieved from `{}`. Using `{}` as path for libgccjit", + config_file.display(), + gcc_path + ); + self.gcc_path = Some(gcc_path); Ok(()) } @@ -299,10 +320,17 @@ impl ConfigInfo { ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); - if self.gcc_path.is_empty() && !use_system_gcc { - self.setup_gcc_path()?; - } - env.insert("GCC_PATH".to_string(), self.gcc_path.clone()); + let gcc_path = if !use_system_gcc { + if self.gcc_path.is_none() { + self.setup_gcc_path()?; + } + self.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ) + } else { + String::new() + }; + env.insert("GCC_PATH".to_string(), gcc_path.clone()); if self.cargo_target_dir.is_empty() { match env.get("CARGO_TARGET_DIR").filter(|dir| !dir.is_empty()) { @@ -381,6 +409,8 @@ impl ConfigInfo { } // This environment variable is useful in case we want to change options of rustc commands. + // We have a different environment variable than RUSTFLAGS to make sure those flags are + // only sent to rustc_codegen_gcc and not the LLVM backend. if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") { rustflags.extend_from_slice(&split_args(&cg_rustflags)?); } @@ -414,7 +444,7 @@ impl ConfigInfo { "{target}:{sysroot}:{gcc_path}", target = self.cargo_target_dir, sysroot = sysroot.display(), - gcc_path = self.gcc_path, + gcc_path = gcc_path, ); env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone()); env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone()); @@ -459,6 +489,7 @@ impl ConfigInfo { --release-sysroot : Build sysroot in release mode --sysroot-panic-abort : Build the sysroot without unwinding support --config-file : Location of the config file to be used + --gcc-path : Location of the GCC root folder --cg_gcc-path : Location of the rustc_codegen_gcc root folder (used when ran from another directory) --no-default-features : Add `--no-default-features` flag to cargo commands diff --git a/compiler/rustc_codegen_gcc/build_system/src/info.rs b/compiler/rustc_codegen_gcc/build_system/src/info.rs index ea38791d38c..bd891de2eb4 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/info.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/info.rs @@ -14,6 +14,8 @@ pub fn run() -> Result<(), String> { } config.no_download = true; config.setup_gcc_path()?; - println!("{}", config.gcc_path); + if let Some(gcc_path) = config.gcc_path { + println!("{}", gcc_path); + } Ok(()) } diff --git a/compiler/rustc_codegen_gcc/build_system/src/main.rs b/compiler/rustc_codegen_gcc/build_system/src/main.rs index 3a860e2b136..39361718306 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/main.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/main.rs @@ -34,11 +34,11 @@ Options: --help : Displays this help message. Commands: - cargo : Executes a cargo command. + cargo : Executes a cargo command. rustc : Compiles the program using the GCC compiler. clean : Cleans the build directory, removing all compiled files and artifacts. prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. - build : Compiles the project. + build : Compiles the project. test : Runs tests for the project. info : Displays information about the build environment and project configuration. clone-gcc : Clones the GCC compiler from a specified source. diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs index 7cc7336612c..6c29c7d1825 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/test.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs @@ -426,19 +426,6 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { run_command_with_env(&command, None, Some(env))?; maybe_run_command_in_vm(&[&cargo_target_dir.join("track-caller-attribute")], env, args)?; - // FIXME: create a function "display_if_not_quiet" or something along the line. - println!("[AOT] mod_bench"); - let mut command = args.config_info.rustc_command_vec(); - command.extend_from_slice(&[ - &"example/mod_bench.rs", - &"--crate-type", - &"bin", - &"--target", - &args.config_info.target_triple, - ]); - run_command_with_env(&command, None, Some(env))?; - // FIXME: the compiled binary is not run. - Ok(()) } @@ -696,19 +683,6 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } -// echo "[BENCH COMPILE] mod_bench" -// -// COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline" -// COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort" -// COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort" -// -// Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow -// hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3" -// echo "[BENCH RUN] mod_bench" -// hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_* - fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); @@ -1255,8 +1229,11 @@ pub fn run() -> Result<(), String> { if !args.use_system_gcc { args.config_info.setup_gcc_path()?; - env.insert("LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); - env.insert("LD_LIBRARY_PATH".to_string(), args.config_info.gcc_path.clone()); + let gcc_path = args.config_info.gcc_path.clone().expect( + "The config module should have emitted an error if the GCC path wasn't provided", + ); + env.insert("LIBRARY_PATH".to_string(), gcc_path.clone()); + env.insert("LD_LIBRARY_PATH".to_string(), gcc_path); } build_if_no_backend(&env, &args)?; diff --git a/compiler/rustc_codegen_gcc/example/alloc_example.rs b/compiler/rustc_codegen_gcc/example/alloc_example.rs index 6ed8b9157f2..9a0b46d5b22 100644 --- a/compiler/rustc_codegen_gcc/example/alloc_example.rs +++ b/compiler/rustc_codegen_gcc/example/alloc_example.rs @@ -1,5 +1,6 @@ -#![feature(start, core_intrinsics, alloc_error_handler, lang_items)] +#![feature(core_intrinsics, alloc_error_handler, lang_items)] #![no_std] +#![no_main] #![allow(internal_features)] extern crate alloc; @@ -37,8 +38,8 @@ unsafe extern "C" fn _Unwind_Resume() { core::intrinsics::unreachable(); } -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { let world: Box<&str> = Box::new("Hello World!\0"); unsafe { puts(*world as *const str as *const u8); diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index 1d51e0a1856..4cbe66c5e4c 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -1,7 +1,7 @@ // Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs #![feature( - no_core, unboxed_closures, start, lang_items, never_type, linkage, + no_core, unboxed_closures, lang_items, never_type, linkage, extern_types, thread_local )] #![no_core] diff --git a/compiler/rustc_codegen_gcc/example/mod_bench.rs b/compiler/rustc_codegen_gcc/example/mod_bench.rs deleted file mode 100644 index e8a9cade747..00000000000 --- a/compiler/rustc_codegen_gcc/example/mod_bench.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![feature(start, core_intrinsics, lang_items)] -#![no_std] -#![allow(internal_features)] - -#[link(name = "c")] -extern "C" {} - -#[panic_handler] -fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { - core::intrinsics::abort(); -} - -#[lang="eh_personality"] -fn eh_personality(){} - -// Required for rustc_codegen_llvm -#[no_mangle] -unsafe extern "C" fn _Unwind_Resume() { - core::intrinsics::unreachable(); -} - -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { - for i in 2..100_000_000 { - black_box((i + 1) % i); - } - - 0 -} - -#[inline(never)] -fn black_box(i: u32) { - if i != 1 { - core::intrinsics::abort(); - } -} diff --git a/compiler/rustc_codegen_gcc/libgccjit.version b/compiler/rustc_codegen_gcc/libgccjit.version index ff58accec1d..417fd5b0393 100644 --- a/compiler/rustc_codegen_gcc/libgccjit.version +++ b/compiler/rustc_codegen_gcc/libgccjit.version @@ -1 +1 @@ -45648c2edd4ecd862d9f08196d3d6c6ccba79f07 +e607be166673a8de9fc07f6f02c60426e556c5f2 diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl index 85fa17a6ba5..882fff8673a 100644 --- a/compiler/rustc_codegen_gcc/messages.ftl +++ b/compiler/rustc_codegen_gcc/messages.ftl @@ -5,9 +5,6 @@ codegen_gcc_unknown_ctarget_feature_prefix = codegen_gcc_invalid_minimum_alignment = invalid minimum global alignment: {$err} -codegen_gcc_lto_not_supported = - LTO is not supported. You may get a linker error. - codegen_gcc_forbidden_ctarget_feature = target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason} diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index f43743fc2a4..bd5d6ba387c 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -64,6 +64,11 @@ impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) } } + fn is_undef(&self, _val: RValue<'gcc>) -> bool { + // FIXME: actually check for undef + false + } + fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> { let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined"); if typ.is_struct().is_some() { diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index c81c53359fd..30732c74eb3 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -513,7 +513,6 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} - // instead of #[start] None } } diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index d3aeb7f3bde..4b84b1dbfd3 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -113,15 +113,15 @@ fn make_mir_scope<'gcc, 'tcx>( let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { make_mir_scope(cx, _instance, mir, variables, debug_context, instantiated, parent); - debug_context.scopes[parent].unwrap() + debug_context.scopes[parent] } else { // The root is the function itself. let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); - debug_context.scopes[scope] = Some(DebugScope { + debug_context.scopes[scope] = DebugScope { file_start_pos: file.start_pos, file_end_pos: file.end_position(), - ..debug_context.scopes[scope].unwrap() - }); + ..debug_context.scopes[scope] + }; instantiated.insert(scope); return; }; @@ -130,7 +130,7 @@ fn make_mir_scope<'gcc, 'tcx>( if !vars.contains(scope) && scope_data.inlined.is_none() { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. - debug_context.scopes[scope] = Some(parent_scope); + debug_context.scopes[scope] = parent_scope; instantiated.insert(scope); return; } @@ -157,12 +157,12 @@ fn make_mir_scope<'gcc, 'tcx>( // TODO(tempdragon): dbg_scope: Add support for scope extension here. inlined_at.or(p_inlined_at); - debug_context.scopes[scope] = Some(DebugScope { + debug_context.scopes[scope] = DebugScope { dbg_scope, inlined_at, file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_position(), - }); + }; instantiated.insert(scope); } @@ -232,12 +232,12 @@ impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } // Initialize fn debug context (including scopes). - let empty_scope = Some(DebugScope { + let empty_scope = DebugScope { dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), inlined_at: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0), - }); + }; let mut fn_debug_context = FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, mir.source_scopes.as_slice()), inlined_function_scopes: Default::default(), diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index f6ad0c79de5..38019faa7a9 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -444,7 +444,6 @@ impl WriteBackendMethods for GccCodegenBackend { } fn autodiff( _cgcx: &CodegenContext<Self>, - _tcx: TyCtxt<'_>, _module: &ModuleCodegen<Self::Module>, _diff_fncs: Vec<AutoDiffItem>, _config: &ModuleConfig, diff --git a/compiler/rustc_codegen_gcc/tests/run/abort1.rs b/compiler/rustc_codegen_gcc/tests/run/abort1.rs index 696197d7377..385e41a6881 100644 --- a/compiler/rustc_codegen_gcc/tests/run/abort1.rs +++ b/compiler/rustc_codegen_gcc/tests/run/abort1.rs @@ -3,11 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -49,7 +50,7 @@ fn test_fail() -> ! { unsafe { intrinsics::abort() }; } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { test_fail(); } diff --git a/compiler/rustc_codegen_gcc/tests/run/abort2.rs b/compiler/rustc_codegen_gcc/tests/run/abort2.rs index 714cd6c0f38..6c66a930e07 100644 --- a/compiler/rustc_codegen_gcc/tests/run/abort2.rs +++ b/compiler/rustc_codegen_gcc/tests/run/abort2.rs @@ -3,11 +3,12 @@ // Run-time: // status: signal -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -50,8 +51,8 @@ fn fail() -> i32 { 0 } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { fail(); 0 } diff --git a/compiler/rustc_codegen_gcc/tests/run/array.rs b/compiler/rustc_codegen_gcc/tests/run/array.rs index c3c08c29c6d..e18a4ced6bc 100644 --- a/compiler/rustc_codegen_gcc/tests/run/array.rs +++ b/compiler/rustc_codegen_gcc/tests/run/array.rs @@ -7,10 +7,11 @@ // 5 // 10 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -28,8 +29,8 @@ fn make_array() -> [u8; 3] { [42, 10, 5] } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let array = [42, 7, 5]; let array2 = make_array(); unsafe { diff --git a/compiler/rustc_codegen_gcc/tests/run/assign.rs b/compiler/rustc_codegen_gcc/tests/run/assign.rs index 2a47f0c2966..4d414c577a6 100644 --- a/compiler/rustc_codegen_gcc/tests/run/assign.rs +++ b/compiler/rustc_codegen_gcc/tests/run/assign.rs @@ -6,10 +6,11 @@ // 10 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -142,8 +143,8 @@ fn inc(num: isize) -> isize { } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { argc = inc(argc); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, argc); diff --git a/compiler/rustc_codegen_gcc/tests/run/closure.rs b/compiler/rustc_codegen_gcc/tests/run/closure.rs index 46c47bc54ed..c7a236f74f9 100644 --- a/compiler/rustc_codegen_gcc/tests/run/closure.rs +++ b/compiler/rustc_codegen_gcc/tests/run/closure.rs @@ -8,10 +8,11 @@ // Int argument: 2 // Both args: 11 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -22,8 +23,8 @@ mod libc { } } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let string = "Arg: %d\n\0"; let mut closure = || { unsafe { diff --git a/compiler/rustc_codegen_gcc/tests/run/condition.rs b/compiler/rustc_codegen_gcc/tests/run/condition.rs index 039ef94eaa7..b02359702ed 100644 --- a/compiler/rustc_codegen_gcc/tests/run/condition.rs +++ b/compiler/rustc_codegen_gcc/tests/run/condition.rs @@ -5,10 +5,11 @@ // stdout: true // 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -19,8 +20,8 @@ mod libc { } } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { if argc == 1 { libc::printf(b"true\n\0" as *const u8 as *const i8); diff --git a/compiler/rustc_codegen_gcc/tests/run/empty_main.rs b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs index e66a859ad69..042e44080c5 100644 --- a/compiler/rustc_codegen_gcc/tests/run/empty_main.rs +++ b/compiler/rustc_codegen_gcc/tests/run/empty_main.rs @@ -3,11 +3,12 @@ // Run-time: // status: 0 -#![feature(auto_traits, lang_items, no_core, start)] +#![feature(auto_traits, lang_items, no_core)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -34,7 +35,7 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { 0 } diff --git a/compiler/rustc_codegen_gcc/tests/run/exit.rs b/compiler/rustc_codegen_gcc/tests/run/exit.rs index bf1cbeef302..9a7c91c0adb 100644 --- a/compiler/rustc_codegen_gcc/tests/run/exit.rs +++ b/compiler/rustc_codegen_gcc/tests/run/exit.rs @@ -3,11 +3,12 @@ // Run-time: // status: 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] mod libc { #[link(name = "c")] @@ -41,8 +42,8 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::exit(2); } diff --git a/compiler/rustc_codegen_gcc/tests/run/exit_code.rs b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs index be7a233efda..c50d2b0d710 100644 --- a/compiler/rustc_codegen_gcc/tests/run/exit_code.rs +++ b/compiler/rustc_codegen_gcc/tests/run/exit_code.rs @@ -3,11 +3,12 @@ // Run-time: // status: 1 -#![feature(auto_traits, lang_items, no_core, start)] +#![feature(auto_traits, lang_items, no_core)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -34,7 +35,7 @@ pub(crate) unsafe auto trait Freeze {} * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { 1 } diff --git a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs index ed1bf72bb27..98b351e5044 100644 --- a/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs +++ b/compiler/rustc_codegen_gcc/tests/run/fun_ptr.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -26,8 +27,8 @@ fn call_func(func: fn(i16) -> i8, param: i16) -> i8 { func(param) } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { let result = call_func(i16_as_i8, argc as i16) as isize; libc::printf(b"%ld\n\0" as *const u8 as *const i8, result); diff --git a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs index 3ae79338216..9be64f991ee 100644 --- a/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs +++ b/compiler/rustc_codegen_gcc/tests/run/mut_ref.rs @@ -8,10 +8,11 @@ // 11 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs, track_caller)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs, track_caller)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -148,8 +149,8 @@ fn update_num(num: &mut isize) { *num = *num + 5; } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let mut test = test(argc); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field); diff --git a/compiler/rustc_codegen_gcc/tests/run/operations.rs b/compiler/rustc_codegen_gcc/tests/run/operations.rs index 0e44fc580b8..c92d3cc0b8f 100644 --- a/compiler/rustc_codegen_gcc/tests/run/operations.rs +++ b/compiler/rustc_codegen_gcc/tests/run/operations.rs @@ -6,10 +6,11 @@ // 10 #![allow(internal_features, unused_attributes)] -#![feature(auto_traits, lang_items, no_core, start, intrinsics, arbitrary_self_types, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, arbitrary_self_types, rustc_attrs)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -231,8 +232,8 @@ pub fn panic_const_mul_overflow() -> ! { * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 + argc); libc::printf(b"%ld\n\0" as *const u8 as *const i8, 40 - argc); diff --git a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs index 2b8812ad51c..0ba49e7187f 100644 --- a/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs +++ b/compiler/rustc_codegen_gcc/tests/run/ptr_cast.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 1 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -24,8 +25,8 @@ fn make_array() -> [u8; 3] { [42, 10, 5] } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { let ptr = ONE as *mut usize; let value = ptr as usize; diff --git a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs index f2a5a2e4384..3cc1e274001 100644 --- a/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs +++ b/compiler/rustc_codegen_gcc/tests/run/return-tuple.rs @@ -6,11 +6,12 @@ // 10 // 42 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] #[lang = "copy"] pub unsafe trait Copy {} @@ -61,8 +62,8 @@ fn int_cast(a: u16, b: i16) -> (u8, u16, u32, usize, i8, i16, i32, isize, u8, u3 ) } -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let (a, b, c, d, e, f, g, h, i, j) = int_cast(10, 42); unsafe { libc::printf(b"%d\n\0" as *const u8 as *const i8, c); diff --git a/compiler/rustc_codegen_gcc/tests/run/slice.rs b/compiler/rustc_codegen_gcc/tests/run/slice.rs index fba93fc1554..825fcb8a081 100644 --- a/compiler/rustc_codegen_gcc/tests/run/slice.rs +++ b/compiler/rustc_codegen_gcc/tests/run/slice.rs @@ -4,10 +4,11 @@ // status: 0 // stdout: 5 -#![feature(no_core, start)] +#![feature(no_core)] #![no_std] #![no_core] +#![no_main] extern crate mini_core; @@ -26,8 +27,8 @@ fn index_slice(s: &[u32]) -> u32 { } } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let array = [42, 7, 5]; unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, index_slice(&array)); diff --git a/compiler/rustc_codegen_gcc/tests/run/static.rs b/compiler/rustc_codegen_gcc/tests/run/static.rs index a17ea2a4893..80c8782c4b1 100644 --- a/compiler/rustc_codegen_gcc/tests/run/static.rs +++ b/compiler/rustc_codegen_gcc/tests/run/static.rs @@ -9,11 +9,12 @@ // 12 // 1 -#![feature(auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] +#![feature(auto_traits, lang_items, no_core, intrinsics, rustc_attrs)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -98,8 +99,8 @@ static mut WITH_REF: WithRef = WithRef { refe: unsafe { &TEST }, }; -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, CONSTANT); libc::printf(b"%ld\n\0" as *const u8 as *const i8, TEST2.field); diff --git a/compiler/rustc_codegen_gcc/tests/run/structs.rs b/compiler/rustc_codegen_gcc/tests/run/structs.rs index d6455667400..59b8f358863 100644 --- a/compiler/rustc_codegen_gcc/tests/run/structs.rs +++ b/compiler/rustc_codegen_gcc/tests/run/structs.rs @@ -5,11 +5,12 @@ // stdout: 1 // 2 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -55,8 +56,8 @@ fn one() -> isize { 1 } -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let test = Test { field: one(), }; diff --git a/compiler/rustc_codegen_gcc/tests/run/tuple.rs b/compiler/rustc_codegen_gcc/tests/run/tuple.rs index 8a7d85ae867..ed60a56a68c 100644 --- a/compiler/rustc_codegen_gcc/tests/run/tuple.rs +++ b/compiler/rustc_codegen_gcc/tests/run/tuple.rs @@ -4,11 +4,12 @@ // status: 0 // stdout: 3 -#![feature(auto_traits, lang_items, no_core, start, intrinsics)] +#![feature(auto_traits, lang_items, no_core, intrinsics)] #![allow(internal_features)] #![no_std] #![no_core] +#![no_main] /* * Core @@ -42,8 +43,8 @@ mod libc { * Code */ -#[start] -fn main(mut argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { let test: (isize, isize, isize) = (3, 1, 4); unsafe { libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.0); diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index c44d1a5e5c2..94f21ac5f57 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -9,6 +9,8 @@ test = false [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" +# To avoid duplicate dependencies, this should match the version of gimli used +# by `rustc_codegen_ssa` via its `thorin-dwp` dependency. gimli = "0.30" itertools = "0.12" libc = "0.2" diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 95e0481b035..3d7afa17bdf 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -333,9 +333,12 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( let mut to_add = SmallVec::<[_; 16]>::new(); match codegen_fn_attrs.optimize { - OptimizeAttr::None => { + OptimizeAttr::Default => { to_add.extend(default_optimisation_attrs(cx)); } + OptimizeAttr::DoNotOptimize => { + to_add.push(llvm::AttributeKind::OptimizeNone.create_attr(cx.llcx)); + } OptimizeAttr::Size => { to_add.push(llvm::AttributeKind::MinSize.create_attr(cx.llcx)); to_add.push(llvm::AttributeKind::OptimizeForSize.create_attr(cx.llcx)); @@ -343,12 +346,12 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>( OptimizeAttr::Speed => {} } - let inline = - if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) { - InlineAttr::Hint - } else { - codegen_fn_attrs.inline - }; + // `optnone` requires `noinline` + let inline = match (codegen_fn_attrs.inline, &codegen_fn_attrs.optimize) { + (_, OptimizeAttr::DoNotOptimize) => InlineAttr::Never, + (InlineAttr::None, _) if instance.def.requires_inline(cx.tcx) => InlineAttr::Hint, + (inline, _) => inline, + }; to_add.extend(inline_attr(cx, inline)); // The `uwtable` attribute according to LLVM is: diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 509b24dd703..4706744f353 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -769,12 +769,9 @@ pub(crate) unsafe fn codegen( } } - // Two things to note: - // - If object files are just LLVM bitcode we write bitcode, copy it to - // the .o file, and delete the bitcode if it wasn't otherwise - // requested. - // - If we don't have the integrated assembler then we need to emit - // asm from LLVM and use `gcc` to create the object file. + // Note that if object files are just LLVM bitcode we write bitcode, + // copy it to the .o file, and delete the bitcode if it wasn't + // otherwise requested. let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); let bc_summary_out = diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 5a34b52e6ef..d2de62b17f0 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1,4 +1,4 @@ -use std::borrow::Cow; +use std::borrow::{Borrow, Cow}; use std::ops::Deref; use std::{iter, ptr}; @@ -31,20 +31,22 @@ use tracing::{debug, instrument}; use crate::abi::FnAbiLlvmExt; use crate::attributes; use crate::common::Funclet; -use crate::context::CodegenCx; +use crate::context::{CodegenCx, SimpleCx}; use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True}; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; -// All Builders must have an llfn associated with them #[must_use] -pub(crate) struct Builder<'a, 'll, 'tcx> { +pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow<SimpleCx<'ll>>> { pub llbuilder: &'ll mut llvm::Builder<'ll>, - pub cx: &'a CodegenCx<'ll, 'tcx>, + pub cx: &'a CX, } -impl Drop for Builder<'_, '_, '_> { +pub(crate) type SBuilder<'a, 'll> = GenericBuilder<'a, 'll, SimpleCx<'ll>>; +pub(crate) type Builder<'a, 'll, 'tcx> = GenericBuilder<'a, 'll, CodegenCx<'ll, 'tcx>>; + +impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> Drop for GenericBuilder<'a, 'll, CX> { fn drop(&mut self) { unsafe { llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _)); @@ -52,6 +54,112 @@ impl Drop for Builder<'_, '_, '_> { } } +impl<'a, 'll> SBuilder<'a, 'll> { + fn call( + &mut self, + llty: &'ll Type, + llfn: &'ll Value, + args: &[&'ll Value], + funclet: Option<&Funclet<'ll>>, + ) -> &'ll Value { + debug!("call {:?} with args ({:?})", llfn, args); + + let args = self.check_call("call", llty, llfn, args); + let funclet_bundle = funclet.map(|funclet| funclet.bundle()); + let mut bundles: SmallVec<[_; 2]> = SmallVec::new(); + if let Some(funclet_bundle) = funclet_bundle { + bundles.push(funclet_bundle); + } + + let call = unsafe { + llvm::LLVMBuildCallWithOperandBundles( + self.llbuilder, + llty, + llfn, + args.as_ptr() as *const &llvm::Value, + args.len() as c_uint, + bundles.as_ptr(), + bundles.len() as c_uint, + c"".as_ptr(), + ) + }; + call + } + + fn with_scx(scx: &'a SimpleCx<'ll>) -> Self { + // Create a fresh builder from the simple context. + let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(scx.llcx) }; + SBuilder { llbuilder, cx: scx } + } +} +impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> { + pub(crate) fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED) } + } + + fn ret_void(&mut self) { + unsafe { + llvm::LLVMBuildRetVoid(self.llbuilder); + } + } + + fn ret(&mut self, v: &'ll Value) { + unsafe { + llvm::LLVMBuildRet(self.llbuilder, v); + } + } +} +impl<'a, 'll> SBuilder<'a, 'll> { + fn build(cx: &'a SimpleCx<'ll>, llbb: &'ll BasicBlock) -> SBuilder<'a, 'll> { + let bx = SBuilder::with_scx(cx); + unsafe { + llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb); + } + bx + } + + fn check_call<'b>( + &mut self, + typ: &str, + fn_ty: &'ll Type, + llfn: &'ll Value, + args: &'b [&'ll Value], + ) -> Cow<'b, [&'ll Value]> { + assert!( + self.cx.type_kind(fn_ty) == TypeKind::Function, + "builder::{typ} not passed a function, but {fn_ty:?}" + ); + + let param_tys = self.cx.func_params_types(fn_ty); + + let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.cx.val_ty(v))) + .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty); + + if all_args_match { + return Cow::Borrowed(args); + } + + let casted_args: Vec<_> = iter::zip(param_tys, args) + .enumerate() + .map(|(i, (expected_ty, &actual_val))| { + let actual_ty = self.cx.val_ty(actual_val); + if expected_ty != actual_ty { + debug!( + "type mismatch in function call of {:?}. \ + Expected {:?} for param {}, got {:?}; injecting bitcast", + llfn, expected_ty, i, actual_ty + ); + self.bitcast(actual_val, expected_ty) + } else { + actual_val + } + }) + .collect(); + + Cow::Owned(casted_args) + } +} + /// Empty string, to be used where LLVM expects an instruction name, indicating /// that the instruction is to be left unnamed (i.e. numbered, in textual IR). // FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer. @@ -1222,6 +1330,14 @@ impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> { } impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { + fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Builder<'a, 'll, 'tcx> { + let bx = Builder::with_cx(cx); + unsafe { + llvm::LLVMPositionBuilderAtEnd(bx.llbuilder, llbb); + } + bx + } + fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { // Create a fresh builder from the crate context. let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) }; @@ -1231,13 +1347,16 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { pub(crate) fn llfn(&self) -> &'ll Value { unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) } } +} +impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> { fn position_at_start(&mut self, llbb: &'ll BasicBlock) { unsafe { llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb); } } - +} +impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { fn align_metadata(&mut self, load: &'ll Value, align: Align) { unsafe { let md = [llvm::LLVMValueAsMetadata(self.cx.const_u64(align.bytes()))]; @@ -1259,7 +1378,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { self.set_metadata(inst, llvm::MD_unpredictable, md); } } - +} +impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> { pub(crate) fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) } } @@ -1360,7 +1480,9 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) }; ret.expect("LLVM does not have support for catchret") } +} +impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { fn check_call<'b>( &mut self, typ: &str, @@ -1401,11 +1523,13 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { Cow::Owned(casted_args) } - +} +impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> { pub(crate) fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) } } - +} +impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { pub(crate) fn call_intrinsic(&mut self, intrinsic: &str, args: &[&'ll Value]) -> &'ll Value { let (ty, f) = self.cx.get_intrinsic(intrinsic); self.call(ty, None, None, f, args, None, None) @@ -1423,7 +1547,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { self.call_intrinsic(intrinsic, &[self.cx.const_u64(size), ptr]); } - +} +impl<'a, 'll, CX: Borrow<SimpleCx<'ll>>> GenericBuilder<'a, 'll, CX> { pub(crate) fn phi( &mut self, ty: &'ll Type, @@ -1443,7 +1568,8 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint); } } - +} +impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { fn fptoint_sat(&mut self, signed: bool, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { let src_ty = self.cx.val_ty(val); let (float_ty, int_ty, vector_length) = if self.cx.type_kind(src_ty) == TypeKind::Vector { diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 38f7eaa090f..6b17b5f6989 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -3,20 +3,19 @@ use std::ptr; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, AutoDiffItem, DiffActivity, DiffMode}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::back::write::ModuleConfig; -use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; use rustc_errors::FatalError; -use rustc_middle::ty::TyCtxt; use rustc_session::config::Lto; use tracing::{debug, trace}; use crate::back::write::{llvm_err, llvm_optimize}; -use crate::builder::Builder; -use crate::declare::declare_raw_fn; +use crate::builder::SBuilder; +use crate::context::SimpleCx; +use crate::declare::declare_simple_fn; use crate::errors::LlvmError; use crate::llvm::AttributePlace::Function; use crate::llvm::{Metadata, True}; use crate::value::Value; -use crate::{CodegenContext, LlvmCodegenBackend, ModuleLlvm, attributes, context, llvm}; +use crate::{CodegenContext, LlvmCodegenBackend, ModuleLlvm, attributes, llvm}; fn get_params(fnc: &Value) -> Vec<&Value> { unsafe { @@ -38,8 +37,8 @@ fn get_params(fnc: &Value) -> Vec<&Value> { /// [^1]: <https://enzyme.mit.edu/getting_started/CallingConvention/> // FIXME(ZuseZ4): `outer_fn` should include upstream safety checks to // cover some assumptions of enzyme/autodiff, which could lead to UB otherwise. -fn generate_enzyme_call<'ll, 'tcx>( - cx: &context::CodegenCx<'ll, 'tcx>, +fn generate_enzyme_call<'ll>( + cx: &SimpleCx<'ll>, fn_to_diff: &'ll Value, outer_fn: &'ll Value, attrs: AutoDiffAttrs, @@ -112,7 +111,7 @@ fn generate_enzyme_call<'ll, 'tcx>( //FIXME(ZuseZ4): the CC/Addr/Vis values are best effort guesses, we should look at tests and // think a bit more about what should go here. let cc = llvm::LLVMGetFunctionCallConv(outer_fn); - let ad_fn = declare_raw_fn( + let ad_fn = declare_simple_fn( cx, &ad_name, llvm::CallConv::try_from(cc).expect("invalid callconv"), @@ -132,7 +131,7 @@ fn generate_enzyme_call<'ll, 'tcx>( llvm::LLVMRustEraseInstFromParent(br); let last_inst = llvm::LLVMRustGetLastInstruction(entry).unwrap(); - let mut builder = Builder::build(cx, entry); + let mut builder = SBuilder::build(cx, entry); let num_args = llvm::LLVMCountParams(&fn_to_diff); let mut args = Vec::with_capacity(num_args as usize + 1); @@ -236,7 +235,7 @@ fn generate_enzyme_call<'ll, 'tcx>( } } - let call = builder.call(enzyme_ty, None, None, ad_fn, &args, None, None); + let call = builder.call(enzyme_ty, ad_fn, &args, None); // This part is a bit iffy. LLVM requires that a call to an inlineable function has some // metadata attachted to it, but we just created this code oota. Given that the @@ -274,10 +273,9 @@ fn generate_enzyme_call<'ll, 'tcx>( } } -pub(crate) fn differentiate<'ll, 'tcx>( +pub(crate) fn differentiate<'ll>( module: &'ll ModuleCodegen<ModuleLlvm>, cgcx: &CodegenContext<LlvmCodegenBackend>, - tcx: TyCtxt<'tcx>, diff_items: Vec<AutoDiffItem>, config: &ModuleConfig, ) -> Result<(), FatalError> { @@ -286,8 +284,7 @@ pub(crate) fn differentiate<'ll, 'tcx>( } let diag_handler = cgcx.create_dcx(); - let (_, cgus) = tcx.collect_and_partition_mono_items(()); - let cx = context::CodegenCx::new(tcx, &cgus.first().unwrap(), &module.module_llvm); + let cx = SimpleCx { llmod: module.module_llvm.llmod(), llcx: module.module_llvm.llcx }; // Before dumping the module, we want all the TypeTrees to become part of the module. for item in diff_items.iter() { diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index adfe8aeb5c5..b4e9b9f44f4 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -126,6 +126,10 @@ impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMGetUndef(t) } } + fn is_undef(&self, v: &'ll Value) -> bool { + unsafe { llvm::LLVMIsUndef(v) == True } + } + fn const_poison(&self, t: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMGetPoison(t) } } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 65345751842..79381f35a3c 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1,11 +1,13 @@ use std::borrow::Borrow; use std::cell::{Cell, RefCell}; use std::ffi::{CStr, c_char, c_uint}; +use std::ops::Deref; use std::str; use rustc_abi::{HasDataLayout, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; +use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; @@ -30,23 +32,46 @@ use smallvec::SmallVec; use crate::back::write::to_llvm_code_model; use crate::callee::get_fn; -use crate::common::AsCCharPtr; +use crate::common::{self, AsCCharPtr}; use crate::debuginfo::metadata::apply_vcall_visibility_metadata; use crate::llvm::{Metadata, MetadataType}; use crate::type_::Type; use crate::value::Value; use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util}; +/// `TyCtxt` (and related cache datastructures) can't be move between threads. +/// However, there are various cx related functions which we want to be available to the builder and +/// other compiler pieces. Here we define a small subset which has enough information and can be +/// moved around more freely. +pub(crate) struct SimpleCx<'ll> { + pub llmod: &'ll llvm::Module, + pub llcx: &'ll llvm::Context, +} + +impl<'ll> Borrow<SimpleCx<'ll>> for CodegenCx<'ll, '_> { + fn borrow(&self) -> &SimpleCx<'ll> { + &self.scx + } +} + +impl<'ll, 'tcx> Deref for CodegenCx<'ll, 'tcx> { + type Target = SimpleCx<'ll>; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.scx + } +} + /// There is one `CodegenCx` per codegen unit. Each one has its own LLVM /// `llvm::Context` so that several codegen units may be processed in parallel. /// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`. pub(crate) struct CodegenCx<'ll, 'tcx> { pub tcx: TyCtxt<'tcx>, + pub scx: SimpleCx<'ll>, pub use_dll_storage_attrs: bool, pub tls_model: llvm::ThreadLocalMode, - pub llmod: &'ll llvm::Module, - pub llcx: &'ll llvm::Context, pub codegen_unit: &'tcx CodegenUnit<'tcx>, /// Cache instances of monomorphic and polymorphic items @@ -553,10 +578,9 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { CodegenCx { tcx, + scx: SimpleCx { llcx, llmod }, use_dll_storage_attrs, tls_model, - llmod, - llcx, codegen_unit, instances: Default::default(), vtables: Default::default(), @@ -600,6 +624,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { llvm::set_section(g, c"llvm.metadata"); } } +} +impl<'ll> SimpleCx<'ll> { + pub(crate) fn val_ty(&self, v: &'ll Value) -> &'ll Type { + common::val_ty(v) + } pub(crate) fn get_metadata_value(&self, metadata: &'ll Metadata) -> &'ll Value { unsafe { llvm::LLVMMetadataAsValue(self.llcx, metadata) } @@ -625,6 +654,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { llvm::LLVMMDStringInContext2(self.llcx, name.as_ptr() as *const c_char, name.len()) }) } + + pub(crate) fn type_kind(&self, ty: &'ll Type) -> TypeKind { + unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() } + } } impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -751,7 +784,6 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { } else { // If the symbol already exists, it is an error: for example, the user wrote // #[no_mangle] extern "C" fn main(..) {..} - // instead of #[start] None } } @@ -1179,6 +1211,20 @@ impl CodegenCx<'_, '_> { } } +// This is a duplication of the set_metadata function above. However, so far it's the only one +// shared between both contexts, so it doesn't seem worth it to make the Cx generic like we did it +// for the Builder. +impl SimpleCx<'_> { + #[allow(unused)] + /// A wrapper for [`llvm::LLVMSetMetadata`], but it takes `Metadata` as a parameter instead of `Value`. + pub(crate) fn set_metadata<'a>(&self, val: &'a Value, kind_id: MetadataType, md: &'a Metadata) { + unsafe { + let node = llvm::LLVMMetadataAsValue(&self.llcx, md); + llvm::LLVMSetMetadata(val, kind_id as c_uint, node); + } + } +} + impl HasDataLayout for CodegenCx<'_, '_> { #[inline] fn data_layout(&self) -> &TargetDataLayout { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index b3ad2a0e409..fd22421c7fc 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -9,6 +9,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::IndexVec; use rustc_middle::mir; +use rustc_middle::mir::mono::MonoItemPartitions; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::RemapFileNameExt; use rustc_session::config::RemapPathScopeComponents; @@ -297,12 +298,13 @@ struct UsageSets<'tcx> { /// Prepare sets of definitions that are relevant to deciding whether something /// is an "unused function" for coverage purposes. fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> { - let (all_mono_items, cgus) = tcx.collect_and_partition_mono_items(()); + let MonoItemPartitions { all_mono_items, codegen_units } = + tcx.collect_and_partition_mono_items(()); // Obtain a MIR body for each function participating in codegen, via an // arbitrary instance. let mut def_ids_seen = FxHashSet::default(); - let def_and_mir_for_all_mono_fns = cgus + let def_and_mir_for_all_mono_fns = codegen_units .iter() .flat_map(|cgu| cgu.items().keys()) .filter_map(|item| match item { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs index 5428d776f41..460a4664615 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/covfun.rs @@ -51,7 +51,7 @@ pub(crate) fn prepare_covfun_record<'tcx>( is_used: bool, ) -> Option<CovfunRecord<'tcx>> { let fn_cov_info = tcx.instance_mir(instance.def).function_coverage_info.as_deref()?; - let ids_info = tcx.coverage_ids_info(instance.def); + let ids_info = tcx.coverage_ids_info(instance.def)?; let expressions = prepare_expressions(fn_cov_info, ids_info, is_used); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 7311cd9d230..021108cd51c 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -8,7 +8,6 @@ use rustc_codegen_ssa::traits::{ use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_middle::mir::coverage::CoverageKind; use rustc_middle::ty::Instance; -use rustc_middle::ty::layout::HasTyCtxt; use tracing::{debug, instrument}; use crate::builder::Builder; @@ -147,6 +146,10 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { debug!("function has a coverage statement but no coverage info"); return; }; + let Some(ids_info) = bx.tcx.coverage_ids_info(instance.def) else { + debug!("function has a coverage statement but no IDs info"); + return; + }; // Mark the instance as used in this CGU, for coverage purposes. // This includes functions that were not partitioned into this CGU, @@ -162,8 +165,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { // be smaller than the number originally inserted by the instrumentor, // if some high-numbered counters were removed by MIR optimizations. // If so, LLVM's profiler runtime will use fewer physical counters. - let num_counters = - bx.tcx().coverage_ids_info(instance.def).num_counters_after_mir_opts(); + let num_counters = ids_info.num_counters_after_mir_opts(); assert!( num_counters as usize <= function_coverage_info.num_counters, "num_counters disagreement: query says {num_counters} but function info only has {}", diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index e545ce386ed..11eb9651af6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::{Body, SourceScope}; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; -use rustc_span::{BytePos, hygiene}; +use rustc_span::{BytePos, DUMMY_SP, hygiene}; use super::metadata::file_metadata; use super::utils::DIB; @@ -85,23 +85,15 @@ fn make_mir_scope<'ll, 'tcx>( discriminators, parent, ); - if let Some(parent_scope) = debug_context.scopes[parent] { - parent_scope - } else { - // If the parent scope could not be represented then no children - // can be either. - debug_context.scopes[scope] = None; - instantiated.insert(scope); - return; - } + debug_context.scopes[parent] } else { // The root is the function itself. let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); - debug_context.scopes[scope] = Some(DebugScope { + debug_context.scopes[scope] = DebugScope { file_start_pos: file.start_pos, file_end_pos: file.end_position(), - ..debug_context.scopes[scope].unwrap() - }); + ..debug_context.scopes[scope] + }; instantiated.insert(scope); return; }; @@ -112,7 +104,7 @@ fn make_mir_scope<'ll, 'tcx>( { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. - debug_context.scopes[scope] = Some(parent_scope); + debug_context.scopes[scope] = parent_scope; instantiated.insert(scope); return; } @@ -145,14 +137,7 @@ fn make_mir_scope<'ll, 'tcx>( }, }; - let mut debug_scope = Some(DebugScope { - dbg_scope, - inlined_at: parent_scope.inlined_at, - file_start_pos: loc.file.start_pos, - file_end_pos: loc.file.end_position(), - }); - - if let Some((_, callsite_span)) = scope_data.inlined { + let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { let callsite_span = hygiene::walk_chain_collapsed(callsite_span, mir.span); let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); let loc = cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span); @@ -175,29 +160,29 @@ fn make_mir_scope<'ll, 'tcx>( // Note further that we can't key this hashtable on the span itself, // because these spans could have distinct SyntaxContexts. We have // to key on exactly what we're giving to LLVM. - let inlined_at = match discriminators.entry(callsite_span.lo()) { + match discriminators.entry(callsite_span.lo()) { Entry::Occupied(mut o) => { *o.get_mut() += 1; + // NB: We have to emit *something* here or we'll fail LLVM IR verification + // in at least some circumstances (see issue #135322) so if the required + // discriminant cannot be encoded fall back to the dummy location. unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, *o.get()) } + .unwrap_or_else(|| { + cx.dbg_loc(callsite_scope, parent_scope.inlined_at, DUMMY_SP) + }) } Entry::Vacant(v) => { v.insert(0); - Some(loc) - } - }; - match inlined_at { - Some(inlined_at) => { - debug_scope.as_mut().unwrap().inlined_at = Some(inlined_at); - } - None => { - // LLVM has a maximum discriminator that it can encode (currently - // it uses 12 bits for 4096 possible values). If we exceed that - // there is little we can do but drop the debug info. - debug_scope = None; + loc } } - } + }); - debug_context.scopes[scope] = debug_scope; + debug_context.scopes[scope] = DebugScope { + dbg_scope, + inlined_at: inlined_at.or(parent_scope.inlined_at), + file_start_pos: loc.file.start_pos, + file_end_pos: loc.file.end_position(), + }; instantiated.insert(scope); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 88e43e1c678..8d782a618fc 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -442,7 +442,7 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> // (or if there is no allocator argument). ty::Adt(def, args) if def.is_box() - && args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst()) => + && args.get(1).is_none_or(|arg| cx.layout_of(arg.expect_ty()).is_1zst()) => { build_pointer_or_reference_di_node(cx, t, t.expect_boxed_ty(), unique_type_id) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 755f4816acf..e6778411365 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -295,12 +295,12 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { } // Initialize fn debug context (including scopes). - let empty_scope = Some(DebugScope { + let empty_scope = DebugScope { dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), inlined_at: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0), - }); + }; let mut fn_debug_context = FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes), inlined_function_scopes: Default::default(), diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index c72b5b5611f..bdc83267cca 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -21,26 +21,26 @@ use tracing::debug; use crate::abi::{FnAbi, FnAbiLlvmExt}; use crate::common::AsCCharPtr; -use crate::context::CodegenCx; +use crate::context::{CodegenCx, SimpleCx}; use crate::llvm::AttributePlace::Function; use crate::llvm::Visibility; use crate::type_::Type; use crate::value::Value; use crate::{attributes, llvm}; -/// Declare a function. +/// Declare a function with a SimpleCx. /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. -pub(crate) fn declare_raw_fn<'ll>( - cx: &CodegenCx<'ll, '_>, +pub(crate) fn declare_simple_fn<'ll>( + cx: &SimpleCx<'ll>, name: &str, callconv: llvm::CallConv, unnamed: llvm::UnnamedAddr, visibility: llvm::Visibility, ty: &'ll Type, ) -> &'ll Value { - debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); + debug!("declare_simple_fn(name={:?}, ty={:?})", name, ty); let llfn = unsafe { llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_c_char_ptr(), name.len(), ty) }; @@ -49,6 +49,24 @@ pub(crate) fn declare_raw_fn<'ll>( llvm::SetUnnamedAddress(llfn, unnamed); llvm::set_visibility(llfn, visibility); + llfn +} + +/// Declare a function. +/// +/// If there’s a value with the same name already declared, the function will +/// update the declaration and return existing Value instead. +pub(crate) fn declare_raw_fn<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + callconv: llvm::CallConv, + unnamed: llvm::UnnamedAddr, + visibility: llvm::Visibility, + ty: &'ll Type, +) -> &'ll Value { + debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); + let llfn = declare_simple_fn(cx, name, callconv, unnamed, visibility, ty); + let mut attrs = SmallVec::<[_; 4]>::new(); if cx.tcx.sess.opts.cg.no_redzone.unwrap_or(cx.tcx.sess.target.disable_redzone) { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index cabcfc9b42b..eab4a9f30c9 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1081,11 +1081,11 @@ fn codegen_emcc_try<'ll>( // Helper function to give a Block to a closure to codegen a shim function. // This is currently primarily used for the `try` intrinsic functions above. -fn gen_fn<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, +fn gen_fn<'a, 'll, 'tcx>( + cx: &'a CodegenCx<'ll, 'tcx>, name: &str, rust_fn_sig: ty::PolyFnSig<'tcx>, - codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), + codegen: &mut dyn FnMut(Builder<'a, 'll, 'tcx>), ) -> (&'ll Type, &'ll Value) { let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty()); let llty = fn_abi.llvm_type(cx); @@ -1104,9 +1104,9 @@ fn gen_fn<'ll, 'tcx>( // catch exceptions. // // This function is only generated once and is then cached. -fn get_rust_try_fn<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), +fn get_rust_try_fn<'a, 'll, 'tcx>( + cx: &'a CodegenCx<'ll, 'tcx>, + codegen: &mut dyn FnMut(Builder<'a, 'll, 'tcx>), ) -> (&'ll Type, &'ll Value) { if let Some(llfn) = cx.rust_try_fn.get() { return llfn; @@ -1182,6 +1182,60 @@ fn generic_simd_intrinsic<'ll, 'tcx>( }}; } + /// Returns the bitwidth of the `$ty` argument if it is an `Int` type. + macro_rules! require_int_ty { + ($ty: expr, $diag: expr) => { + match $ty { + ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), + _ => { + return_error!($diag); + } + } + }; + } + + /// Returns the bitwidth of the `$ty` argument if it is an `Int` or `Uint` type. + macro_rules! require_int_or_uint_ty { + ($ty: expr, $diag: expr) => { + match $ty { + ty::Int(i) => i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), + ty::Uint(i) => { + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) + } + _ => { + return_error!($diag); + } + } + }; + } + + /// Converts a vector mask, where each element has a bit width equal to the data elements it is used with, + /// down to an i1 based mask that can be used by llvm intrinsics. + /// + /// The rust simd semantics are that each element should either consist of all ones or all zeroes, + /// but this information is not available to llvm. Truncating the vector effectively uses the lowest bit, + /// but codegen for several targets is better if we consider the highest bit by shifting. + /// + /// For x86 SSE/AVX targets this is beneficial since most instructions with mask parameters only consider the highest bit. + /// So even though on llvm level we have an additional shift, in the final assembly there is no shift or truncate and + /// instead the mask can be used as is. + /// + /// For aarch64 and other targets there is a benefit because a mask from the sign bit can be more + /// efficiently converted to an all ones / all zeroes mask by comparing whether each element is negative. + fn vector_mask_to_bitmask<'a, 'll, 'tcx>( + bx: &mut Builder<'a, 'll, 'tcx>, + i_xn: &'ll Value, + in_elem_bitwidth: u64, + in_len: u64, + ) -> &'ll Value { + // Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position. + let shift_idx = bx.cx.const_int(bx.type_ix(in_elem_bitwidth), (in_elem_bitwidth - 1) as _); + let shift_indices = vec![shift_idx; in_len as _]; + let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice())); + // Truncate vector to an <i1 x N> + bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len)) + } + let tcx = bx.tcx(); let sig = tcx.normalize_erasing_late_bound_regions(bx.typing_env(), callee_ty.fn_sig(tcx)); let arg_tys = sig.inputs(); @@ -1433,14 +1487,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>( m_len, v_len }); - match m_elem_ty.kind() { - ty::Int(_) => {} - _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }), - } - // truncate the mask to a vector of i1s - let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, m_len as u64); - let m_i1s = bx.trunc(args[0].immediate(), i1xn); + let in_elem_bitwidth = + require_int_ty!(m_elem_ty.kind(), InvalidMonomorphization::MaskType { + span, + name, + ty: m_elem_ty + }); + let m_i1s = vector_mask_to_bitmask(bx, args[0].immediate(), in_elem_bitwidth, m_len); return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } @@ -1457,33 +1510,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let expected_bytes = in_len.div_ceil(8); // Integer vector <i{in_bitwidth} x in_len>: - let (i_xn, in_elem_bitwidth) = match in_elem.kind() { - ty::Int(i) => ( - args[0].immediate(), - i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), - ), - ty::Uint(i) => ( - args[0].immediate(), - i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), - ), - _ => return_error!(InvalidMonomorphization::VectorArgument { + let in_elem_bitwidth = + require_int_or_uint_ty!(in_elem.kind(), InvalidMonomorphization::VectorArgument { span, name, in_ty, in_elem - }), - }; + }); - // LLVM doesn't always know the inputs are `0` or `!0`, so we shift here so it optimizes to - // `pmovmskb` and similar on x86. - let shift_indices = - vec![ - bx.cx.const_int(bx.type_ix(in_elem_bitwidth), (in_elem_bitwidth - 1) as _); - in_len as _ - ]; - let i_xn_msb = bx.lshr(i_xn, bx.const_vector(shift_indices.as_slice())); - // Truncate vector to an <i1 x N> - let i1xn = bx.trunc(i_xn_msb, bx.type_vector(bx.type_i1(), in_len)); + let i1xn = vector_mask_to_bitmask(bx, args[0].immediate(), in_elem_bitwidth, in_len); // Bitcast <i1 x N> to iN: let i_ = bx.bitcast(i1xn, bx.type_ix(in_len)); @@ -1704,28 +1739,21 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } ); - match element_ty2.kind() { - ty::Int(_) => (), - _ => { - return_error!(InvalidMonomorphization::ThirdArgElementType { - span, - name, - expected_element: element_ty2, - third_arg: arg_tys[2] - }); - } - } + let mask_elem_bitwidth = + require_int_ty!(element_ty2.kind(), InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + }); // Alignment of T, must be a constant integer value: let alignment_ty = bx.type_i32(); let alignment = bx.const_i32(bx.align_of(in_elem).bytes() as i32); // Truncate the mask vector to a vector of i1s: - let (mask, mask_ty) = { - let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, in_len); - (bx.trunc(args[2].immediate(), i1xn), i1xn) - }; + let mask = vector_mask_to_bitmask(bx, args[2].immediate(), mask_elem_bitwidth, in_len); + let mask_ty = bx.type_vector(bx.type_i1(), in_len); // Type of the vector of pointers: let llvm_pointer_vec_ty = llvm_vector_ty(bx, element_ty1, in_len); @@ -1810,27 +1838,21 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } ); - require!( - matches!(mask_elem.kind(), ty::Int(_)), - InvalidMonomorphization::ThirdArgElementType { + let m_elem_bitwidth = + require_int_ty!(mask_elem.kind(), InvalidMonomorphization::ThirdArgElementType { span, name, expected_element: values_elem, third_arg: mask_ty, - } - ); + }); + + let mask = vector_mask_to_bitmask(bx, args[0].immediate(), m_elem_bitwidth, mask_len); + let mask_ty = bx.type_vector(bx.type_i1(), mask_len); // Alignment of T, must be a constant integer value: let alignment_ty = bx.type_i32(); let alignment = bx.const_i32(bx.align_of(values_elem).bytes() as i32); - // Truncate the mask vector to a vector of i1s: - let (mask, mask_ty) = { - let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, mask_len); - (bx.trunc(args[0].immediate(), i1xn), i1xn) - }; - let llvm_pointer = bx.type_ptr(); // Type of the vector of elements: @@ -1901,27 +1923,21 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } ); - require!( - matches!(mask_elem.kind(), ty::Int(_)), - InvalidMonomorphization::ThirdArgElementType { + let m_elem_bitwidth = + require_int_ty!(mask_elem.kind(), InvalidMonomorphization::ThirdArgElementType { span, name, expected_element: values_elem, third_arg: mask_ty, - } - ); + }); + + let mask = vector_mask_to_bitmask(bx, args[0].immediate(), m_elem_bitwidth, mask_len); + let mask_ty = bx.type_vector(bx.type_i1(), mask_len); // Alignment of T, must be a constant integer value: let alignment_ty = bx.type_i32(); let alignment = bx.const_i32(bx.align_of(values_elem).bytes() as i32); - // Truncate the mask vector to a vector of i1s: - let (mask, mask_ty) = { - let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, in_len); - (bx.trunc(args[0].immediate(), i1xn), i1xn) - }; - let ret_t = bx.type_void(); let llvm_pointer = bx.type_ptr(); @@ -1995,28 +2011,21 @@ fn generic_simd_intrinsic<'ll, 'tcx>( ); // The element type of the third argument must be a signed integer type of any width: - match element_ty2.kind() { - ty::Int(_) => (), - _ => { - return_error!(InvalidMonomorphization::ThirdArgElementType { - span, - name, - expected_element: element_ty2, - third_arg: arg_tys[2] - }); - } - } + let mask_elem_bitwidth = + require_int_ty!(element_ty2.kind(), InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + }); // Alignment of T, must be a constant integer value: let alignment_ty = bx.type_i32(); let alignment = bx.const_i32(bx.align_of(in_elem).bytes() as i32); // Truncate the mask vector to a vector of i1s: - let (mask, mask_ty) = { - let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, in_len); - (bx.trunc(args[2].immediate(), i1xn), i1xn) - }; + let mask = vector_mask_to_bitmask(bx, args[2].immediate(), mask_elem_bitwidth, in_len); + let mask_ty = bx.type_vector(bx.type_i1(), in_len); let ret_t = bx.type_void(); @@ -2164,8 +2173,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>( }); args[0].immediate() } else { - match in_elem.kind() { - ty::Int(_) | ty::Uint(_) => {} + let bitwidth = match in_elem.kind() { + ty::Int(i) => { + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) + } + ty::Uint(i) => { + i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()) + } _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { span, name, @@ -2174,12 +2188,9 @@ fn generic_simd_intrinsic<'ll, 'tcx>( in_elem, ret_ty }), - } + }; - // boolean reductions operate on vectors of i1s: - let i1 = bx.type_i1(); - let i1xn = bx.type_vector(i1, in_len as u64); - bx.trunc(args[0].immediate(), i1xn) + vector_mask_to_bitmask(bx, args[0].immediate(), bitwidth, in_len as _) }; return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 06afe8bb3ad..4a84fd29e44 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -237,7 +237,6 @@ impl WriteBackendMethods for LlvmCodegenBackend { /// Generate autodiff rules fn autodiff( cgcx: &CodegenContext<Self>, - tcx: TyCtxt<'_>, module: &ModuleCodegen<Self::Module>, diff_fncs: Vec<AutoDiffItem>, config: &ModuleConfig, @@ -246,7 +245,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { let dcx = cgcx.create_dcx(); return Err(dcx.handle().emit_almost_fatal(AutoDiffWithoutLTO)); } - builder::autodiff::differentiate(module, cgcx, tcx, diff_fncs, config) + builder::autodiff::differentiate(module, cgcx, diff_fncs, config) } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index ec6c84f6f25..009d15a932f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -741,8 +741,11 @@ pub mod debuginfo { pub type DIEnumerator = DIDescriptor; pub type DITemplateTypeParameter = DIDescriptor; - // These values **must** match with LLVMRustDIFlags!! bitflags! { + /// Must match the layout of `LLVMDIFlags` in the LLVM-C API. + /// + /// Each value declared here must also be covered by the static + /// assertions in `RustWrapper.cpp` used by `fromRust(LLVMDIFlags)`. #[repr(transparent)] #[derive(Clone, Copy, Default)] pub struct DIFlags: u32 { @@ -752,7 +755,7 @@ pub mod debuginfo { const FlagPublic = 3; const FlagFwdDecl = (1 << 2); const FlagAppleBlock = (1 << 3); - const FlagBlockByrefStruct = (1 << 4); + const FlagReservedBit4 = (1 << 4); const FlagVirtual = (1 << 5); const FlagArtificial = (1 << 6); const FlagExplicit = (1 << 7); @@ -763,10 +766,21 @@ pub mod debuginfo { const FlagStaticMember = (1 << 12); const FlagLValueReference = (1 << 13); const FlagRValueReference = (1 << 14); - const FlagExternalTypeRef = (1 << 15); + const FlagReserved = (1 << 15); + const FlagSingleInheritance = (1 << 16); + const FlagMultipleInheritance = (2 << 16); + const FlagVirtualInheritance = (3 << 16); const FlagIntroducedVirtual = (1 << 18); const FlagBitField = (1 << 19); const FlagNoReturn = (1 << 20); + // The bit at (1 << 21) is unused, but was `LLVMDIFlagMainSubprogram`. + const FlagTypePassByValue = (1 << 22); + const FlagTypePassByReference = (1 << 23); + const FlagEnumClass = (1 << 24); + const FlagThunk = (1 << 25); + const FlagNonTrivial = (1 << 26); + const FlagBigEndian = (1 << 27); + const FlagLittleEndian = (1 << 28); } } @@ -918,6 +932,7 @@ unsafe extern "C" { pub fn LLVMMetadataTypeInContext(C: &Context) -> &Type; // Operations on all values + pub fn LLVMIsUndef(Val: &Value) -> Bool; pub fn LLVMTypeOf(Val: &Value) -> &Type; pub fn LLVMGetValueName2(Val: &Value, Length: *mut size_t) -> *const c_char; pub fn LLVMSetValueName2(Val: &Value, Name: *const c_char, NameLen: size_t); diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 6aec078e0de..c56ad886120 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_target::callconv::{CastTarget, FnAbi, Reg}; use crate::abi::{FnAbiLlvmExt, LlvmType}; -use crate::context::CodegenCx; +use crate::context::{CodegenCx, SimpleCx}; pub(crate) use crate::llvm::Type; use crate::llvm::{Bool, False, Metadata, True}; use crate::type_of::LayoutLlvmExt; @@ -35,7 +35,8 @@ impl fmt::Debug for Type { } } -impl<'ll> CodegenCx<'ll, '_> { +impl<'ll> CodegenCx<'ll, '_> {} +impl<'ll> SimpleCx<'ll> { pub(crate) fn type_named_struct(&self, name: &str) -> &'ll Type { let name = SmallCStr::new(name); unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) } @@ -44,11 +45,9 @@ impl<'ll> CodegenCx<'ll, '_> { pub(crate) fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) { unsafe { llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed as Bool) } } - pub(crate) fn type_void(&self) -> &'ll Type { unsafe { llvm::LLVMVoidTypeInContext(self.llcx) } } - pub(crate) fn type_token(&self) -> &'ll Type { unsafe { llvm::LLVMTokenTypeInContext(self.llcx) } } @@ -75,7 +74,8 @@ impl<'ll> CodegenCx<'ll, '_> { args } } - +} +impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { pub(crate) fn type_bool(&self) -> &'ll Type { self.type_i8() } @@ -120,7 +120,8 @@ impl<'ll> CodegenCx<'ll, '_> { assert_eq!(size % unit_size, 0); self.type_array(self.type_from_integer(unit), size / unit_size) } - +} +impl<'ll> SimpleCx<'ll> { pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) } } diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 3254b5d38e7..b22357acdc2 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" ar_archive_writer = "0.4.2" arrayvec = { version = "0.7", default-features = false } bitflags = "2.4.1" +bstr = "1.11.3" # Pinned so `cargo update` bumps don't cause breakage. Please also update the # `cc` in `rustc_llvm` if you update the `cc` here. cc = "=1.2.7" @@ -59,5 +60,5 @@ default-features = false features = ["read_core", "elf", "macho", "pe", "xcoff", "unaligned", "archive", "write", "wasm"] [target.'cfg(windows)'.dependencies.windows] -version = "0.57.0" +version = "0.59.0" features = ["Win32_Globalization"] diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 484f467068a..de37de09f5a 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -183,6 +183,8 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker codegen_ssa_linker_not_found = linker `{$linker_path}` not found .note = {$error} +codegen_ssa_linker_output = {$inner} + codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status} @@ -211,7 +213,7 @@ codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times - .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead + .help = did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point codegen_ssa_no_field = no field `{$name}` diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index ab65319e3d3..27331ce4ca6 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -46,8 +46,12 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>, set_reuse: &dyn Fn(&mut CguReuseTr return; } - let available_cgus = - tcx.collect_and_partition_mono_items(()).1.iter().map(|cgu| cgu.name()).collect(); + let available_cgus = tcx + .collect_and_partition_mono_items(()) + .codegen_units + .iter() + .map(|cgu| cgu.name()) + .collect(); let mut ams = AssertModuleSource { tcx, diff --git a/compiler/rustc_codegen_ssa/src/back/command.rs b/compiler/rustc_codegen_ssa/src/back/command.rs index b3c5b86ccf4..63023fdba20 100644 --- a/compiler/rustc_codegen_ssa/src/back/command.rs +++ b/compiler/rustc_codegen_ssa/src/back/command.rs @@ -13,6 +13,7 @@ pub(crate) struct Command { args: Vec<OsString>, env: Vec<(OsString, OsString)>, env_remove: Vec<OsString>, + env_clear: bool, } #[derive(Clone)] @@ -36,7 +37,13 @@ impl Command { } fn _new(program: Program) -> Command { - Command { program, args: Vec::new(), env: Vec::new(), env_remove: Vec::new() } + Command { + program, + args: Vec::new(), + env: Vec::new(), + env_remove: Vec::new(), + env_clear: false, + } } pub(crate) fn arg<P: AsRef<OsStr>>(&mut self, arg: P) -> &mut Command { @@ -79,6 +86,11 @@ impl Command { self } + pub(crate) fn env_clear(&mut self) -> &mut Command { + self.env_clear = true; + self + } + fn _env_remove(&mut self, key: &OsStr) { self.env_remove.push(key.to_owned()); } @@ -106,6 +118,9 @@ impl Command { for k in &self.env_remove { ret.env_remove(k); } + if self.env_clear { + ret.env_clear(); + } ret } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index df35b5e8426..105a4cb81f0 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -15,12 +15,14 @@ use rustc_ast::CRATE_NODE_ID; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; -use rustc_errors::DiagCtxtHandle; +use rustc_errors::{DiagCtxtHandle, LintDiagnostic}; use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_macros::LintDiagnostic; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; use rustc_metadata::{find_native_static_library, walk_native_lib_search_dirs}; use rustc_middle::bug; +use rustc_middle::lint::lint_level; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -29,6 +31,7 @@ use rustc_session::config::{ OutputType, PrintKind, SplitDwarfKind, Strip, }; use rustc_session::cstore::DllImport; +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; @@ -749,6 +752,14 @@ fn link_dwarf_object(sess: &Session, cg_results: &CodegenResults, executable_out } } +#[derive(LintDiagnostic)] +#[diag(codegen_ssa_linker_output)] +/// Translating this is kind of useless. We don't pass translation flags to the linker, so we'd just +/// end up with inconsistent languages within the same diagnostic. +struct LinkerOutput { + inner: String, +} + /// Create a dynamic library or executable. /// /// This will invoke the system linker/cc to create the resulting file. This links to all upstream @@ -981,6 +992,11 @@ fn link_natively( match prog { Ok(prog) => { + let is_msvc_link_exe = sess.target.is_like_msvc + && flavor == LinkerFlavor::Msvc(Lld::No) + // Match exactly "link.exe" + && linker_path.to_str() == Some("link.exe"); + if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); @@ -991,22 +1007,16 @@ fn link_natively( command: cmd, escaped_output, verbose: sess.opts.verbose, + sysroot_dir: sess.sysroot.clone(), }; sess.dcx().emit_err(err); // If MSVC's `link.exe` was expected but the return code // is not a Microsoft LNK error then suggest a way to fix or // install the Visual Studio build tools. if let Some(code) = prog.status.code() { - if sess.target.is_like_msvc - && flavor == LinkerFlavor::Msvc(Lld::No) - // Respect the command line override - && sess.opts.cg.linker.is_none() - // Match exactly "link.exe" - && linker_path.to_str() == Some("link.exe") - // All Microsoft `link.exe` linking error codes are - // four digit numbers in the range 1000 to 9999 inclusive - && (code < 1000 || code > 9999) - { + // All Microsoft `link.exe` linking ror codes are + // four digit numbers in the range 1000 to 9999 inclusive + if is_msvc_link_exe && (code < 1000 || code > 9999) { let is_vs_installed = windows_registry::find_vs_version().is_ok(); let has_linker = windows_registry::find_tool(&sess.target.arch, "link.exe").is_some(); @@ -1028,8 +1038,49 @@ fn link_natively( sess.dcx().abort_if_errors(); } - info!("linker stderr:\n{}", escape_string(&prog.stderr)); - info!("linker stdout:\n{}", escape_string(&prog.stdout)); + + let stderr = escape_string(&prog.stderr); + let mut stdout = escape_string(&prog.stdout); + info!("linker stderr:\n{}", &stderr); + info!("linker stdout:\n{}", &stdout); + + // Hide some progress messages from link.exe that we don't care about. + // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 + if is_msvc_link_exe { + if let Ok(str) = str::from_utf8(&prog.stdout) { + let mut output = String::with_capacity(str.len()); + for line in stdout.lines() { + if line.starts_with(" Creating library") + || line.starts_with("Generating code") + || line.starts_with("Finished generating code") + { + continue; + } + output += line; + output += "\r\n" + } + stdout = escape_string(output.trim().as_bytes()) + } + } + + let (level, src) = codegen_results.crate_info.lint_levels.linker_messages; + let lint = |msg| { + lint_level(sess, LINKER_MESSAGES, level, src, None, |diag| { + LinkerOutput { inner: msg }.decorate_lint(diag) + }) + }; + + if !prog.stderr.is_empty() { + // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present. + let stderr = stderr + .strip_prefix("warning: ") + .unwrap_or(&stderr) + .replace(": warning: ", ": "); + lint(format!("linker stderr: {stderr}")); + } + if !stdout.is_empty() { + lint(format!("linker stdout: {}", stdout)) + } } Err(e) => { let linker_not_found = e.kind() == io::ErrorKind::NotFound; diff --git a/compiler/rustc_codegen_ssa/src/back/lto.rs b/compiler/rustc_codegen_ssa/src/back/lto.rs index efccf7687a1..9fd984b6419 100644 --- a/compiler/rustc_codegen_ssa/src/back/lto.rs +++ b/compiler/rustc_codegen_ssa/src/back/lto.rs @@ -4,7 +4,6 @@ use std::sync::Arc; use rustc_ast::expand::autodiff_attrs::AutoDiffItem; use rustc_data_structures::memmap::Mmap; use rustc_errors::FatalError; -use rustc_middle::ty::TyCtxt; use super::write::CodegenContext; use crate::ModuleCodegen; @@ -89,13 +88,12 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> { pub unsafe fn autodiff( self, cgcx: &CodegenContext<B>, - tcx: TyCtxt<'_>, diff_fncs: Vec<AutoDiffItem>, config: &ModuleConfig, ) -> Result<LtoModuleCodegen<B>, FatalError> { match &self { LtoModuleCodegen::Fat(module) => { - B::autodiff(cgcx, tcx, &module, diff_fncs, config)?; + B::autodiff(cgcx, &module, diff_fncs, config)?; } _ => panic!("autodiff called with non-fat LTO module"), } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 60ab2919352..f8f7bb2dbc6 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -293,7 +293,7 @@ fn exported_symbols_provider_local( // external linkage is enough for monomorphization to be linked to. let need_visibility = tcx.sess.target.dynamic_linking && !tcx.sess.target.only_cdylib; - let (_, cgus) = tcx.collect_and_partition_mono_items(()); + let cgus = tcx.collect_and_partition_mono_items(()).codegen_units; // The symbols created in this loop are sorted below it #[allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 544578b29f1..e438bd70c51 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -44,7 +44,8 @@ use crate::mir::operand::OperandValue; use crate::mir::place::PlaceRef; use crate::traits::*; use crate::{ - CachedModuleCodegen, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, errors, meth, mir, + CachedModuleCodegen, CodegenLintLevels, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, + errors, meth, mir, }; pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate { @@ -490,8 +491,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let ptr_ty = cx.type_ptr(); let (arg_argc, arg_argv) = get_argc_argv(&mut bx); - let (start_fn, start_ty, args, instance) = if let EntryFnType::Main { sigpipe } = entry_type - { + let EntryFnType::Main { sigpipe } = entry_type; + let (start_fn, start_ty, args, instance) = { let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None); let start_instance = ty::Instance::expect_resolve( cx.tcx(), @@ -512,10 +513,6 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( vec![rust_main, arg_argc, arg_argv, arg_sigpipe], Some(start_instance), ) - } else { - debug!("using user-defined start fn"); - let start_ty = cx.type_func(&[isize_ty, ptr_ty], isize_ty); - (rust_main, start_ty, vec![arg_argc, arg_argv], None) }; let result = bx.call(start_ty, None, None, start_fn, &args, None, instance); @@ -530,7 +527,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } -/// Obtain the `argc` and `argv` values to pass to the rust start function. +/// Obtain the `argc` and `argv` values to pass to the rust start function +/// (i.e., the "start" lang item). fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx) -> (Bx::Value, Bx::Value) { if bx.cx().sess().target.os.contains("uefi") { // Params for UEFI @@ -621,7 +619,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>( // Run the monomorphization collector and partition the collected items into // codegen units. - let codegen_units = tcx.collect_and_partition_mono_items(()).1; + let codegen_units = tcx.collect_and_partition_mono_items(()).codegen_units; // Force all codegen_unit queries so they are already either red or green // when compile_codegen_unit accesses them. We are not able to re-execute @@ -927,6 +925,7 @@ impl CrateInfo { dependency_formats: Lrc::clone(tcx.dependency_formats(())), windows_subsystem, natvis_debugger_visualizers: Default::default(), + lint_levels: CodegenLintLevels::from_tcx(tcx), }; info.native_libraries.reserve(n_crates); @@ -1052,14 +1051,11 @@ pub(crate) fn provide(providers: &mut Providers) { config::OptLevel::SizeMin => config::OptLevel::Default, }; - let (defids, _) = tcx.collect_and_partition_mono_items(cratenum); + let defids = tcx.collect_and_partition_mono_items(cratenum).all_mono_items; let any_for_speed = defids.items().any(|id| { let CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id); - match optimize { - attr::OptimizeAttr::None | attr::OptimizeAttr::Size => false, - attr::OptimizeAttr::Speed => true, - } + matches!(optimize, attr::OptimizeAttr::Speed) }); if any_for_speed { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 1daa17fbaf3..a0bc2d4ea48 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -575,7 +575,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { codegen_fn_attrs.inline = InlineAttr::Never; } - codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::None, |ia, attr| { + codegen_fn_attrs.optimize = attrs.iter().fold(OptimizeAttr::Default, |ia, attr| { if !attr.has_name(sym::optimize) { return ia; } @@ -587,17 +587,19 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { inline_span = Some(attr.span); if items.len() != 1 { err(attr.span, "expected one argument"); - OptimizeAttr::None + OptimizeAttr::Default } else if list_contains_name(items, sym::size) { OptimizeAttr::Size } else if list_contains_name(items, sym::speed) { OptimizeAttr::Speed + } else if list_contains_name(items, sym::none) { + OptimizeAttr::DoNotOptimize } else { err(items[0].span(), "invalid argument"); - OptimizeAttr::None + OptimizeAttr::Default } } else { - OptimizeAttr::None + OptimizeAttr::Default } }); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index c7213bbc801..5e684632fb2 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -351,6 +351,7 @@ pub(crate) struct LinkingFailed<'a> { pub command: Command, pub escaped_output: String, pub verbose: bool, + pub sysroot_dir: PathBuf, } impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> { @@ -364,6 +365,8 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> { if self.verbose { diag.note(format!("{:?}", self.command)); } else { + self.command.env_clear(); + enum ArgGroup { Regular(OsString), Objects(usize), @@ -398,26 +401,55 @@ impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> { args.push(ArgGroup::Regular(arg)); } } - self.command.args(args.into_iter().map(|arg_group| match arg_group { - ArgGroup::Regular(arg) => arg, - ArgGroup::Objects(n) => OsString::from(format!("<{n} object files omitted>")), - ArgGroup::Rlibs(dir, rlibs) => { - let mut arg = dir.into_os_string(); - arg.push("/{"); - let mut first = true; - for rlib in rlibs { - if !first { - arg.push(","); + let crate_hash = regex::bytes::Regex::new(r"-[0-9a-f]+\.rlib$").unwrap(); + self.command.args(args.into_iter().map(|arg_group| { + match arg_group { + // SAFETY: we are only matching on ASCII, not any surrogate pairs, so any replacements we do will still be valid. + ArgGroup::Regular(arg) => unsafe { + use bstr::ByteSlice; + OsString::from_encoded_bytes_unchecked( + arg.as_encoded_bytes().replace( + self.sysroot_dir.as_os_str().as_encoded_bytes(), + b"<sysroot>", + ), + ) + }, + ArgGroup::Objects(n) => OsString::from(format!("<{n} object files omitted>")), + ArgGroup::Rlibs(mut dir, rlibs) => { + let is_sysroot_dir = match dir.strip_prefix(&self.sysroot_dir) { + Ok(short) => { + dir = Path::new("<sysroot>").join(short); + true + } + Err(_) => false, + }; + let mut arg = dir.into_os_string(); + arg.push("/{"); + let mut first = true; + for mut rlib in rlibs { + if !first { + arg.push(","); + } + first = false; + if is_sysroot_dir { + // SAFETY: Regex works one byte at a type, and our regex will not match surrogate pairs (because it only matches ascii). + rlib = unsafe { + OsString::from_encoded_bytes_unchecked( + crate_hash + .replace(rlib.as_encoded_bytes(), b"-*") + .into_owned(), + ) + }; + } + arg.push(rlib); } - first = false; - arg.push(rlib); + arg.push("}.rlib"); + arg } - arg.push("}"); - arg } })); - diag.note(format!("{:?}", self.command)); + diag.note(format!("{:?}", self.command).trim_start_matches("env -i").to_owned()); diag.note("some arguments are omitted. use `--verbose` to show all linker arguments"); } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 65c6067c740..40299ae2630 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -29,18 +29,23 @@ use rustc_ast as ast; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordMap; +use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::CrateNum; use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_middle::dep_graph::WorkProduct; +use rustc_middle::lint::LintLevelSource; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Dependencies; use rustc_middle::middle::exported_symbols::SymbolExportKind; +use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_serialize::opaque::{FileEncoder, MemDecoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::Session; use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_session::cstore::{self, CrateSource}; +use rustc_session::lint::Level; +use rustc_session::lint::builtin::LINKER_MESSAGES; use rustc_session::utils::NativeLibKind; use rustc_span::Symbol; @@ -200,6 +205,7 @@ pub struct CrateInfo { pub dependency_formats: Lrc<Dependencies>, pub windows_subsystem: Option<String>, pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>, + pub lint_levels: CodegenLintLevels, } #[derive(Encodable, Decodable)] @@ -302,3 +308,19 @@ impl CodegenResults { Ok((codegen_results, outputs)) } } + +/// A list of lint levels used in codegen. +/// +/// When using `-Z link-only`, we don't have access to the tcx and must work +/// solely from the `.rlink` file. `Lint`s are defined too early to be encodeable. +/// Instead, encode exactly the information we need. +#[derive(Copy, Clone, Debug, Encodable, Decodable)] +pub struct CodegenLintLevels { + linker_messages: (Level, LintLevelSource), +} + +impl CodegenLintLevels { + pub fn from_tcx(tcx: TyCtxt<'_>) -> Self { + Self { linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID) } + } +} diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs index 843a996d2bf..5924c8991ad 100644 --- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs @@ -19,9 +19,7 @@ use crate::traits::*; pub struct FunctionDebugContext<'tcx, S, L> { /// Maps from source code to the corresponding debug info scope. - /// May be None if the backend is not capable of representing the scope for - /// some reason. - pub scopes: IndexVec<mir::SourceScope, Option<DebugScope<S, L>>>, + pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>, /// Maps from an inlined function to its debug info declaration. pub inlined_function_scopes: FxHashMap<Instance<'tcx>, S>, @@ -232,7 +230,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &self, source_info: mir::SourceInfo, ) -> Option<(Bx::DIScope, Option<Bx::DILocation>, Span)> { - let scope = &self.debug_context.as_ref()?.scopes[source_info.scope]?; + let scope = &self.debug_context.as_ref()?.scopes[source_info.scope]; let span = hygiene::walk_chain_collapsed(source_info.span, self.mir.span); Some((scope.adjust_dbg_scope_for_span(self.cx, span), scope.inlined_at, span)) } diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 8df270abc81..dc406809874 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -1,10 +1,14 @@ +use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind}; use rustc_attr_parsing::InstructionSetAttr; +use rustc_hir::def_id::DefId; use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility}; use rustc_middle::mir::{Body, InlineAsmOperand}; -use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf}; -use rustc_middle::ty::{Instance, TyCtxt}; -use rustc_middle::{bug, ty}; +use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; +use rustc_middle::ty::{Instance, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug, ty}; use rustc_span::sym; +use rustc_target::callconv::{ArgAbi, FnAbi, PassMode}; +use rustc_target::spec::WasmCAbi; use crate::common; use crate::traits::{AsmCodegenMethods, BuilderMethods, GlobalAsmOperandRef, MiscCodegenMethods}; @@ -32,7 +36,8 @@ pub(crate) fn codegen_naked_asm<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let item_data = cx.codegen_unit().items().get(&MonoItem::Fn(instance)).unwrap(); let name = cx.mangled_name(instance); - let (begin, end) = prefix_and_suffix(cx.tcx(), instance, &name, item_data); + let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty()); + let (begin, end) = prefix_and_suffix(cx.tcx(), instance, &name, item_data, fn_abi); let mut template_vec = Vec::new(); template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(begin.into())); @@ -103,6 +108,7 @@ enum AsmBinaryFormat { Elf, Macho, Coff, + Wasm, } impl AsmBinaryFormat { @@ -111,6 +117,8 @@ impl AsmBinaryFormat { Self::Coff } else if target.is_like_osx { Self::Macho + } else if target.is_like_wasm { + Self::Wasm } else { Self::Elf } @@ -122,6 +130,7 @@ fn prefix_and_suffix<'tcx>( instance: Instance<'tcx>, asm_name: &str, item_data: &MonoItemData, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> (String, String) { use std::fmt::Write; @@ -169,7 +178,7 @@ fn prefix_and_suffix<'tcx>( } Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR => { match asm_binary_format { - AsmBinaryFormat::Elf | AsmBinaryFormat::Coff => { + AsmBinaryFormat::Elf | AsmBinaryFormat::Coff | AsmBinaryFormat::Wasm => { writeln!(w, ".weak {asm_name}")?; } AsmBinaryFormat::Macho => { @@ -264,7 +273,161 @@ fn prefix_and_suffix<'tcx>( writeln!(end, "{}", arch_suffix).unwrap(); } } + AsmBinaryFormat::Wasm => { + let section = link_section.unwrap_or(format!(".text.{asm_name}")); + + writeln!(begin, ".section {section},\"\",@").unwrap(); + // wasm functions cannot be aligned, so skip + write_linkage(&mut begin).unwrap(); + if let Visibility::Hidden = item_data.visibility { + writeln!(begin, ".hidden {asm_name}").unwrap(); + } + writeln!(begin, ".type {asm_name}, @function").unwrap(); + if !arch_prefix.is_empty() { + writeln!(begin, "{}", arch_prefix).unwrap(); + } + writeln!(begin, "{asm_name}:").unwrap(); + writeln!( + begin, + ".functype {asm_name} {}", + wasm_functype(tcx, fn_abi, instance.def_id()) + ) + .unwrap(); + + writeln!(end).unwrap(); + // .size is ignored for function symbols, so we can skip it + writeln!(end, "end_function").unwrap(); + } } (begin, end) } + +/// The webassembly type signature for the given function. +/// +/// Used by the `.functype` directive on wasm targets. +fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id: DefId) -> String { + let mut signature = String::with_capacity(64); + + let ptr_type = match tcx.data_layout.pointer_size.bits() { + 32 => "i32", + 64 => "i64", + other => bug!("wasm pointer size cannot be {other} bits"), + }; + + // FIXME: remove this once the wasm32-unknown-unknown ABI is fixed + // please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs` + // basically the commit introducing this comment should be reverted + if let PassMode::Pair { .. } = fn_abi.ret.mode { + let _ = WasmCAbi::Legacy; + span_bug!( + tcx.def_span(def_id), + "cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666" + ); + } + + let hidden_return = matches!(fn_abi.ret.mode, PassMode::Indirect { .. }); + + signature.push('('); + + if hidden_return { + signature.push_str(ptr_type); + if !fn_abi.args.is_empty() { + signature.push_str(", "); + } + } + + let mut it = fn_abi.args.iter().peekable(); + while let Some(arg_abi) = it.next() { + wasm_type(tcx, &mut signature, arg_abi, ptr_type, def_id); + if it.peek().is_some() { + signature.push_str(", "); + } + } + + signature.push_str(") -> ("); + + if !hidden_return { + wasm_type(tcx, &mut signature, &fn_abi.ret, ptr_type, def_id); + } + + signature.push(')'); + + signature +} + +fn wasm_type<'tcx>( + tcx: TyCtxt<'tcx>, + signature: &mut String, + arg_abi: &ArgAbi<'_, Ty<'tcx>>, + ptr_type: &'static str, + def_id: DefId, +) { + match arg_abi.mode { + PassMode::Ignore => { /* do nothing */ } + PassMode::Direct(_) => { + let direct_type = match arg_abi.layout.backend_repr { + BackendRepr::Scalar(scalar) => wasm_primitive(scalar.primitive(), ptr_type), + BackendRepr::Vector { .. } => "v128", + BackendRepr::Memory { .. } => { + // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed + let _ = WasmCAbi::Legacy; + span_bug!( + tcx.def_span(def_id), + "cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666" + ); + } + other => unreachable!("unexpected BackendRepr: {:?}", other), + }; + + signature.push_str(direct_type); + } + PassMode::Pair(_, _) => match arg_abi.layout.backend_repr { + BackendRepr::ScalarPair(a, b) => { + signature.push_str(wasm_primitive(a.primitive(), ptr_type)); + signature.push_str(", "); + signature.push_str(wasm_primitive(b.primitive(), ptr_type)); + } + other => unreachable!("{other:?}"), + }, + PassMode::Cast { pad_i32, ref cast } => { + // For wasm, Cast is used for single-field primitive wrappers like `struct Wrapper(i64);` + assert!(!pad_i32, "not currently used by wasm calling convention"); + assert!(cast.prefix[0].is_none(), "no prefix"); + assert_eq!(cast.rest.total, arg_abi.layout.size, "single item"); + + let wrapped_wasm_type = match cast.rest.unit.kind { + RegKind::Integer => match cast.rest.unit.size.bytes() { + ..=4 => "i32", + ..=8 => "i64", + _ => ptr_type, + }, + RegKind::Float => match cast.rest.unit.size.bytes() { + ..=4 => "f32", + ..=8 => "f64", + _ => ptr_type, + }, + RegKind::Vector => "v128", + }; + + signature.push_str(wrapped_wasm_type); + } + PassMode::Indirect { .. } => signature.push_str(ptr_type), + } +} + +fn wasm_primitive(primitive: Primitive, ptr_type: &'static str) -> &'static str { + match primitive { + Primitive::Int(integer, _) => match integer { + Integer::I8 | Integer::I16 | Integer::I32 => "i32", + Integer::I64 => "i64", + Integer::I128 => "i64, i64", + }, + Primitive::Float(float) => match float { + Float::F16 | Float::F32 => "f32", + Float::F64 => "f64", + Float::F128 => "i64, i64", + }, + Primitive::Pointer(_) => ptr_type, + } +} diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 19101ec2d1b..9ca7d4f8f00 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -204,14 +204,30 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let alloc_align = alloc.inner().align; assert!(alloc_align >= layout.align.abi); + // Returns `None` when the value is partially undefined or any byte of it has provenance. + // Otherwise returns the value or (if the entire value is undef) returns an undef. let read_scalar = |start, size, s: abi::Scalar, ty| { + let range = alloc_range(start, size); match alloc.0.read_scalar( bx, - alloc_range(start, size), + range, /*read_provenance*/ matches!(s.primitive(), abi::Primitive::Pointer(_)), ) { - Ok(val) => bx.scalar_to_backend(val, s, ty), - Err(_) => bx.const_poison(ty), + Ok(val) => Some(bx.scalar_to_backend(val, s, ty)), + Err(_) => { + // We may have failed due to partial provenance or unexpected provenance, + // continue down the normal code path if so. + if alloc.0.provenance().range_empty(range, &bx.tcx()) + // Since `read_scalar` failed, but there were no relocations involved, the + // bytes must be partially or fully uninitialized. Thus we can now unwrap the + // information about the range of uninit bytes and check if it's the full range. + && alloc.0.init_mask().is_range_initialized(range).unwrap_err() == range + { + Some(bx.const_undef(ty)) + } else { + None + } + } } }; @@ -222,16 +238,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { // check that walks over the type of `mplace` to make sure it is truly correct to treat this // like a `Scalar` (or `ScalarPair`). match layout.backend_repr { - BackendRepr::Scalar(s @ abi::Scalar::Initialized { .. }) => { + BackendRepr::Scalar(s) => { let size = s.size(bx); assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); - let val = read_scalar(offset, size, s, bx.immediate_backend_type(layout)); - OperandRef { val: OperandValue::Immediate(val), layout } + if let Some(val) = read_scalar(offset, size, s, bx.immediate_backend_type(layout)) { + return OperandRef { val: OperandValue::Immediate(val), layout }; + } } - BackendRepr::ScalarPair( - a @ abi::Scalar::Initialized { .. }, - b @ abi::Scalar::Initialized { .. }, - ) => { + BackendRepr::ScalarPair(a, b) => { let (a_size, b_size) = (a.size(bx), b.size(bx)); let b_offset = (offset + a_size).align_to(b.align(bx).abi); assert!(b_offset.bytes() > 0); @@ -247,20 +261,21 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { b, bx.scalar_pair_element_backend_type(layout, 1, true), ); - OperandRef { val: OperandValue::Pair(a_val, b_val), layout } - } - _ if layout.is_zst() => OperandRef::zero_sized(layout), - _ => { - // Neither a scalar nor scalar pair. Load from a place - // FIXME: should we cache `const_data_from_alloc` to avoid repeating this for the - // same `ConstAllocation`? - let init = bx.const_data_from_alloc(alloc); - let base_addr = bx.static_addr_of(init, alloc_align, None); - - let llval = bx.const_ptr_byte_offset(base_addr, offset); - bx.load_operand(PlaceRef::new_sized(llval, layout)) + if let (Some(a_val), Some(b_val)) = (a_val, b_val) { + return OperandRef { val: OperandValue::Pair(a_val, b_val), layout }; + } } + _ if layout.is_zst() => return OperandRef::zero_sized(layout), + _ => {} } + // Neither a scalar nor scalar pair. Load from a place + // FIXME: should we cache `const_data_from_alloc` to avoid repeating this for the + // same `ConstAllocation`? + let init = bx.const_data_from_alloc(alloc); + let base_addr = bx.static_addr_of(init, alloc_align, None); + + let llval = bx.const_ptr_byte_offset(base_addr, offset); + bx.load_operand(PlaceRef::new_sized(llval, layout)) } /// Asserts that this operand refers to a scalar and returns diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index eb4ef599b82..e775d219c7b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug}; use rustc_session::config::OptLevel; use rustc_span::{DUMMY_SP, Span}; -use tracing::{debug, instrument}; +use tracing::{debug, instrument, trace}; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; @@ -93,6 +93,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } + // If `v` is an integer constant whose value is just a single byte repeated N times, + // emit a `memset` filling the entire `dest` with that byte. let try_init_all_same = |bx: &mut Bx, v| { let start = dest.val.llval; let size = bx.const_usize(dest.layout.size.bytes()); @@ -117,13 +119,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { false }; + trace!(?cg_elem.val); match cg_elem.val { OperandValue::Immediate(v) => { if try_init_all_same(bx, v) { return; } } - _ => (), + OperandValue::Pair(a, b) => { + let a_is_undef = bx.cx().is_undef(a); + match (a_is_undef, bx.cx().is_undef(b)) { + // Can happen for uninit unions + (true, true) => { + // FIXME: can we produce better output here? + } + (false, true) | (true, false) => { + let val = if a_is_undef { b } else { a }; + if try_init_all_same(bx, val) { + return; + } + } + (false, false) => { + // FIXME: if both are the same value, use try_init_all_same + } + } + } + OperandValue::ZeroSized => unreachable!("checked above"), + OperandValue::Ref(..) => {} } let count = self @@ -365,10 +387,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { use abi::Primitive::*; imm = bx.from_immediate(imm); - // When scalars are passed by value, there's no metadata recording their - // valid ranges. For example, `char`s are passed as just `i32`, with no - // way for LLVM to know that they're 0x10FFFF at most. Thus we assume - // the range of the input value too, not just the output range. + // If we have a scalar, we must already know its range. Either + // + // 1) It's a parameter with `range` parameter metadata, + // 2) It's something we `load`ed with `!range` metadata, or + // 3) After a transmute we `assume`d the range (see below). + // + // That said, last time we tried removing this, it didn't actually help + // the rustc-perf results, so might as well keep doing it + // <https://github.com/rust-lang/rust/pull/135610#issuecomment-2599275182> self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty); imm = match (from_scalar.primitive(), to_scalar.primitive()) { @@ -389,7 +416,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.bitcast(int_imm, to_backend_ty) } }; + + // This `assume` remains important for cases like (a conceptual) + // transmute::<u32, NonZeroU32>(x) == 0 + // since it's never passed to something with parameter metadata (especially + // after MIR inlining) so the only way to tell the backend about the + // constraint that the `transmute` introduced is to `assume` it. self.assume_scalar_range(bx, imm, to_scalar, to_backend_ty); + imm = bx.to_immediate_scalar(imm, to_scalar); imm } @@ -411,31 +445,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return; } - let abi::WrappingRange { start, end } = scalar.valid_range(self.cx); - - if start <= end { - if start > 0 { - let low = bx.const_uint_big(backend_ty, start); - let cmp = bx.icmp(IntPredicate::IntUGE, imm, low); - bx.assume(cmp); - } - - let type_max = scalar.size(self.cx).unsigned_int_max(); - if end < type_max { - let high = bx.const_uint_big(backend_ty, end); - let cmp = bx.icmp(IntPredicate::IntULE, imm, high); - bx.assume(cmp); - } - } else { - let low = bx.const_uint_big(backend_ty, start); - let cmp_low = bx.icmp(IntPredicate::IntUGE, imm, low); - - let high = bx.const_uint_big(backend_ty, end); - let cmp_high = bx.icmp(IntPredicate::IntULE, imm, high); - - let or = bx.or(cmp_low, cmp_high); - bx.assume(or); - } + let range = scalar.valid_range(self.cx); + bx.assume_integer_range(imm, backend_ty, range); } pub(crate) fn codegen_rvalue_unsized( diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 3ee13b19f66..bbf87a59942 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -217,6 +217,27 @@ pub trait BuilderMethods<'a, 'tcx>: dest: PlaceRef<'tcx, Self::Value>, ); + /// Emits an `assume` that the integer value `imm` of type `ty` is contained in `range`. + /// + /// This *always* emits the assumption, so you probably want to check the + /// optimization level and `Scalar::is_always_valid` before calling it. + fn assume_integer_range(&mut self, imm: Self::Value, ty: Self::Type, range: WrappingRange) { + let WrappingRange { start, end } = range; + + // Perhaps one day we'll be able to use assume operand bundles for this, + // but for now this encoding with a single icmp+assume is best per + // <https://github.com/llvm/llvm-project/issues/123278#issuecomment-2597440158> + let shifted = if start == 0 { + imm + } else { + let low = self.const_uint_big(ty, start); + self.sub(imm, low) + }; + let width = self.const_uint_big(ty, u128::wrapping_sub(end, start)); + let cmp = self.icmp(IntPredicate::IntULE, shifted, width); + self.assume(cmp); + } + fn range_metadata(&mut self, load: Self::Value, range: WrappingRange); fn nonnull_metadata(&mut self, load: Self::Value); diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index 9af463a691a..d0de7ff0b5f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -9,6 +9,7 @@ pub trait ConstCodegenMethods<'tcx>: BackendTypes { /// Generate an uninitialized value (matching uninitialized memory in MIR). /// Whether memory is initialized or not is tracked byte-for-byte. fn const_undef(&self, t: Self::Type) -> Self::Value; + fn is_undef(&self, v: Self::Value) -> bool; /// Generate a fake value. Poison always affects the entire value, even if just a single byte is /// poison. This can only be used in codepaths that are already UB, i.e., UB-free Rust code /// (including code that e.g. copies uninit memory with `MaybeUninit`) can never encounter a diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs index 51e2255efe1..97fe614aa10 100644 --- a/compiler/rustc_codegen_ssa/src/traits/write.rs +++ b/compiler/rustc_codegen_ssa/src/traits/write.rs @@ -1,7 +1,6 @@ use rustc_ast::expand::autodiff_attrs::AutoDiffItem; use rustc_errors::{DiagCtxtHandle, FatalError}; use rustc_middle::dep_graph::WorkProduct; -use rustc_middle::ty::TyCtxt; use crate::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use crate::back::write::{CodegenContext, FatLtoInput, ModuleConfig}; @@ -65,7 +64,6 @@ pub trait WriteBackendMethods: 'static + Sized + Clone { fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer); fn autodiff( cgcx: &CodegenContext<Self>, - tcx: TyCtxt<'_>, module: &ModuleCodegen<Self::Module>, diff_fncs: Vec<AutoDiffItem>, config: &ModuleConfig, diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index d4bfb781320..485c8696342 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -416,7 +416,7 @@ const_eval_unsized_local = unsized locals are not supported const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn const_eval_unstable_in_stable_exposed = const function that might be (indirectly) exposed to stable cannot use `#[feature({$gate})]` - .is_function_call = mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + .is_function_call = mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features .unstable_sugg = if the {$is_function_call2 -> [true] caller *[false] function diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index fee7287951d..cc21a18af3a 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -140,7 +140,7 @@ where // Don't emit a new diagnostic for these errors, they are already reported elsewhere or // should remain silent. err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span), - err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { + err_inval!(Layout(LayoutError::TooGeneric(_))) | err_inval!(TooGeneric) => { ErrorHandled::TooGeneric(span) } err_inval!(Layout(LayoutError::ReferencesError(guar))) => { diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index c8ecddb046c..889a8299c18 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -32,7 +32,7 @@ tracing = "0.1" version = "0.12" [target.'cfg(windows)'.dependencies.windows] -version = "0.57.0" +version = "0.59.0" features = [ "Win32_Foundation", "Win32_Storage_FileSystem", diff --git a/compiler/rustc_data_structures/src/flock/windows.rs b/compiler/rustc_data_structures/src/flock/windows.rs index 9739e501272..e761faee67b 100644 --- a/compiler/rustc_data_structures/src/flock/windows.rs +++ b/compiler/rustc_data_structures/src/flock/windows.rs @@ -60,9 +60,9 @@ impl Lock { unsafe { LockFileEx( - HANDLE(file.as_raw_handle() as isize), + HANDLE(file.as_raw_handle()), flags, - 0, + None, u32::MAX, u32::MAX, &mut overlapped, diff --git a/compiler/rustc_data_structures/src/graph/mod.rs b/compiler/rustc_data_structures/src/graph/mod.rs index 92035e8bc48..4a1e5db6768 100644 --- a/compiler/rustc_data_structures/src/graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/mod.rs @@ -14,7 +14,23 @@ mod tests; pub trait DirectedGraph { type Node: Idx; + /// Returns the total number of nodes in this graph. + /// + /// Several graph algorithm implementations assume that every node ID is + /// strictly less than the number of nodes, i.e. nodes are densely numbered. + /// That assumption allows them to use `num_nodes` to allocate per-node + /// data structures, indexed by node. fn num_nodes(&self) -> usize; + + /// Iterates over all nodes of a graph in ascending numeric order. + /// + /// Assumes that nodes are densely numbered, i.e. every index in + /// `0..num_nodes` is a valid node. + fn iter_nodes( + &self, + ) -> impl Iterator<Item = Self::Node> + DoubleEndedIterator + ExactSizeIterator { + (0..self.num_nodes()).map(<Self::Node as Idx>::new) + } } pub trait NumEdges: DirectedGraph { diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index 06fedef00fc..93f6192b10b 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -333,8 +333,8 @@ where to_annotation, }; - let scc_indices = (0..num_nodes) - .map(G::Node::new) + let scc_indices = graph + .iter_nodes() .map(|node| match this.start_walk_from(node) { WalkReturn::Complete { scc_index, .. } => scc_index, WalkReturn::Cycle { min_depth, .. } => { diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 2f0fe64b096..07b88e59723 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -59,7 +59,7 @@ libc = "0.2" # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] -version = "0.57.0" +version = "0.59.0" features = [ "Win32_System_Diagnostics_Debug", ] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index f7e7aa64614..20be2144609 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -28,8 +28,8 @@ use std::io::{self, IsTerminal, Read, Write}; use std::panic::{self, PanicHookInfo, catch_unwind}; use std::path::{Path, PathBuf}; use std::process::{self, Command, Stdio}; +use std::sync::OnceLock; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, OnceLock}; use std::time::{Instant, SystemTime}; use std::{env, str}; @@ -53,14 +53,13 @@ use rustc_middle::ty::TyCtxt; use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::config::{ CG_OPTIONS, ErrorOutputType, Input, OptionDesc, OutFileName, OutputType, UnstableOptions, - Z_OPTIONS, nightly_options, + Z_OPTIONS, nightly_options, parse_target_triple, }; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; use rustc_session::output::collect_crate_types; use rustc_session::{EarlyDiagCtxt, Session, config, filesearch}; use rustc_span::FileName; -use rustc_span::source_map::FileLoader; use rustc_target::json::ToJson; use rustc_target::spec::{Target, TargetTuple}; use time::OffsetDateTime; @@ -208,84 +207,7 @@ pub fn diagnostics_registry() -> Registry { } /// This is the primary entry point for rustc. -pub struct RunCompiler<'a> { - at_args: &'a [String], - callbacks: &'a mut (dyn Callbacks + Send), - file_loader: Option<Box<dyn FileLoader + Send + Sync>>, - make_codegen_backend: - Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>, - using_internal_features: Arc<std::sync::atomic::AtomicBool>, -} - -impl<'a> RunCompiler<'a> { - pub fn new(at_args: &'a [String], callbacks: &'a mut (dyn Callbacks + Send)) -> Self { - Self { - at_args, - callbacks, - file_loader: None, - make_codegen_backend: None, - using_internal_features: Arc::default(), - } - } - - /// Set a custom codegen backend. - /// - /// Has no uses within this repository, but is used by bjorn3 for "the - /// hotswapping branch of cg_clif" for "setting the codegen backend from a - /// custom driver where the custom codegen backend has arbitrary data." - /// (See #102759.) - pub fn set_make_codegen_backend( - &mut self, - make_codegen_backend: Option< - Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>, - >, - ) -> &mut Self { - self.make_codegen_backend = make_codegen_backend; - self - } - - /// Load files from sources other than the file system. - /// - /// Has no uses within this repository, but may be used in the future by - /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for - /// running rustc without having to save". (See #102759.) - pub fn set_file_loader( - &mut self, - file_loader: Option<Box<dyn FileLoader + Send + Sync>>, - ) -> &mut Self { - self.file_loader = file_loader; - self - } - - /// Set the session-global flag that checks whether internal features have been used, - /// suppressing the message about submitting an issue in ICEs when enabled. - #[must_use] - pub fn set_using_internal_features(mut self, using_internal_features: Arc<AtomicBool>) -> Self { - self.using_internal_features = using_internal_features; - self - } - - /// Parse args and run the compiler. - pub fn run(self) { - run_compiler( - self.at_args, - self.callbacks, - self.file_loader, - self.make_codegen_backend, - self.using_internal_features, - ); - } -} - -fn run_compiler( - at_args: &[String], - callbacks: &mut (dyn Callbacks + Send), - file_loader: Option<Box<dyn FileLoader + Send + Sync>>, - make_codegen_backend: Option< - Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>, - >, - using_internal_features: Arc<std::sync::atomic::AtomicBool>, -) { +pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) { let mut default_early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); // Throw away the first argument, the name of the binary. @@ -322,16 +244,16 @@ fn run_compiler( output_file: ofile, output_dir: odir, ice_file, - file_loader, + file_loader: None, locale_resources: DEFAULT_LOCALE_RESOURCES.to_vec(), lint_caps: Default::default(), psess_created: None, hash_untracked_state: None, register_lints: None, override_queries: None, - make_codegen_backend, + make_codegen_backend: None, registry: diagnostics_registry(), - using_internal_features, + using_internal_features: &USING_INTERNAL_FEATURES, expanded_args: args, }; @@ -916,13 +838,7 @@ pub fn version_at_macro_invocation( safe_println!("host: {}", config::host_tuple()); safe_println!("release: {release}"); - let debug_flags = matches.opt_strs("Z"); - let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); - let opts = config::Options::default(); - let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone()); - let target = config::build_target_config(early_dcx, &opts, &sysroot); - - get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_version(); + get_backend_from_raw_matches(early_dcx, matches).print_version(); } } @@ -1125,19 +1041,32 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) -> } if cg_flags.iter().any(|x| *x == "passes=list") { - let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); - - let opts = config::Options::default(); - let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone()); - let target = config::build_target_config(early_dcx, &opts, &sysroot); - - get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_passes(); + get_backend_from_raw_matches(early_dcx, matches).print_passes(); return true; } false } +/// Get the codegen backend based on the raw [`Matches`]. +/// +/// `rustc -vV` and `rustc -Cpasses=list` need to get the codegen backend before we have parsed all +/// arguments and created a [`Session`]. This function reads `-Zcodegen-backend`, `--target` and +/// `--sysroot` without validating any other arguments and loads the codegen backend based on these +/// arguments. +fn get_backend_from_raw_matches( + early_dcx: &EarlyDiagCtxt, + matches: &Matches, +) -> Box<dyn CodegenBackend> { + let debug_flags = matches.opt_strs("Z"); + let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); + let target = parse_target_triple(early_dcx, matches); + let sysroot = filesearch::materialize_sysroot(matches.opt_str("sysroot").map(PathBuf::from)); + let target = config::build_target_config(early_dcx, &target, &sysroot); + + get_codegen_backend(early_dcx, &sysroot, backend_name, &target) +} + fn describe_debug_flags() { safe_println!("\nAvailable options:\n"); print_flag_list("-Z", config::Z_OPTIONS); @@ -1343,6 +1272,8 @@ fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option<Pat }) } +pub static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false); + /// Installs a panic hook that will print the ICE message on unexpected panics. /// /// The hook is intended to be useable even by external tools. You can pass a custom @@ -1353,15 +1284,8 @@ fn ice_path_with_config(config: Option<&UnstableOptions>) -> &'static Option<Pat /// If you have no extra info to report, pass the empty closure `|_| ()` as the argument to /// extra_info. /// -/// Returns a flag that can be set to disable the note for submitting a bug. This can be passed to -/// [`RunCompiler::set_using_internal_features`] to let macro expansion set it when encountering -/// internal features. -/// /// A custom rustc driver can skip calling this to set up a custom ICE hook. -pub fn install_ice_hook( - bug_report_url: &'static str, - extra_info: fn(&DiagCtxt), -) -> Arc<AtomicBool> { +pub fn install_ice_hook(bug_report_url: &'static str, extra_info: fn(&DiagCtxt)) { // If the user has not explicitly overridden "RUST_BACKTRACE", then produce // full backtraces. When a compiler ICE happens, we want to gather // as much information as possible to present in the issue opened @@ -1378,8 +1302,6 @@ pub fn install_ice_hook( } } - let using_internal_features = Arc::new(std::sync::atomic::AtomicBool::default()); - let using_internal_features_hook = Arc::clone(&using_internal_features); panic::update_hook(Box::new( move |default_hook: &(dyn Fn(&PanicHookInfo<'_>) + Send + Sync + 'static), info: &PanicHookInfo<'_>| { @@ -1431,11 +1353,9 @@ pub fn install_ice_hook( } // Print the ICE message - report_ice(info, bug_report_url, extra_info, &using_internal_features_hook); + report_ice(info, bug_report_url, extra_info, &USING_INTERNAL_FEATURES); }, )); - - using_internal_features } /// Prints the ICE message, including query stack, but without backtrace. @@ -1521,9 +1441,9 @@ fn report_ice( // If backtraces are enabled, also print the query stack let backtrace = env::var_os("RUST_BACKTRACE").is_some_and(|x| &x != "0"); - let num_frames = if backtrace { None } else { Some(2) }; + let limit_frames = if backtrace { None } else { Some(2) }; - interface::try_print_query_stack(dcx, num_frames, file); + interface::try_print_query_stack(dcx, limit_frames, file); // We don't trust this callback not to panic itself, so run it at the end after we're sure we've // printed all the relevant info. @@ -1576,13 +1496,11 @@ pub fn main() -> ! { init_rustc_env_logger(&early_dcx); signal_handler::install(); let mut callbacks = TimePassesCallbacks::default(); - let using_internal_features = install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); + install_ice_hook(DEFAULT_BUG_REPORT_URL, |_| ()); install_ctrlc_handler(); let exit_code = catch_with_exit_code(|| { - RunCompiler::new(&args::raw_args(&early_dcx)?, &mut callbacks) - .set_using_internal_features(using_internal_features) - .run(); + run_compiler(&args::raw_args(&early_dcx)?, &mut callbacks); Ok(()) }); diff --git a/compiler/rustc_error_codes/src/error_codes/E0038.md b/compiler/rustc_error_codes/src/error_codes/E0038.md index 014d8c4f761..4b06395897a 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0038.md +++ b/compiler/rustc_error_codes/src/error_codes/E0038.md @@ -264,15 +264,15 @@ trait Foo { ### Trait contains associated constants Just like static functions, associated constants aren't stored on the method -table. If the trait or any subtrait contain an associated constant, they cannot -be made into an object. +table. If the trait or any subtrait contain an associated constant, they are not +dyn compatible. ```compile_fail,E0038 trait Foo { const X: i32; } -impl Foo {} +impl dyn Foo {} ``` A simple workaround is to use a helper method instead: diff --git a/compiler/rustc_error_codes/src/error_codes/E0132.md b/compiler/rustc_error_codes/src/error_codes/E0132.md index 51258739b89..cbb14510ed7 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0132.md +++ b/compiler/rustc_error_codes/src/error_codes/E0132.md @@ -1,32 +1,3 @@ -A function with the `start` attribute was declared with type parameters. - -Erroneous code example: - -```compile_fail,E0132 -#![feature(start)] - -#[start] -fn f<T>() {} -``` - -It is not possible to declare type parameters on a function that has the `start` -attribute. Such a function must have the following type signature (for more -information, view [the unstable book][1]): +#### Note: this error code is no longer emitted by the compiler. -[1]: https://doc.rust-lang.org/unstable-book/language-features/start.html - -``` -# let _: -fn(isize, *const *const u8) -> isize; -``` - -Example: - -``` -#![feature(start)] - -#[start] -fn my_start(argc: isize, argv: *const *const u8) -> isize { - 0 -} -``` +A function with the `start` attribute was declared with type parameters. diff --git a/compiler/rustc_error_codes/src/error_codes/E0138.md b/compiler/rustc_error_codes/src/error_codes/E0138.md index 3f5eaea9f98..2e6ba546a16 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0138.md +++ b/compiler/rustc_error_codes/src/error_codes/E0138.md @@ -1,25 +1,3 @@ -More than one function was declared with the `#[start]` attribute. - -Erroneous code example: - -```compile_fail,E0138 -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize {} +#### Note: this error code is no longer emitted by the compiler. -#[start] -fn f(argc: isize, argv: *const *const u8) -> isize {} -// error: multiple 'start' functions -``` - -This error indicates that the compiler found multiple functions with the -`#[start]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! -``` +More than one function was declared with the `#[start]` attribute. diff --git a/compiler/rustc_error_codes/src/error_codes/E0393.md b/compiler/rustc_error_codes/src/error_codes/E0393.md index 50225b25163..c7260815905 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0393.md +++ b/compiler/rustc_error_codes/src/error_codes/E0393.md @@ -3,12 +3,10 @@ A type parameter which references `Self` in its default value was not specified. Erroneous code example: ```compile_fail,E0393 -trait A<T=Self> {} +trait A<T = Self> {} -fn together_we_will_rule_the_galaxy(son: &A) {} -// error: the type parameter `T` must be explicitly specified in an -// object type because its default value `Self` references the -// type `Self` +fn together_we_will_rule_the_galaxy(son: &dyn A) {} +// error: the type parameter `T` must be explicitly specified ``` A trait object is defined over a single, fully-defined trait. With a regular @@ -23,7 +21,7 @@ disallowed. Making the trait concrete by explicitly specifying the value of the defaulted parameter will fix this issue. Fixed example: ``` -trait A<T=Self> {} +trait A<T = Self> {} -fn together_we_will_rule_the_galaxy(son: &A<i32>) {} // Ok! +fn together_we_will_rule_the_galaxy(son: &dyn A<i32>) {} // Ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0433.md b/compiler/rustc_error_codes/src/error_codes/E0433.md index 5a64c13c9af..36e4b66e8dc 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0433.md +++ b/compiler/rustc_error_codes/src/error_codes/E0433.md @@ -19,7 +19,7 @@ If you've expected to use a crate name: ```compile_fail use ferris_wheel::BigO; -// error: failed to resolve: use of undeclared crate or module `ferris_wheel` +// error: failed to resolve: use of undeclared module or unlinked crate ``` Make sure the crate has been added as a dependency in `Cargo.toml`. diff --git a/compiler/rustc_error_codes/src/error_codes/E0647.md b/compiler/rustc_error_codes/src/error_codes/E0647.md index 59bb47ba62a..e2f14b81aa6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0647.md +++ b/compiler/rustc_error_codes/src/error_codes/E0647.md @@ -1,13 +1,3 @@ -The `start` function was defined with a where clause. - -Erroneous code example: +#### Note: this error code is no longer emitted by the compiler. -```compile_fail,E0647 -#![feature(start)] - -#[start] -fn start(_: isize, _: *const *const u8) -> isize where (): Copy { - //^ error: `#[start]` function is not allowed to have a where clause - 0 -} -``` +The `start` function was defined with a where clause. diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs index 29f3277d399..0a30bdb48a0 100644 --- a/compiler/rustc_error_codes/src/lib.rs +++ b/compiler/rustc_error_codes/src/lib.rs @@ -24,6 +24,10 @@ // // Both columns are necessary because it's not possible in Rust to create a new identifier such as // `E0123` from an integer literal such as `0123`, unfortunately. +// +// Do *not* remove entries from this list. Instead, just add a note th the corresponding markdown +// file saying that this error is not emitted by the compiler any more (see E0001.md for an +// example), and remove all code examples that do not build any more. #[macro_export] macro_rules! error_codes { ($macro:path) => ( diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 66b9adbead0..fbb6a1cc475 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -31,7 +31,7 @@ tracing = "0.1" # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] -version = "0.57.0" +version = "0.59.0" features = [ "Win32_Foundation", "Win32_Security", diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index f938352820d..991dfa1821a 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -3146,7 +3146,7 @@ impl FileWithAnnotatedLines { add_annotation_to_file(&mut output, Lrc::clone(&file), line, ann.as_line()); } let line_end = ann.line_end - 1; - let end_is_empty = file.get_line(line_end - 1).map_or(false, |s| !filter(&s)); + let end_is_empty = file.get_line(line_end - 1).is_some_and(|s| !filter(&s)); if middle < line_end && !end_is_empty { add_annotation_to_file(&mut output, Lrc::clone(&file), line_end, ann.as_line()); } diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 97df7f9265a..95c81fc5f44 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -21,7 +21,7 @@ use rustc_error_messages::FluentArgs; use rustc_lint_defs::Applicability; use rustc_span::Span; use rustc_span::hygiene::ExpnData; -use rustc_span::source_map::SourceMap; +use rustc_span::source_map::{FilePathMapping, SourceMap}; use serde::Serialize; use termcolor::{ColorSpec, WriteColor}; @@ -45,7 +45,7 @@ pub struct JsonEmitter { #[setters(skip)] dst: IntoDynSyncSend<Box<dyn Write + Send>>, #[setters(skip)] - sm: Lrc<SourceMap>, + sm: Option<Lrc<SourceMap>>, fluent_bundle: Option<Lrc<FluentBundle>>, #[setters(skip)] fallback_bundle: LazyFallbackBundle, @@ -65,7 +65,7 @@ pub struct JsonEmitter { impl JsonEmitter { pub fn new( dst: Box<dyn Write + Send>, - sm: Lrc<SourceMap>, + sm: Option<Lrc<SourceMap>>, fallback_bundle: LazyFallbackBundle, pretty: bool, json_rendered: HumanReadableErrorType, @@ -171,7 +171,7 @@ impl Emitter for JsonEmitter { } fn source_map(&self) -> Option<&SourceMap> { - Some(&self.sm) + self.sm.as_deref() } fn should_show_explain(&self) -> bool { @@ -371,7 +371,7 @@ impl Diagnostic { } HumanEmitter::new(dst, Lrc::clone(&je.fallback_bundle)) .short_message(short) - .sm(Some(Lrc::clone(&je.sm))) + .sm(je.sm.clone()) .fluent_bundle(je.fluent_bundle.clone()) .diagnostic_width(je.diagnostic_width) .macro_backtrace(je.macro_backtrace) @@ -458,22 +458,34 @@ impl DiagnosticSpan { mut backtrace: impl Iterator<Item = ExpnData>, je: &JsonEmitter, ) -> DiagnosticSpan { - let start = je.sm.lookup_char_pos(span.lo()); + let empty_source_map; + let sm = match &je.sm { + Some(s) => s, + None => { + span = rustc_span::DUMMY_SP; + empty_source_map = Arc::new(SourceMap::new(FilePathMapping::empty())); + empty_source_map + .new_source_file(std::path::PathBuf::from("empty.rs").into(), String::new()); + &empty_source_map + } + }; + let start = sm.lookup_char_pos(span.lo()); // If this goes from the start of a line to the end and the replacement // is an empty string, increase the length to include the newline so we don't // leave an empty line if start.col.0 == 0 - && suggestion.map_or(false, |(s, _)| s.is_empty()) - && let Ok(after) = je.sm.span_to_next_source(span) + && let Some((suggestion, _)) = suggestion + && suggestion.is_empty() + && let Ok(after) = sm.span_to_next_source(span) && after.starts_with('\n') { span = span.with_hi(span.hi() + rustc_span::BytePos(1)); } - let end = je.sm.lookup_char_pos(span.hi()); + let end = sm.lookup_char_pos(span.hi()); let backtrace_step = backtrace.next().map(|bt| { let call_site = Self::from_span_full(bt.call_site, false, None, None, backtrace, je); let def_site_span = Self::from_span_full( - je.sm.guess_head_span(bt.def_site), + sm.guess_head_span(bt.def_site), false, None, None, @@ -488,7 +500,7 @@ impl DiagnosticSpan { }); DiagnosticSpan { - file_name: je.sm.filename_for_diagnostics(&start.file.name).to_string(), + file_name: sm.filename_for_diagnostics(&start.file.name).to_string(), byte_start: start.file.original_relative_byte_pos(span.lo()).0, byte_end: start.file.original_relative_byte_pos(span.hi()).0, line_start: start.line, @@ -558,19 +570,20 @@ impl DiagnosticSpanLine { /// `span` within the line. fn from_span(span: Span, je: &JsonEmitter) -> Vec<DiagnosticSpanLine> { je.sm - .span_to_lines(span) - .map(|lines| { + .as_ref() + .and_then(|sm| { + let lines = sm.span_to_lines(span).ok()?; // We can't get any lines if the source is unavailable. if !should_show_source_code( &je.ignored_directories_in_source_blocks, - &je.sm, + &sm, &lines.file, ) { - return vec![]; + return None; } let sf = &*lines.file; - lines + let span_lines = lines .lines .iter() .map(|line| { @@ -581,8 +594,9 @@ impl DiagnosticSpanLine { line.end_col.0 + 1, ) }) - .collect() + .collect(); + Some(span_lines) }) - .unwrap_or_else(|_| vec![]) + .unwrap_or_default() } } diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs index 0de555b83d3..cebaf7c1cfe 100644 --- a/compiler/rustc_errors/src/json/tests.rs +++ b/compiler/rustc_errors/src/json/tests.rs @@ -47,7 +47,7 @@ fn test_positions(code: &str, span: (u32, u32), expected_output: SpanTestData) { let output = Arc::new(Mutex::new(Vec::new())); let je = JsonEmitter::new( Box::new(Shared { data: output.clone() }), - sm, + Some(sm), fallback_bundle, true, // pretty HumanReadableErrorType::Short, diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index cc5eb9c335e..549729548f5 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -35,6 +35,7 @@ use std::backtrace::{Backtrace, BacktraceStatus}; use std::borrow::Cow; use std::cell::Cell; use std::error::Report; +use std::ffi::OsStr; use std::hash::Hash; use std::io::Write; use std::num::NonZero; @@ -1717,7 +1718,7 @@ impl DiagCtxtInner { let bugs: Vec<_> = std::mem::take(&mut self.delayed_bugs).into_iter().map(|(b, _)| b).collect(); - let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(true, |x| &x != "0"); + let backtrace = std::env::var_os("RUST_BACKTRACE").as_deref() != Some(OsStr::new("0")); let decorate = backtrace || self.ice_file.is_none(); let mut out = self .ice_file diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 3e3f35332e0..83255b82017 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -391,7 +391,7 @@ impl<'a> StripUnconfigured<'a> { validate_attr::deny_builtin_meta_unsafety(&self.sess.psess, &meta_item); ( - parse_cfg(&meta_item, self.sess).map_or(true, |meta_item| { + parse_cfg(&meta_item, self.sess).is_none_or(|meta_item| { attr::cfg_matches(meta_item, &self.sess, self.lint_node_id, self.features) }), Some(meta_item), diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 9f48835e15d..e60a9e83184 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -159,7 +159,7 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match if self .best_failure .as_ref() - .map_or(true, |failure| failure.is_better_position(*approx_position)) + .is_none_or(|failure| failure.is_better_position(*approx_position)) { self.best_failure = Some(BestFailure { token: token.clone(), diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index ef209c2bce1..21688521ade 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -282,11 +282,13 @@ pub(super) fn transcribe<'a>( } MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => { marker.visit_span(&mut sp); + with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); let kind = token::NtIdent(*ident, *is_raw); TokenTree::token_alone(kind, sp) } MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => { marker.visit_span(&mut sp); + with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); let kind = token::NtLifetime(*ident, *is_raw); TokenTree::token_alone(kind, sp) } @@ -295,6 +297,8 @@ pub(super) fn transcribe<'a>( // `Delimiter::Invisible` to maintain parsing priorities. // `Interpolated` is currently used for such groups in rustc parser. marker.visit_span(&mut sp); + let use_span = nt.use_span(); + with_metavar_spans(|mspans| mspans.insert(use_span, sp)); TokenTree::token_alone(token::Interpolated(Lrc::clone(nt)), sp) } MatchedSeq(..) => { @@ -410,19 +414,15 @@ fn maybe_use_metavar_location( return orig_tt.clone(); } - let insert = |mspans: &mut FxHashMap<_, _>, s, ms| match mspans.try_insert(s, ms) { - Ok(_) => true, - Err(err) => *err.entry.get() == ms, // Tried to insert the same span, still success - }; marker.visit_span(&mut metavar_span); let no_collision = match orig_tt { TokenTree::Token(token, ..) => { - with_metavar_spans(|mspans| insert(mspans, token.span, metavar_span)) + with_metavar_spans(|mspans| mspans.insert(token.span, metavar_span)) } TokenTree::Delimited(dspan, ..) => with_metavar_spans(|mspans| { - insert(mspans, dspan.open, metavar_span) - && insert(mspans, dspan.close, metavar_span) - && insert(mspans, dspan.entire(), metavar_span) + mspans.insert(dspan.open, metavar_span) + && mspans.insert(dspan.close, metavar_span) + && mspans.insert(dspan.entire(), metavar_span) }), }; if no_collision || psess.source_map().is_imported(metavar_span) { @@ -434,14 +434,14 @@ fn maybe_use_metavar_location( match orig_tt { TokenTree::Token(Token { kind, span }, spacing) => { let span = metavar_span.with_ctxt(span.ctxt()); - with_metavar_spans(|mspans| insert(mspans, span, metavar_span)); + with_metavar_spans(|mspans| mspans.insert(span, metavar_span)); TokenTree::Token(Token { kind: kind.clone(), span }, *spacing) } TokenTree::Delimited(dspan, dspacing, delimiter, tts) => { let open = metavar_span.with_ctxt(dspan.open.ctxt()); let close = metavar_span.with_ctxt(dspan.close.ctxt()); with_metavar_spans(|mspans| { - insert(mspans, open, metavar_span) && insert(mspans, close, metavar_span) + mspans.insert(open, metavar_span) && mspans.insert(close, metavar_span) }); let dspan = DelimSpan::from_pair(open, close); TokenTree::Delimited(dspan, *dspacing, *delimiter, tts.clone()) diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 5510e7e09e5..17433eed9e7 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -408,11 +408,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), DuplicatesOk, EncodeCrossCrate::No, ), - // crate_id is deprecated - ungated!( - crate_id, CrateLevel, template!(NameValueStr: "ignored"), FutureWarnFollowing, - EncodeCrossCrate::No, - ), // ABI, linking, symbols, and FFI ungated!( @@ -448,8 +443,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - ungated!(start, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), - ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No), // Modules, prelude, and resolution: @@ -533,7 +526,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // RFC 2412 gated!( - optimize, Normal, template!(List: "size|speed"), ErrorPreceding, + optimize, Normal, template!(List: "none|size|speed"), ErrorPreceding, EncodeCrossCrate::No, optimize_attribute, experimental!(optimize) ), diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 9aa59375706..081638715df 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -163,7 +163,7 @@ declare_features! ( /// then removed. But there was no utility storing it separately, so now /// it's in this list. (removed, no_stack_check, "1.0.0", None, None), - /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible (object safe). + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible (object safe). /// Renamed to `dyn_compatible_for_dispatch`. (removed, object_safe_for_dispatch, "1.83.0", Some(43561), Some("renamed to `dyn_compatible_for_dispatch`")), @@ -220,8 +220,9 @@ declare_features! ( (removed, rustc_diagnostic_macros, "1.38.0", None, None), /// Allows identifying crates that contain sanitizer runtimes. (removed, sanitizer_runtime, "1.17.0", None, None), - (removed, simd, "1.0.0", Some(27731), - Some("removed in favor of `#[repr(simd)]`")), + (removed, simd, "1.0.0", Some(27731), Some("removed in favor of `#[repr(simd)]`")), + /// Allows using `#[start]` on a function indicating that it is the program entrypoint. + (removed, start, "1.0.0", Some(29633), Some("not portable enough and never RFC'd")), /// Allows `#[link(kind = "static-nobundle", ...)]`. (removed, static_nobundle, "1.16.0", Some(37403), Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#)), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 4ab0bc47305..1a216ebf117 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -272,7 +272,7 @@ declare_features! ( (unstable, doc_notable_trait, "1.52.0", Some(45040)), /// Allows using the `may_dangle` attribute (RFC 1327). (unstable, dropck_eyepatch, "1.10.0", Some(34761)), - /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn-compatible[^1]. + /// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible[^1]. /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden. /// @@ -300,8 +300,6 @@ declare_features! ( (internal, rustdoc_internals, "1.58.0", Some(90418)), /// Allows using the `rustdoc::missing_doc_code_examples` lint (unstable, rustdoc_missing_doc_code_examples, "1.31.0", Some(101730)), - /// Allows using `#[start]` on a function indicating that it is the program entrypoint. - (unstable, start, "1.0.0", Some(29633)), /// Allows using `#[structural_match]` which indicates that a type is structurally matchable. /// FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library /// feature with the same name exists. diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 705de389e07..7e3a8561da0 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -794,7 +794,7 @@ impl<Id> Res<Id> { /// Always returns `true` if `self` is `Res::Err` pub fn matches_ns(&self, ns: Namespace) -> bool { - self.ns().map_or(true, |actual_ns| actual_ns == ns) + self.ns().is_none_or(|actual_ns| actual_ns == ns) } /// Returns whether such a resolved path can occur in a tuple struct/variant pattern diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5339feb5d27..a396d705cbb 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -15,6 +15,7 @@ pub use rustc_ast::{ }; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; +use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_index::IndexVec; use rustc_macros::{Decodable, Encodable, HashStable_Generic}; use rustc_span::def_id::LocalDefId; @@ -30,7 +31,7 @@ use crate::LangItem; use crate::def::{CtorKind, DefKind, Res}; use crate::def_id::{DefId, LocalDefIdMap}; pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId}; -use crate::intravisit::FnKind; +use crate::intravisit::{FnKind, VisitorExt}; #[derive(Debug, Copy, Clone, HashStable_Generic)] pub struct Lifetime { @@ -263,14 +264,58 @@ impl<'hir> PathSegment<'hir> { /// So, `ConstArg` (specifically, [`ConstArgKind`]) distinguishes between const args /// that are [just paths](ConstArgKind::Path) (currently just bare const params) /// versus const args that are literals or have arbitrary computations (e.g., `{ 1 + 3 }`). +/// +/// The `Unambig` generic parameter represents whether the position this const is from is +/// unambiguously a const or ambiguous as to whether it is a type or a const. When in an +/// ambiguous context the parameter is instantiated with an uninhabited type making the +/// [`ConstArgKind::Infer`] variant unusable and [`GenericArg::Infer`] is used instead. #[derive(Clone, Copy, Debug, HashStable_Generic)] -pub struct ConstArg<'hir> { +#[repr(C)] +pub struct ConstArg<'hir, Unambig = ()> { #[stable_hasher(ignore)] pub hir_id: HirId, - pub kind: ConstArgKind<'hir>, + pub kind: ConstArgKind<'hir, Unambig>, +} + +impl<'hir> ConstArg<'hir, AmbigArg> { + /// Converts a `ConstArg` in an ambiguous position to one in an unambiguous position. + /// + /// Functions accepting an unambiguous consts may expect the [`ConstArgKind::Infer`] variant + /// to be used. Care should be taken to separately handle infer consts when calling this + /// function as it cannot be handled by downstream code making use of the returned const. + /// + /// In practice this may mean overriding the [`Visitor::visit_infer`][visit_infer] method on hir visitors, or + /// specifically matching on [`GenericArg::Infer`] when handling generic arguments. + /// + /// [visit_infer]: [rustc_hir::intravisit::Visitor::visit_infer] + pub fn as_unambig_ct(&self) -> &ConstArg<'hir> { + // SAFETY: `ConstArg` is `repr(C)` and `ConstArgKind` is marked `repr(u8)` so that the + // layout is the same across different ZST type arguments. + let ptr = self as *const ConstArg<'hir, AmbigArg> as *const ConstArg<'hir, ()>; + unsafe { &*ptr } + } } impl<'hir> ConstArg<'hir> { + /// Converts a `ConstArg` in an unambigous position to one in an ambiguous position. This is + /// fallible as the [`ConstArgKind::Infer`] variant is not present in ambiguous positions. + /// + /// Functions accepting ambiguous consts will not handle the [`ConstArgKind::Infer`] variant, if + /// infer consts are relevant to you then care should be taken to handle them separately. + pub fn try_as_ambig_ct(&self) -> Option<&ConstArg<'hir, AmbigArg>> { + if let ConstArgKind::Infer(_, ()) = self.kind { + return None; + } + + // SAFETY: `ConstArg` is `repr(C)` and `ConstArgKind` is marked `repr(u8)` so that the layout is + // the same across different ZST type arguments. We also asserted that the `self` is + // not a `ConstArgKind::Infer` so there is no risk of transmuting a `()` to `AmbigArg`. + let ptr = self as *const ConstArg<'hir> as *const ConstArg<'hir, AmbigArg>; + Some(unsafe { &*ptr }) + } +} + +impl<'hir, Unambig> ConstArg<'hir, Unambig> { pub fn anon_const_hir_id(&self) -> Option<HirId> { match self.kind { ConstArgKind::Anon(ac) => Some(ac.hir_id), @@ -282,14 +327,15 @@ impl<'hir> ConstArg<'hir> { match self.kind { ConstArgKind::Path(path) => path.span(), ConstArgKind::Anon(anon) => anon.span, - ConstArgKind::Infer(span) => span, + ConstArgKind::Infer(span, _) => span, } } } /// See [`ConstArg`]. #[derive(Clone, Copy, Debug, HashStable_Generic)] -pub enum ConstArgKind<'hir> { +#[repr(u8, C)] +pub enum ConstArgKind<'hir, Unambig = ()> { /// **Note:** Currently this is only used for bare const params /// (`N` where `fn foo<const N: usize>(...)`), /// not paths to any const (`N` where `const N: usize = ...`). @@ -297,11 +343,9 @@ pub enum ConstArgKind<'hir> { /// However, in the future, we'll be using it for all of those. Path(QPath<'hir>), Anon(&'hir AnonConst), - /// **Note:** Not all inferred consts are represented as - /// `ConstArgKind::Infer`. In cases where it is ambiguous whether - /// a generic arg is a type or a const, inference variables are - /// represented as `GenericArg::Infer` instead. - Infer(Span), + /// This variant is not always used to represent inference consts, sometimes + /// [`GenericArg::Infer`] is used instead. + Infer(Span, Unambig), } #[derive(Clone, Copy, Debug, HashStable_Generic)] @@ -313,19 +357,24 @@ pub struct InferArg { impl InferArg { pub fn to_ty(&self) -> Ty<'static> { - Ty { kind: TyKind::Infer, span: self.span, hir_id: self.hir_id } + Ty { kind: TyKind::Infer(()), span: self.span, hir_id: self.hir_id } } } #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum GenericArg<'hir> { Lifetime(&'hir Lifetime), - Type(&'hir Ty<'hir>), - Const(&'hir ConstArg<'hir>), - /// **Note:** Inference variables are only represented as - /// `GenericArg::Infer` in cases where it is ambiguous whether - /// a generic arg is a type or a const. Otherwise, inference variables - /// are represented as `TyKind::Infer` or `ConstArgKind::Infer`. + Type(&'hir Ty<'hir, AmbigArg>), + Const(&'hir ConstArg<'hir, AmbigArg>), + /// Inference variables in [`GenericArg`] are always represnted by + /// `GenericArg::Infer` instead of the `Infer` variants on [`TyKind`] and + /// [`ConstArgKind`] as it is not clear until hir ty lowering whether a + /// `_` argument is a type or const argument. + /// + /// However, some builtin types' generic arguments are represented by [`TyKind`] + /// without a [`GenericArg`], instead directly storing a [`Ty`] or [`ConstArg`]. In + /// such cases they *are* represented by the `Infer` variants on [`TyKind`] and + /// [`ConstArgKind`] as it is not ambiguous whether the argument is a type or const. Infer(InferArg), } @@ -353,7 +402,7 @@ impl GenericArg<'_> { GenericArg::Lifetime(_) => "lifetime", GenericArg::Type(_) => "type", GenericArg::Const(_) => "constant", - GenericArg::Infer(_) => "inferred", + GenericArg::Infer(_) => "placeholder", } } @@ -764,11 +813,8 @@ impl<'hir> Generics<'hir> { && let [.., segment] = trait_ref.path.segments && let Some(ret_ty) = segment.args().paren_sugar_output() && let ret_ty = ret_ty.peel_refs() - && let TyKind::TraitObject( - _, - _, - TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar, - ) = ret_ty.kind + && let TyKind::TraitObject(_, tagged_ptr) = ret_ty.kind + && let TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar = tagged_ptr.tag() && ret_ty.span.can_be_used_for_suggestions() { Some(ret_ty.span) @@ -1239,13 +1285,13 @@ impl fmt::Debug for OwnerNodes<'_> { .field("node", &self.nodes[ItemLocalId::ZERO]) .field( "parents", - &self - .nodes - .iter_enumerated() - .map(|(id, parented_node)| { - debug_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent)) - }) - .collect::<Vec<_>>(), + &fmt::from_fn(|f| { + f.debug_list() + .entries(self.nodes.iter_enumerated().map(|(id, parented_node)| { + fmt::from_fn(move |f| write!(f, "({id:?}, {:?})", parented_node.parent)) + })) + .finish() + }), ) .field("bodies", &self.bodies) .field("opt_hash_including_bodies", &self.opt_hash_including_bodies) @@ -2917,15 +2963,84 @@ impl<'hir> AssocItemConstraintKind<'hir> { } } +/// An uninhabited enum used to make `Infer` variants on [`Ty`] and [`ConstArg`] be +/// unreachable. Zero-Variant enums are guaranteed to have the same layout as the never +/// type. #[derive(Debug, Clone, Copy, HashStable_Generic)] -pub struct Ty<'hir> { +pub enum AmbigArg {} + +#[derive(Debug, Clone, Copy, HashStable_Generic)] +#[repr(C)] +/// Represents a type in the `HIR`. +/// +/// The `Unambig` generic parameter represents whether the position this type is from is +/// unambiguously a type or ambiguous as to whether it is a type or a const. When in an +/// ambiguous context the parameter is instantiated with an uninhabited type making the +/// [`TyKind::Infer`] variant unusable and [`GenericArg::Infer`] is used instead. +pub struct Ty<'hir, Unambig = ()> { #[stable_hasher(ignore)] pub hir_id: HirId, - pub kind: TyKind<'hir>, pub span: Span, + pub kind: TyKind<'hir, Unambig>, +} + +impl<'hir> Ty<'hir, AmbigArg> { + /// Converts a `Ty` in an ambiguous position to one in an unambiguous position. + /// + /// Functions accepting an unambiguous types may expect the [`TyKind::Infer`] variant + /// to be used. Care should be taken to separately handle infer types when calling this + /// function as it cannot be handled by downstream code making use of the returned ty. + /// + /// In practice this may mean overriding the [`Visitor::visit_infer`][visit_infer] method on hir visitors, or + /// specifically matching on [`GenericArg::Infer`] when handling generic arguments. + /// + /// [visit_infer]: [rustc_hir::intravisit::Visitor::visit_infer] + pub fn as_unambig_ty(&self) -> &Ty<'hir> { + // SAFETY: `Ty` is `repr(C)` and `TyKind` is marked `repr(u8)` so that the layout is + // the same across different ZST type arguments. + let ptr = self as *const Ty<'hir, AmbigArg> as *const Ty<'hir, ()>; + unsafe { &*ptr } + } +} + +impl<'hir> Ty<'hir> { + /// Converts a `Ty` in an unambigous position to one in an ambiguous position. This is + /// fallible as the [`TyKind::Infer`] variant is not present in ambiguous positions. + /// + /// Functions accepting ambiguous types will not handle the [`TyKind::Infer`] variant, if + /// infer types are relevant to you then care should be taken to handle them separately. + pub fn try_as_ambig_ty(&self) -> Option<&Ty<'hir, AmbigArg>> { + if let TyKind::Infer(()) = self.kind { + return None; + } + + // SAFETY: `Ty` is `repr(C)` and `TyKind` is marked `repr(u8)` so that the layout is + // the same across different ZST type arguments. We also asserted that the `self` is + // not a `TyKind::Infer` so there is no risk of transmuting a `()` to `AmbigArg`. + let ptr = self as *const Ty<'hir> as *const Ty<'hir, AmbigArg>; + Some(unsafe { &*ptr }) + } +} + +impl<'hir> Ty<'hir, AmbigArg> { + pub fn peel_refs(&self) -> &Ty<'hir> { + let mut final_ty = self.as_unambig_ty(); + while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { + final_ty = ty; + } + final_ty + } } impl<'hir> Ty<'hir> { + pub fn peel_refs(&self) -> &Self { + let mut final_ty = self; + while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { + final_ty = ty; + } + final_ty + } + /// Returns `true` if `param_def_id` matches the `bounded_ty` of this predicate. pub fn as_generic_param(&self) -> Option<(DefId, Ident)> { let TyKind::Path(QPath::Resolved(None, path)) = self.kind else { @@ -2942,19 +3057,11 @@ impl<'hir> Ty<'hir> { } } - pub fn peel_refs(&self) -> &Self { - let mut final_ty = self; - while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { - final_ty = ty; - } - final_ty - } - pub fn find_self_aliases(&self) -> Vec<Span> { use crate::intravisit::Visitor; struct MyVisitor(Vec<Span>); impl<'v> Visitor<'v> for MyVisitor { - fn visit_ty(&mut self, t: &'v Ty<'v>) { + fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) { if matches!( &t.kind, TyKind::Path(QPath::Resolved(_, Path { @@ -2970,7 +3077,7 @@ impl<'hir> Ty<'hir> { } let mut my_visitor = MyVisitor(vec![]); - my_visitor.visit_ty(self); + my_visitor.visit_ty_unambig(self); my_visitor.0 } @@ -2979,14 +3086,14 @@ impl<'hir> Ty<'hir> { pub fn is_suggestable_infer_ty(&self) -> bool { fn are_suggestable_generic_args(generic_args: &[GenericArg<'_>]) -> bool { generic_args.iter().any(|arg| match arg { - GenericArg::Type(ty) => ty.is_suggestable_infer_ty(), + GenericArg::Type(ty) => ty.as_unambig_ty().is_suggestable_infer_ty(), GenericArg::Infer(_) => true, _ => false, }) } debug!(?self); match &self.kind { - TyKind::Infer => true, + TyKind::Infer(()) => true, TyKind::Slice(ty) => ty.is_suggestable_infer_ty(), TyKind::Array(ty, length) => { ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..)) @@ -3200,7 +3307,9 @@ pub enum InferDelegationKind { /// The various kinds of types recognized by the compiler. #[derive(Debug, Clone, Copy, HashStable_Generic)] -pub enum TyKind<'hir> { +// SAFETY: `repr(u8)` is required so that `TyKind<()>` and `TyKind<!>` are layout compatible +#[repr(u8, C)] +pub enum TyKind<'hir, Unambig = ()> { /// Actual type should be inherited from `DefId` signature InferDelegation(DefId, InferDelegationKind), /// A variable length slice (i.e., `[T]`). @@ -3230,21 +3339,22 @@ pub enum TyKind<'hir> { TraitAscription(GenericBounds<'hir>), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. - TraitObject(&'hir [PolyTraitRef<'hir>], &'hir Lifetime, TraitObjectSyntax), + /// + /// We use pointer tagging to represent a `&'hir Lifetime` and `TraitObjectSyntax` pair + /// as otherwise this type being `repr(C)` would result in `TyKind` increasing in size. + TraitObject(&'hir [PolyTraitRef<'hir>], TaggedRef<'hir, Lifetime, TraitObjectSyntax>), /// Unused for now. Typeof(&'hir AnonConst), - /// `TyKind::Infer` means the type should be inferred instead of it having been - /// specified. This can appear anywhere in a type. - /// - /// **Note:** Not all inferred types are represented as - /// `TyKind::Infer`. In cases where it is ambiguous whether - /// a generic arg is a type or a const, inference variables are - /// represented as `GenericArg::Infer` instead. - Infer, /// Placeholder for a type that has failed to be defined. Err(rustc_span::ErrorGuaranteed), /// Pattern types (`pattern_type!(u32 is 1..)`) Pat(&'hir Ty<'hir>, &'hir Pat<'hir>), + /// `TyKind::Infer` means the type should be inferred instead of it having been + /// specified. This can appear anywhere in a type. + /// + /// This variant is not always used to represent inference types, sometimes + /// [`GenericArg::Infer`] is used instead. + Infer(Unambig), } #[derive(Debug, Clone, Copy, HashStable_Generic)] @@ -4528,12 +4638,5 @@ mod size_asserts { // tidy-alphabetical-end } -fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug { - struct DebugFn<F>(F); - impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - (self.0)(fmt) - } - } - DebugFn(f) -} +#[cfg(test)] +mod tests; diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs new file mode 100644 index 00000000000..300d4435530 --- /dev/null +++ b/compiler/rustc_hir/src/hir/tests.rs @@ -0,0 +1,83 @@ +use rustc_span::def_id::DefIndex; + +use super::*; + +macro_rules! define_tests { + ($($name:ident $kind:ident $variant:ident {$($init:tt)*})*) => {$( + #[test] + fn $name() { + let unambig = $kind::$variant::<'_, ()> { $($init)* }; + let unambig_to_ambig = unsafe { std::mem::transmute::<_, $kind<'_, AmbigArg>>(unambig) }; + + assert!(matches!(&unambig_to_ambig, $kind::$variant { $($init)* })); + + let ambig_to_unambig = unsafe { std::mem::transmute::<_, $kind<'_, ()>>(unambig_to_ambig) }; + + assert!(matches!(&ambig_to_unambig, $kind::$variant { $($init)* })); + } + )*}; +} + +define_tests! { + cast_never TyKind Never {} + cast_tup TyKind Tup { 0: &[Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }] } + cast_ptr TyKind Ptr { 0: MutTy { ty: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, mutbl: Mutability::Not }} + cast_array TyKind Array { + 0: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, + 1: &ConstArg { hir_id: HirId::INVALID, kind: ConstArgKind::Anon(&AnonConst { + hir_id: HirId::INVALID, + def_id: LocalDefId { local_def_index: DefIndex::ZERO }, + body: BodyId { hir_id: HirId::INVALID }, + span: DUMMY_SP, + })} + } + + cast_anon ConstArgKind Anon { + 0: &AnonConst { + hir_id: HirId::INVALID, + def_id: LocalDefId { local_def_index: DefIndex::ZERO }, + body: BodyId { hir_id: HirId::INVALID }, + span: DUMMY_SP, + } + } +} + +#[test] +fn trait_object_roundtrips() { + trait_object_roundtrips_impl(TraitObjectSyntax::Dyn); + trait_object_roundtrips_impl(TraitObjectSyntax::DynStar); + trait_object_roundtrips_impl(TraitObjectSyntax::None); +} + +fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) { + let unambig = TyKind::TraitObject::<'_, ()>( + &[], + TaggedRef::new( + &const { + Lifetime { + hir_id: HirId::INVALID, + ident: Ident::new(sym::name, DUMMY_SP), + res: LifetimeName::Static, + } + }, + syntax, + ), + ); + let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) }; + + match unambig_to_ambig { + TyKind::TraitObject(_, tagged_ref) => { + assert!(tagged_ref.tag() == syntax) + } + _ => panic!("`TyKind::TraitObject` did not roundtrip"), + }; + + let ambig_to_unambig = unsafe { std::mem::transmute::<_, TyKind<'_, ()>>(unambig_to_ambig) }; + + match ambig_to_unambig { + TyKind::TraitObject(_, tagged_ref) => { + assert!(tagged_ref.tag() == syntax) + } + _ => panic!("`TyKind::TraitObject` did not roundtrip"), + }; +} diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index ef863aca090..b0d80d0f809 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -351,18 +351,48 @@ pub trait Visitor<'v>: Sized { fn visit_inline_const(&mut self, c: &'v ConstBlock) -> Self::Result { walk_inline_const(self, c) } - fn visit_const_arg(&mut self, c: &'v ConstArg<'v>) -> Self::Result { - walk_const_arg(self, c) + + fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) -> Self::Result { + walk_generic_arg(self, generic_arg) + } + + /// All types are treated as ambiguous types for the purposes of hir visiting in + /// order to ensure that visitors can handle infer vars without it being too error-prone. + /// + /// See the doc comments on [`Ty`] for an explanation of what it means for a type to be + /// ambiguous. + /// + /// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars. + fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) -> Self::Result { + walk_ty(self, t) } + + /// All consts are treated as ambiguous consts for the purposes of hir visiting in + /// order to ensure that visitors can handle infer vars without it being too error-prone. + /// + /// See the doc comments on [`ConstArg`] for an explanation of what it means for a const to be + /// ambiguous. + /// + /// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars. + fn visit_const_arg(&mut self, c: &'v ConstArg<'v, AmbigArg>) -> Self::Result { + walk_ambig_const_arg(self, c) + } + + #[allow(unused_variables)] + fn visit_infer(&mut self, inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result { + self.visit_id(inf_id) + } + + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result { + walk_lifetime(self, lifetime) + } + fn visit_expr(&mut self, ex: &'v Expr<'v>) -> Self::Result { walk_expr(self, ex) } fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result { walk_expr_field(self, field) } - fn visit_ty(&mut self, t: &'v Ty<'v>) -> Self::Result { - walk_ty(self, t) - } fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) { // Do nothing. Only a few visitors need to know the details of the pattern type, // and they opt into it. All other visitors will just choke on our fake patterns @@ -444,15 +474,6 @@ pub trait Visitor<'v>: Sized { fn visit_label(&mut self, label: &'v Label) -> Self::Result { walk_label(self, label) } - fn visit_infer(&mut self, inf: &'v InferArg) -> Self::Result { - walk_inf(self, inf) - } - fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg<'v>) -> Self::Result { - walk_generic_arg(self, generic_arg) - } - fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result { - walk_lifetime(self, lifetime) - } // The span is that of the surrounding type/pattern/expr/whatever. fn visit_qpath(&mut self, qpath: &'v QPath<'v>, id: HirId, _span: Span) -> Self::Result { walk_qpath(self, qpath, id) @@ -486,6 +507,26 @@ pub trait Visitor<'v>: Sized { } } +pub trait VisitorExt<'v>: Visitor<'v> { + /// Extension trait method to visit types in unambiguous positions, this is not + /// directly on the [`Visitor`] trait as this method should never be overridden. + /// + /// Named `visit_ty_unambig` instead of `visit_unambig_ty` to aid in discovery + /// by IDes when `v.visit_ty` is written. + fn visit_ty_unambig(&mut self, t: &'v Ty<'v>) -> Self::Result { + walk_unambig_ty(self, t) + } + /// Extension trait method to visit consts in unambiguous positions, this is not + /// directly on the [`Visitor`] trait as this method should never be overridden. + /// + /// Named `visit_const_arg_unambig` instead of `visit_unambig_const_arg` to aid in + /// discovery by IDes when `v.visit_const_arg` is written. + fn visit_const_arg_unambig(&mut self, c: &'v ConstArg<'v>) -> Self::Result { + walk_const_arg(self, c) + } +} +impl<'v, V: Visitor<'v>> VisitorExt<'v> for V {} + pub fn walk_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Param<'v>) -> V::Result { try_visit!(visitor.visit_id(param.hir_id)); visitor.visit_pat(param.pat) @@ -503,12 +544,12 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: } ItemKind::Static(ref typ, _, body) => { try_visit!(visitor.visit_id(item.hir_id())); - try_visit!(visitor.visit_ty(typ)); + try_visit!(visitor.visit_ty_unambig(typ)); try_visit!(visitor.visit_nested_body(body)); } ItemKind::Const(ref typ, ref generics, body) => { try_visit!(visitor.visit_id(item.hir_id())); - try_visit!(visitor.visit_ty(typ)); + try_visit!(visitor.visit_ty_unambig(typ)); try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_nested_body(body)); } @@ -539,7 +580,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: } ItemKind::TyAlias(ref ty, ref generics) => { try_visit!(visitor.visit_id(item.hir_id())); - try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_ty_unambig(ty)); try_visit!(visitor.visit_generics(generics)); } ItemKind::Enum(ref enum_definition, ref generics) => { @@ -561,7 +602,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_id(item.hir_id())); try_visit!(visitor.visit_generics(generics)); visit_opt!(visitor, visit_trait_ref, of_trait); - try_visit!(visitor.visit_ty(self_ty)); + try_visit!(visitor.visit_ty_unambig(self_ty)); walk_list!(visitor, visit_impl_item_ref, *items); } ItemKind::Struct(ref struct_definition, ref generics) @@ -618,7 +659,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( walk_list!(visitor, visit_ident, param_names.iter().copied()); } ForeignItemKind::Static(ref typ, _, _) => { - try_visit!(visitor.visit_ty(typ)); + try_visit!(visitor.visit_ty_unambig(typ)); } ForeignItemKind::Type => (), } @@ -632,7 +673,7 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v LetStmt<'v>) - try_visit!(visitor.visit_id(local.hir_id)); try_visit!(visitor.visit_pat(local.pat)); visit_opt!(visitor, visit_block, local.els); - visit_opt!(visitor, visit_ty, local.ty); + visit_opt!(visitor, visit_ty_unambig, local.ty); V::Result::output() } @@ -735,18 +776,6 @@ pub fn walk_inline_const<'v, V: Visitor<'v>>( visitor.visit_nested_body(constant.body) } -pub fn walk_const_arg<'v, V: Visitor<'v>>( - visitor: &mut V, - const_arg: &'v ConstArg<'v>, -) -> V::Result { - try_visit!(visitor.visit_id(const_arg.hir_id)); - match &const_arg.kind { - ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()), - ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), - ConstArgKind::Infer(..) => V::Result::output(), - } -} - pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) -> V::Result { try_visit!(visitor.visit_id(expression.hir_id)); match expression.kind { @@ -758,7 +787,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) } ExprKind::Repeat(ref element, ref count) => { try_visit!(visitor.visit_expr(element)); - try_visit!(visitor.visit_const_arg(count)); + try_visit!(visitor.visit_const_arg_unambig(count)); } ExprKind::Struct(ref qpath, fields, ref optional_base) => { try_visit!(visitor.visit_qpath(qpath, expression.hir_id, expression.span)); @@ -789,7 +818,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) } ExprKind::Cast(ref subexpression, ref typ) | ExprKind::Type(ref subexpression, ref typ) => { try_visit!(visitor.visit_expr(subexpression)); - try_visit!(visitor.visit_ty(typ)); + try_visit!(visitor.visit_ty_unambig(typ)); } ExprKind::DropTemps(ref subexpression) => { try_visit!(visitor.visit_expr(subexpression)); @@ -798,7 +827,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) // match the visit order in walk_local try_visit!(visitor.visit_expr(init)); try_visit!(visitor.visit_pat(pat)); - visit_opt!(visitor, visit_ty, ty); + visit_opt!(visitor, visit_ty_unambig, ty); } ExprKind::If(ref cond, ref then, ref else_opt) => { try_visit!(visitor.visit_expr(cond)); @@ -866,7 +895,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) try_visit!(visitor.visit_inline_asm(asm, expression.hir_id)); } ExprKind::OffsetOf(ref container, ref fields) => { - try_visit!(visitor.visit_ty(container)); + try_visit!(visitor.visit_ty_unambig(container)); walk_list!(visitor, visit_ident, fields.iter().copied()); } ExprKind::Yield(ref subexpression, _) => { @@ -874,7 +903,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) } ExprKind::UnsafeBinderCast(_kind, expr, ty) => { try_visit!(visitor.visit_expr(expr)); - visit_opt!(visitor, visit_ty, ty); + visit_opt!(visitor, visit_ty_unambig, ty); } ExprKind::Lit(_) | ExprKind::Err(_) => {} } @@ -886,20 +915,49 @@ pub fn walk_expr_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v ExprField try_visit!(visitor.visit_ident(field.ident)); visitor.visit_expr(field.expr) } +/// We track whether an infer var is from a [`Ty`], [`ConstArg`], or [`GenericArg`] so that +/// HIR visitors overriding [`Visitor::visit_infer`] can determine what kind of infer is being visited +pub enum InferKind<'hir> { + Ty(&'hir Ty<'hir>), + Const(&'hir ConstArg<'hir>), + Ambig(&'hir InferArg), +} -pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Result { +pub fn walk_generic_arg<'v, V: Visitor<'v>>( + visitor: &mut V, + generic_arg: &'v GenericArg<'v>, +) -> V::Result { + match generic_arg { + GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt), + GenericArg::Type(ty) => visitor.visit_ty(ty), + GenericArg::Const(ct) => visitor.visit_const_arg(ct), + GenericArg::Infer(inf) => visitor.visit_infer(inf.hir_id, inf.span, InferKind::Ambig(inf)), + } +} + +pub fn walk_unambig_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Result { + match typ.try_as_ambig_ty() { + Some(ambig_ty) => visitor.visit_ty(ambig_ty), + None => { + try_visit!(visitor.visit_id(typ.hir_id)); + visitor.visit_infer(typ.hir_id, typ.span, InferKind::Ty(typ)) + } + } +} + +pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) -> V::Result { try_visit!(visitor.visit_id(typ.hir_id)); match typ.kind { - TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty(ty)), - TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty(mutable_type.ty)), + TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)), + TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty_unambig(mutable_type.ty)), TyKind::Ref(ref lifetime, ref mutable_type) => { try_visit!(visitor.visit_lifetime(lifetime)); - try_visit!(visitor.visit_ty(mutable_type.ty)); + try_visit!(visitor.visit_ty_unambig(mutable_type.ty)); } TyKind::Never => {} TyKind::Tup(tuple_element_types) => { - walk_list!(visitor, visit_ty, tuple_element_types); + walk_list!(visitor, visit_ty_unambig, tuple_element_types); } TyKind::BareFn(ref function_declaration) => { walk_list!(visitor, visit_generic_param, function_declaration.generic_params); @@ -907,7 +965,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul } TyKind::UnsafeBinder(ref unsafe_binder) => { walk_list!(visitor, visit_generic_param, unsafe_binder.generic_params); - try_visit!(visitor.visit_ty(unsafe_binder.inner_ty)); + try_visit!(visitor.visit_ty_unambig(unsafe_binder.inner_ty)); } TyKind::Path(ref qpath) => { try_visit!(visitor.visit_qpath(qpath, typ.hir_id, typ.span)); @@ -919,25 +977,49 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul walk_list!(visitor, visit_param_bound, bounds); } TyKind::Array(ref ty, ref length) => { - try_visit!(visitor.visit_ty(ty)); - try_visit!(visitor.visit_const_arg(length)); + try_visit!(visitor.visit_ty_unambig(ty)); + try_visit!(visitor.visit_const_arg_unambig(length)); } - TyKind::TraitObject(bounds, ref lifetime, _syntax) => { + TyKind::TraitObject(bounds, ref lifetime) => { for bound in bounds { try_visit!(visitor.visit_poly_trait_ref(bound)); } try_visit!(visitor.visit_lifetime(lifetime)); } TyKind::Typeof(ref expression) => try_visit!(visitor.visit_anon_const(expression)), - TyKind::Infer | TyKind::InferDelegation(..) | TyKind::Err(_) => {} + TyKind::InferDelegation(..) | TyKind::Err(_) => {} TyKind::Pat(ty, pat) => { - try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_ty_unambig(ty)); try_visit!(visitor.visit_pattern_type_pattern(pat)); } } V::Result::output() } +pub fn walk_const_arg<'v, V: Visitor<'v>>( + visitor: &mut V, + const_arg: &'v ConstArg<'v>, +) -> V::Result { + match const_arg.try_as_ambig_ct() { + Some(ambig_ct) => visitor.visit_const_arg(ambig_ct), + None => { + try_visit!(visitor.visit_id(const_arg.hir_id)); + visitor.visit_infer(const_arg.hir_id, const_arg.span(), InferKind::Const(const_arg)) + } + } +} + +pub fn walk_ambig_const_arg<'v, V: Visitor<'v>>( + visitor: &mut V, + const_arg: &'v ConstArg<'v, AmbigArg>, +) -> V::Result { + try_visit!(visitor.visit_id(const_arg.hir_id)); + match &const_arg.kind { + ConstArgKind::Path(qpath) => visitor.visit_qpath(qpath, const_arg.hir_id, qpath.span()), + ConstArgKind::Anon(anon) => visitor.visit_anon_const(*anon), + } +} + pub fn walk_generic_param<'v, V: Visitor<'v>>( visitor: &mut V, param: &'v GenericParam<'v>, @@ -949,9 +1031,11 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>( } match param.kind { GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { ref default, .. } => visit_opt!(visitor, visit_ty, default), + GenericParamKind::Type { ref default, .. } => { + visit_opt!(visitor, visit_ty_unambig, default) + } GenericParamKind::Const { ref ty, ref default, synthetic: _ } => { - try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_ty_unambig(ty)); if let Some(ref default) = default { try_visit!(visitor.visit_const_param_default(param.hir_id, default)); } @@ -964,7 +1048,7 @@ pub fn walk_const_param_default<'v, V: Visitor<'v>>( visitor: &mut V, ct: &'v ConstArg<'v>, ) -> V::Result { - visitor.visit_const_arg(ct) + visitor.visit_const_arg_unambig(ct) } pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) -> V::Result { @@ -986,7 +1070,7 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( bound_generic_params, origin: _, }) => { - try_visit!(visitor.visit_ty(bounded_ty)); + try_visit!(visitor.visit_ty_unambig(bounded_ty)); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); } @@ -999,8 +1083,8 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( walk_list!(visitor, visit_param_bound, bounds); } WherePredicateKind::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty }) => { - try_visit!(visitor.visit_ty(lhs_ty)); - try_visit!(visitor.visit_ty(rhs_ty)); + try_visit!(visitor.visit_ty_unambig(lhs_ty)); + try_visit!(visitor.visit_ty_unambig(rhs_ty)); } } V::Result::output() @@ -1010,13 +1094,13 @@ pub fn walk_fn_decl<'v, V: Visitor<'v>>( visitor: &mut V, function_declaration: &'v FnDecl<'v>, ) -> V::Result { - walk_list!(visitor, visit_ty, function_declaration.inputs); + walk_list!(visitor, visit_ty_unambig, function_declaration.inputs); visitor.visit_fn_ret_ty(&function_declaration.output) } pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) -> V::Result { if let FnRetTy::Return(output_ty) = *ret_ty { - try_visit!(visitor.visit_ty(output_ty)); + try_visit!(visitor.visit_ty_unambig(output_ty)); } V::Result::output() } @@ -1069,7 +1153,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_id(hir_id)); match *kind { TraitItemKind::Const(ref ty, default) => { - try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_ty_unambig(ty)); visit_opt!(visitor, visit_nested_body, default); } TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { @@ -1087,7 +1171,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>( } TraitItemKind::Type(bounds, ref default) => { walk_list!(visitor, visit_param_bound, bounds); - visit_opt!(visitor, visit_ty, default); + visit_opt!(visitor, visit_ty_unambig, default); } } V::Result::output() @@ -1125,7 +1209,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_id(impl_item.hir_id())); match *kind { ImplItemKind::Const(ref ty, body) => { - try_visit!(visitor.visit_ty(ty)); + try_visit!(visitor.visit_ty_unambig(ty)); visitor.visit_nested_body(body) } ImplItemKind::Fn(ref sig, body_id) => visitor.visit_fn( @@ -1135,7 +1219,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>( impl_item.span, impl_item.owner_id.def_id, ), - ImplItemKind::Type(ref ty) => visitor.visit_ty(ty), + ImplItemKind::Type(ref ty) => visitor.visit_ty_unambig(ty), } } @@ -1223,7 +1307,7 @@ pub fn walk_field_def<'v, V: Visitor<'v>>( try_visit!(visitor.visit_id(*hir_id)); try_visit!(visitor.visit_ident(*ident)); visit_opt!(visitor, visit_anon_const, default); - visitor.visit_ty(*ty) + visitor.visit_ty_unambig(*ty) } pub fn walk_enum_def<'v, V: Visitor<'v>>( @@ -1252,18 +1336,6 @@ pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) -> V::Re visitor.visit_id(inf.hir_id) } -pub fn walk_generic_arg<'v, V: Visitor<'v>>( - visitor: &mut V, - generic_arg: &'v GenericArg<'v>, -) -> V::Result { - match generic_arg { - GenericArg::Lifetime(lt) => visitor.visit_lifetime(lt), - GenericArg::Type(ty) => visitor.visit_ty(ty), - GenericArg::Const(ct) => visitor.visit_const_arg(ct), - GenericArg::Infer(inf) => visitor.visit_infer(inf), - } -} - pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) -> V::Result { try_visit!(visitor.visit_id(lifetime.hir_id)); visitor.visit_ident(lifetime.ident) @@ -1276,11 +1348,11 @@ pub fn walk_qpath<'v, V: Visitor<'v>>( ) -> V::Result { match *qpath { QPath::Resolved(ref maybe_qself, ref path) => { - visit_opt!(visitor, visit_ty, maybe_qself); + visit_opt!(visitor, visit_ty_unambig, maybe_qself); visitor.visit_path(path, id) } QPath::TypeRelative(ref qself, ref segment) => { - try_visit!(visitor.visit_ty(qself)); + try_visit!(visitor.visit_ty_unambig(qself)); visitor.visit_path_segment(segment) } QPath::LangItem(..) => V::Result::output(), @@ -1320,8 +1392,8 @@ pub fn walk_assoc_item_constraint<'v, V: Visitor<'v>>( try_visit!(visitor.visit_generic_args(constraint.gen_args)); match constraint.kind { AssocItemConstraintKind::Equality { ref term } => match term { - Term::Ty(ref ty) => try_visit!(visitor.visit_ty(ty)), - Term::Const(ref c) => try_visit!(visitor.visit_const_arg(c)), + Term::Ty(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)), + Term::Const(ref c) => try_visit!(visitor.visit_const_arg_unambig(c)), }, AssocItemConstraintKind::Bound { bounds } => { walk_list!(visitor, visit_param_bound, bounds) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index fae3b778d7b..02bc069fc5f 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -332,6 +332,10 @@ language_item_table! { FallbackSurfaceDrop, sym::fallback_surface_drop, fallback_surface_drop_fn, Target::Fn, GenericRequirement::None; AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None; + /// For all binary crates without `#![no_main]`, Rust will generate a "main" function. + /// The exact name and signature are target-dependent. The "main" function will invoke + /// this lang item, passing it the `argc` and `argv` (or null, if those don't exist + /// on the current target) as well as the user-defined `fn main` from the binary crate. Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1); EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 381062b1429..705c167e258 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -6,6 +6,8 @@ #![allow(internal_features)] #![feature(associated_type_defaults)] #![feature(closure_track_caller)] +#![feature(debug_closure_helpers)] +#![feature(exhaustive_patterns)] #![feature(let_chains)] #![feature(never_type)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index d7ab6eca84b..be4004f5904 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -353,7 +353,13 @@ hir_analysis_missing_type_params = [one] reference *[other] references } to {$parameters} - .note = because of the default `Self` reference, type parameters must be specified on object types + .note = because the parameter {$parameterCount -> + [one] default references + *[other] defaults reference + } `Self`, the {$parameterCount -> + [one] parameter + *[other] parameters + } must be specified on the object type hir_analysis_multiple_relaxed_default_bounds = type parameter has more than one relaxed default bound, only one is supported @@ -489,21 +495,6 @@ hir_analysis_simd_ffi_highly_experimental = use of SIMD type{$snip} in FFI is hi hir_analysis_specialization_trait = implementing `rustc_specialization_trait` traits is unstable .help = add `#![feature(min_specialization)]` to the crate attributes to enable -hir_analysis_start_function_parameters = `#[start]` function is not allowed to have type parameters - .label = `#[start]` function cannot have type parameters - -hir_analysis_start_function_where = `#[start]` function is not allowed to have a `where` clause - .label = `#[start]` function cannot have a `where` clause - -hir_analysis_start_not_async = `#[start]` function is not allowed to be `async` - .label = `#[start]` is not allowed to be `async` - -hir_analysis_start_not_target_feature = `#[start]` function is not allowed to have `#[target_feature]` - .label = `#[start]` function is not allowed to have `#[target_feature]` - -hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]` - .label = `#[start]` function is not allowed to be `#[track_caller]` - hir_analysis_static_specialize = cannot specialize on `'static` lifetime hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index d8e9227a87c..b3eade8c8ae 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { if self.infcx.next_trait_solver() && let ty::Alias(..) = ty.kind() { - let (normalized_ty, obligations) = self.structurally_normalize(ty)?; + let (normalized_ty, obligations) = self.structurally_normalize_ty(ty)?; self.state.obligations.extend(obligations); (AutoderefKind::Builtin, normalized_ty) } else { @@ -166,7 +166,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { } let (normalized_ty, obligations) = - self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?; + self.structurally_normalize_ty(Ty::new_projection(tcx, trait_target_def_id, [ty]))?; debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); self.state.obligations.extend(obligations); @@ -174,12 +174,12 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { } #[instrument(level = "debug", skip(self), ret)] - pub fn structurally_normalize( + pub fn structurally_normalize_ty( &self, ty: Ty<'tcx>, ) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> { let ocx = ObligationCtxt::new(self.infcx); - let Ok(normalized_ty) = ocx.structurally_normalize( + let Ok(normalized_ty) = ocx.structurally_normalize_ty( &traits::ObligationCause::misc(self.span, self.body_id), self.param_env, ty, diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 4a957d5da24..d2ab98bae89 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -6,9 +6,9 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; -use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{GenericParamKind, ImplItemKind, intravisit}; +use rustc_hir::intravisit::VisitorExt; +use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; @@ -1610,7 +1610,7 @@ fn compare_synthetic_generics<'tcx>( struct Visitor(hir::def_id::LocalDefId); impl<'v> intravisit::Visitor<'v> for Visitor { type Result = ControlFlow<Span>; - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) -> Self::Result { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) -> Self::Result { if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind && let Res::Def(DefKind::TyParam, def_id) = path.res && def_id == self.0.to_def_id() @@ -1622,9 +1622,9 @@ fn compare_synthetic_generics<'tcx>( } } - let span = input_tys.iter().find_map(|ty| { - intravisit::Visitor::visit_ty(&mut Visitor(impl_def_id), ty).break_value() - })?; + let span = input_tys + .iter() + .find_map(|ty| Visitor(impl_def_id).visit_ty_unambig(ty).break_value())?; let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds; let bounds = bounds.first()?.span().to(bounds.last()?.span()); @@ -2362,7 +2362,7 @@ fn try_report_async_mismatch<'tcx>( // the right span is a bit difficult. return Err(tcx.sess.dcx().emit_err(MethodShouldReturnFuture { span: tcx.def_span(impl_m.def_id), - method_name: trait_m.name, + method_name: tcx.item_ident(impl_m.def_id), trait_item_span: tcx.hir().span_if_local(trait_m.def_id), })); } diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 332ac2fa0c0..25c2f8554b7 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -5,7 +5,7 @@ use rustc_hir as hir; use rustc_hir::Node; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::span_bug; -use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_session::config::EntryFnType; use rustc_span::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_span::{Span, sym}; @@ -18,7 +18,6 @@ use crate::errors; pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) { match tcx.entry_fn(()) { Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id), - Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id), _ => {} } } @@ -192,83 +191,3 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { }); } } - -fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { - let start_def_id = start_def_id.expect_local(); - let start_id = tcx.local_def_id_to_hir_id(start_def_id); - let start_span = tcx.def_span(start_def_id); - let start_t = tcx.type_of(start_def_id).instantiate_identity(); - match start_t.kind() { - ty::FnDef(..) => { - if let Node::Item(it) = tcx.hir_node(start_id) { - if let hir::ItemKind::Fn { sig, generics, .. } = &it.kind { - let mut error = false; - if !generics.params.is_empty() { - tcx.dcx().emit_err(errors::StartFunctionParameters { span: generics.span }); - error = true; - } - if generics.has_where_clause_predicates { - tcx.dcx().emit_err(errors::StartFunctionWhere { - span: generics.where_clause_span, - }); - error = true; - } - if sig.header.asyncness.is_async() { - let span = tcx.def_span(it.owner_id); - tcx.dcx().emit_err(errors::StartAsync { span }); - error = true; - } - - let attrs = tcx.hir().attrs(start_id); - for attr in attrs { - if attr.has_name(sym::track_caller) { - tcx.dcx().emit_err(errors::StartTrackCaller { - span: attr.span, - start: start_span, - }); - error = true; - } - if attr.has_name(sym::target_feature) - // Calling functions with `#[target_feature]` is - // not unsafe on WASM, see #84988 - && !tcx.sess.target.is_like_wasm - && !tcx.sess.opts.actually_rustdoc - { - tcx.dcx().emit_err(errors::StartTargetFeature { - span: attr.span, - start: start_span, - }); - error = true; - } - } - - if error { - return; - } - } - } - - let expected_sig = ty::Binder::dummy(tcx.mk_fn_sig( - [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))], - tcx.types.isize, - false, - hir::Safety::Safe, - ExternAbi::Rust, - )); - - let _ = check_function_signature( - tcx, - ObligationCause::new( - start_span, - start_def_id, - ObligationCauseCode::StartFunctionType, - ), - start_def_id.into(), - expected_sig, - ); - } - _ => { - span_bug!(start_span, "start has a non-function type: found `{}`", start_t); - } - } -} diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 92b18c80fd8..69b4aa47eba 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -197,7 +197,7 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: LocalDefId) { fn report_forbidden_specialization(tcx: TyCtxt<'_>, impl_item: DefId, parent_impl: DefId) { let span = tcx.def_span(impl_item); - let ident = tcx.item_name(impl_item); + let ident = tcx.item_ident(impl_item); let err = match tcx.span_of_impl(parent_impl) { Ok(sp) => errors::ImplNotMarkedDefault::Ok { span, ident, ok_label: sp }, @@ -297,7 +297,7 @@ fn default_body_is_unstable( reason: Option<Symbol>, issue: Option<NonZero<u32>>, ) { - let missing_item_name = tcx.associated_item(item_did).name; + let missing_item_name = tcx.item_ident(item_did); let (mut some_note, mut none_note, mut reason_str) = (false, false, String::new()); match reason { Some(r) => { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index dd6adb17c5e..cd19993f937 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -6,10 +6,10 @@ use rustc_abi::ExternAbi; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; -use rustc_hir::ItemKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::lang_items::LangItem; +use rustc_hir::{AmbigArg, ItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_macros::LintDiagnostic; @@ -2196,7 +2196,7 @@ impl<'tcx> Visitor<'tcx> for CollectUsageSpans<'_> { // Skip the generics. We only care about fields, not where clause/param bounds. } - fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result { + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { if let hir::TyKind::Path(hir::QPath::Resolved(None, qpath)) = t.kind { if let Res::Def(DefKind::TyParam, def_id) = qpath.res && def_id == self.param_def_id diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index b43a808ccdc..27a7c2ea530 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -292,7 +292,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() res = Err(tcx.dcx().emit_err(errors::DispatchFromDynZST { span, - name: field.name, + name: field.ident(tcx), ty: ty_a, })); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 1be4aa2f63a..4e5f0a3186a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -13,6 +13,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_session::parse::feature_err; use rustc_span::{ErrorGuaranteed, sym}; +use rustc_type_ir::elaborate; use tracing::debug; use crate::errors; @@ -184,7 +185,7 @@ fn check_object_overlap<'tcx>( // check for overlap with the automatic `impl Trait for dyn Trait` if let ty::Dynamic(data, ..) = trait_ref.self_ty().kind() { // This is something like `impl Trait1 for Trait2`. Illegal if - // Trait1 is a supertrait of Trait2 or Trait2 is not dyn-compatible. + // Trait1 is a supertrait of Trait2 or Trait2 is not dyn compatible. let component_def_ids = data.iter().flat_map(|predicate| { match predicate.skip_binder() { @@ -205,7 +206,7 @@ fn check_object_overlap<'tcx>( // With the feature enabled, the trait is not implemented automatically, // so this is valid. } else { - let mut supertrait_def_ids = tcx.supertrait_def_ids(component_def_id); + let mut supertrait_def_ids = elaborate::supertrait_def_ids(tcx, component_def_id); if supertrait_def_ids .any(|d| d == trait_def_id && tcx.trait_def(d).implement_via_object) { diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 7d651155781..dbf7a7378f5 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -320,7 +320,7 @@ fn orphan_check<'tcx>( } let ty = if infcx.next_trait_solver() { - ocx.structurally_normalize( + ocx.structurally_normalize_ty( &cause, ty::ParamEnv::empty(), infcx.resolve_vars_if_possible(ty), @@ -465,8 +465,8 @@ fn emit_orphan_check_error<'tcx>( traits::OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => { let mut reported = None; for param_def_id in uncovered { - let span = tcx.def_ident_span(param_def_id).unwrap(); - let name = tcx.item_name(param_def_id); + let name = tcx.item_ident(param_def_id); + let span = name.span; reported.get_or_insert(match local_ty { Some(local_type) => tcx.dcx().emit_err(errors::TyParamFirstLocal { @@ -492,7 +492,7 @@ fn lint_uncovered_ty_params<'tcx>( for param_def_id in uncovered { let span = tcx.def_ident_span(param_def_id).unwrap(); - let name = tcx.item_name(param_def_id); + let name = tcx.item_ident(param_def_id); match local_ty { Some(local_type) => tcx.emit_node_span_lint( diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 86c6532c97d..447050ea7d2 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -28,7 +28,7 @@ use rustc_errors::{ }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{self, Visitor, walk_generics}; +use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt, walk_generics}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; @@ -139,29 +139,12 @@ pub(crate) struct HirPlaceholderCollector { } impl<'v> Visitor<'v> for HirPlaceholderCollector { - fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { - if let hir::TyKind::Infer = t.kind { - self.spans.push(t.span); - } - intravisit::walk_ty(self, t) - } - fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) { - match generic_arg { - hir::GenericArg::Infer(inf) => { - self.spans.push(inf.span); - self.may_contain_const_infer = true; - intravisit::walk_inf(self, inf); - } - hir::GenericArg::Type(t) => self.visit_ty(t), - _ => {} - } - } - fn visit_const_arg(&mut self, const_arg: &'v hir::ConstArg<'v>) { - if let hir::ConstArgKind::Infer(span) = const_arg.kind { + fn visit_infer(&mut self, _inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result { + self.spans.push(inf_span); + + if let InferKind::Const(_) | InferKind::Ambig(_) = kind { self.may_contain_const_infer = true; - self.spans.push(span); } - intravisit::walk_const_arg(self, const_arg) } } @@ -583,7 +566,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { .iter() .enumerate() .map(|(i, a)| { - if let hir::TyKind::Infer = a.kind { + if let hir::TyKind::Infer(()) = a.kind { if let Some(suggested_ty) = self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) { @@ -593,21 +576,21 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } // Only visit the type looking for `_` if we didn't fix the type above - visitor.visit_ty(a); + visitor.visit_ty_unambig(a); self.lowerer().lower_arg_ty(a, None) }) .collect(); let output_ty = match decl.output { hir::FnRetTy::Return(output) => { - if let hir::TyKind::Infer = output.kind + if let hir::TyKind::Infer(()) = output.kind && let Some(suggested_ty) = self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None) { infer_replacements.push((output.span, suggested_ty.to_string())); Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string()) } else { - visitor.visit_ty(output); + visitor.visit_ty_unambig(output); self.lower_ty(output) } } @@ -945,7 +928,7 @@ fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed { span, discr: prev_discr.unwrap().to_string(), - item_name: tcx.item_name(variant.def_id), + item_name: tcx.item_ident(variant.def_id), wrapped_discr: wrapped_discr.to_string(), }); None @@ -1007,11 +990,10 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> { } /// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before. - fn check_field_decl(&mut self, ident: Ident, field_decl: FieldDeclSpan) { + fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) { use FieldDeclSpan::*; - let field_name = ident.name; - let ident = ident.normalize_to_macros_2_0(); - match (field_decl, self.seen_fields.get(&ident).copied()) { + let field_name = field_name.normalize_to_macros_2_0(); + match (field_decl, self.seen_fields.get(&field_name).copied()) { (NotNested(span), Some(NotNested(prev_span))) => { self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested { field_name, @@ -1052,7 +1034,7 @@ impl<'tcx> FieldUniquenessCheckContext<'tcx> { }); } (field_decl, None) => { - self.seen_fields.insert(ident, field_decl); + self.seen_fields.insert(field_name, field_decl); } } } @@ -1453,7 +1435,7 @@ fn recover_infer_ret_ty<'tcx>( }); let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_ty(infer_ret_ty); + visitor.visit_ty_unambig(infer_ret_ty); let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type"); let ret_ty = fn_sig.output(); diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 075615de522..2ac8acbd3a4 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -3,9 +3,10 @@ use std::ops::ControlFlow; use hir::intravisit::{self, Visitor}; use hir::{GenericParamKind, HirId, Node}; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; +use rustc_hir::intravisit::VisitorExt; +use rustc_hir::{self as hir, AmbigArg}; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; use rustc_span::{Span, Symbol, kw}; @@ -461,7 +462,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> { type Result = ControlFlow<Span>; - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) -> ControlFlow<Span> { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) -> ControlFlow<Span> { match ty.kind { hir::TyKind::BareFn(..) => { self.outer_index.shift_in(1); @@ -539,7 +540,7 @@ impl<'v> Visitor<'v> for AnonConstInParamTyDetector { if let GenericParamKind::Const { ty, default: _, synthetic: _ } = p.kind { let prev = self.in_param_ty; self.in_param_ty = true; - let res = self.visit_ty(ty); + let res = self.visit_ty_unambig(ty); self.in_param_ty = prev; res } else { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index e8706d1adfb..72baf5c4b58 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -14,11 +14,11 @@ use rustc_ast::visit::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::ErrorGuaranteed; -use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; use rustc_hir::{ - GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap, LifetimeName, Node, + self as hir, AmbigArg, GenericArg, GenericParam, GenericParamKind, HirId, ItemLocalMap, + LifetimeName, Node, }; use rustc_macros::extension; use rustc_middle::hir::nested_filter; @@ -184,29 +184,11 @@ enum Scope<'a> { }, } -#[derive(Copy, Clone, Debug)] -enum BinderScopeType { - /// Any non-concatenating binder scopes. - Normal, - /// Within a syntactic trait ref, there may be multiple poly trait refs that - /// are nested (under the `associated_type_bounds` feature). The binders of - /// the inner poly trait refs are extended from the outer poly trait refs - /// and don't increase the late bound depth. If you had - /// `T: for<'a> Foo<Bar: for<'b> Baz<'a, 'b>>`, then the `for<'b>` scope - /// would be `Concatenating`. This also used in trait refs in where clauses - /// where we have two binders `for<> T: for<> Foo` (I've intentionally left - /// out any lifetimes because they aren't needed to show the two scopes). - /// The inner `for<>` has a scope of `Concatenating`. - Concatenating, -} - -// A helper struct for debugging scopes without printing parent scopes -struct TruncatedScopeDebug<'a>(&'a Scope<'a>); - -impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - Scope::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f +impl<'a> Scope<'a> { + // A helper for debugging scopes without printing parent scopes + fn debug_truncated(&'a self) -> impl fmt::Debug + 'a { + fmt::from_fn(move |f| match self { + Self::Binder { bound_vars, scope_type, hir_id, where_bound_origin, s: _ } => f .debug_struct("Binder") .field("bound_vars", bound_vars) .field("scope_type", scope_type) @@ -214,38 +196,54 @@ impl<'a> fmt::Debug for TruncatedScopeDebug<'a> { .field("where_bound_origin", where_bound_origin) .field("s", &"..") .finish(), - Scope::Opaque { captures, def_id, s: _ } => f + Self::Opaque { captures, def_id, s: _ } => f .debug_struct("Opaque") .field("def_id", def_id) .field("captures", &captures.borrow()) .field("s", &"..") .finish(), - Scope::Body { id, s: _ } => { + Self::Body { id, s: _ } => { f.debug_struct("Body").field("id", id).field("s", &"..").finish() } - Scope::ObjectLifetimeDefault { lifetime, s: _ } => f + Self::ObjectLifetimeDefault { lifetime, s: _ } => f .debug_struct("ObjectLifetimeDefault") .field("lifetime", lifetime) .field("s", &"..") .finish(), - Scope::Supertrait { bound_vars, s: _ } => f + Self::Supertrait { bound_vars, s: _ } => f .debug_struct("Supertrait") .field("bound_vars", bound_vars) .field("s", &"..") .finish(), - Scope::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), - Scope::LateBoundary { s: _, what, deny_late_regions } => f + Self::TraitRefBoundary { s: _ } => f.debug_struct("TraitRefBoundary").finish(), + Self::LateBoundary { s: _, what, deny_late_regions } => f .debug_struct("LateBoundary") .field("what", what) .field("deny_late_regions", deny_late_regions) .finish(), - Scope::Root { opt_parent_item } => { + Self::Root { opt_parent_item } => { f.debug_struct("Root").field("opt_parent_item", &opt_parent_item).finish() } - } + }) } } +#[derive(Copy, Clone, Debug)] +enum BinderScopeType { + /// Any non-concatenating binder scopes. + Normal, + /// Within a syntactic trait ref, there may be multiple poly trait refs that + /// are nested (under the `associated_type_bounds` feature). The binders of + /// the inner poly trait refs are extended from the outer poly trait refs + /// and don't increase the late bound depth. If you had + /// `T: for<'a> Foo<Bar: for<'b> Baz<'a, 'b>>`, then the `for<'b>` scope + /// would be `Concatenating`. This also used in trait refs in where clauses + /// where we have two binders `for<> T: for<> Foo` (I've intentionally left + /// out any lifetimes because they aren't needed to show the two scopes). + /// The inner `for<>` has a scope of `Concatenating`. + Concatenating, +} + type ScopeRef<'a> = &'a Scope<'a>; pub(crate) fn provide(providers: &mut Providers) { @@ -489,15 +487,17 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { struct FindInferInClosureWithBinder; impl<'v> Visitor<'v> for FindInferInClosureWithBinder { type Result = ControlFlow<Span>; - fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result { - if matches!(t.kind, hir::TyKind::Infer) { - ControlFlow::Break(t.span) - } else { - intravisit::walk_ty(self, t) - } + + fn visit_infer( + &mut self, + _inf_id: HirId, + inf_span: Span, + _kind: InferKind<'v>, + ) -> Self::Result { + ControlFlow::Break(inf_span) } } - FindInferInClosureWithBinder.visit_ty(ty).break_value() + FindInferInClosureWithBinder.visit_ty_unambig(ty).break_value() } let infer_in_rt_sp = match fn_decl.output { @@ -749,7 +749,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { match ty.kind { hir::TyKind::BareFn(c) => { let (mut bound_vars, binders): (FxIndexMap<LocalDefId, ResolvedArg>, Vec<_>) = c @@ -810,7 +810,9 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { intravisit::walk_ty(this, ty); }); } - hir::TyKind::TraitObject(bounds, lifetime, _) => { + hir::TyKind::TraitObject(bounds, lifetime) => { + let lifetime = lifetime.pointer(); + debug!(?bounds, ?lifetime, "TraitObject"); let scope = Scope::TraitRefBoundary { s: self.scope }; self.with(scope, |this| { @@ -827,7 +829,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // use the object lifetime defaulting // rules. So e.g., `Box<dyn Debug>` becomes // `Box<dyn Debug + 'static>`. - self.resolve_object_lifetime_default(lifetime) + self.resolve_object_lifetime_default(&*lifetime) } LifetimeName::Infer => { // If the user writes `'_`, we use the *ordinary* elision @@ -838,7 +840,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } LifetimeName::Param(..) | LifetimeName::Static => { // If the user wrote an explicit name, use that. - self.visit_lifetime(lifetime); + self.visit_lifetime(&*lifetime); } LifetimeName::Error => {} } @@ -849,7 +851,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { lifetime: self.map.defs.get(&lifetime_ref.hir_id.local_id).cloned(), s: self.scope, }; - self.with(scope, |this| this.visit_ty(mt.ty)); + self.with(scope, |this| this.visit_ty_unambig(mt.ty)); } hir::TyKind::TraitAscription(bounds) => { let scope = Scope::TraitRefBoundary { s: self.scope }; @@ -891,7 +893,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { this.visit_param_bound(bound); } if let Some(ty) = ty { - this.visit_ty(ty); + this.visit_ty_unambig(ty); } }) } @@ -910,7 +912,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }), Type(ty) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| { this.visit_generics(impl_item.generics); - this.visit_ty(ty); + this.visit_ty_unambig(ty); }), Const(_, _) => self.visit_early(impl_item.hir_id(), impl_item.generics, |this| { intravisit::walk_impl_item(this, impl_item) @@ -1019,7 +1021,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }; self.with(scope, |this| { walk_list!(this, visit_generic_param, bound_generic_params); - this.visit_ty(bounded_ty); + this.visit_ty_unambig(bounded_ty); walk_list!(this, visit_param_bound, bounds); }) } @@ -1034,8 +1036,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => { - self.visit_ty(lhs_ty); - self.visit_ty(rhs_ty); + self.visit_ty_unambig(lhs_ty); + self.visit_ty_unambig(rhs_ty); } } } @@ -1068,13 +1070,13 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { default, .. } => { if let Some(ty) = default { - self.visit_ty(ty); + self.visit_ty_unambig(ty); } } GenericParamKind::Const { ty, default, .. } => { - self.visit_ty(ty); + self.visit_ty_unambig(ty); if let Some(default) = default { - self.visit_const_arg(default); + self.visit_const_arg_unambig(default); } } } @@ -1140,7 +1142,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { { let BoundVarContext { tcx, map, .. } = self; let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope }; - let span = debug_span!("scope", scope = ?TruncatedScopeDebug(this.scope)); + let span = debug_span!("scope", scope = ?this.scope.debug_truncated()); { let _enter = span.enter(); f(&mut this); @@ -1983,15 +1985,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }, |this| { for input in inputs { - this.visit_ty(input); + this.visit_ty_unambig(input); } if !in_closure && let Some(output) = output { - this.visit_ty(output); + this.visit_ty_unambig(output); } }, ); if in_closure && let Some(output) = output { - self.visit_ty(output); + self.visit_ty_unambig(output); } } @@ -2309,7 +2311,7 @@ fn is_late_bound_map( let mut constrained_by_input = ConstrainedCollector { regions: Default::default(), tcx }; for arg_ty in sig.decl.inputs { - constrained_by_input.visit_ty(arg_ty); + constrained_by_input.visit_ty_unambig(arg_ty); } let mut appears_in_output = @@ -2417,7 +2419,7 @@ fn is_late_bound_map( } impl<'v> Visitor<'v> for ConstrainedCollector<'_> { - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { match ty.kind { hir::TyKind::Path( hir::QPath::Resolved(Some(_), _) | hir::QPath::TypeRelative(..), diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 51e15767b8c..348d4d708b5 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -1,10 +1,9 @@ use core::ops::ControlFlow; use rustc_errors::{Applicability, StashKey, Suggestions}; -use rustc_hir as hir; -use rustc_hir::HirId; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::VisitorExt; +use rustc_hir::{self as hir, AmbigArg, HirId}; use rustc_middle::query::plumbing::CyclePlaceholder; use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::print::with_forced_trimmed_paths; @@ -451,7 +450,7 @@ fn infer_placeholder_type<'tcx>( let mut visitor = HirPlaceholderCollector::default(); let node = tcx.hir_node_by_def_id(def_id); if let Some(ty) = node.ty() { - visitor.visit_ty(ty); + visitor.visit_ty_unambig(ty); } // If we have just one span, let's try to steal a const `_` feature error. let try_steal_span = if !tcx.features().generic_arg_infer() && visitor.spans.len() == 1 @@ -525,7 +524,7 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> struct HasTait; impl<'tcx> Visitor<'tcx> for HasTait { type Result = ControlFlow<()>; - fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) -> Self::Result { + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { if let hir::TyKind::OpaqueDef(..) = t.kind { ControlFlow::Break(()) } else { @@ -533,5 +532,5 @@ pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> } } } - HasTait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break() + HasTait.visit_ty_unambig(tcx.hir().expect_item(def_id).expect_ty_alias().0).is_break() } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index d1a1e36c1d5..e2b9fe0f9f7 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -55,7 +55,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( } else { let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), - name: tcx.item_name(parent_def_id.to_def_id()), + name: tcx.item_ident(parent_def_id.to_def_id()), what: "impl", }); Ty::new_error(tcx, reported) @@ -136,7 +136,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local } let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), - name: tcx.item_name(parent_def_id.to_def_id()), + name: tcx.item_ident(parent_def_id.to_def_id()), what: match tcx.hir_node(scope) { _ if scope == hir::CRATE_HIR_ID => "module", Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module", diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 00ba1741ed7..1dcea5d0335 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -217,7 +217,7 @@ pub(crate) struct DropImplOnWrongItem { pub(crate) enum FieldAlreadyDeclared { #[diag(hir_analysis_field_already_declared, code = E0124)] NotNested { - field_name: Symbol, + field_name: Ident, #[primary_span] #[label] span: Span, @@ -226,7 +226,7 @@ pub(crate) enum FieldAlreadyDeclared { }, #[diag(hir_analysis_field_already_declared_current_nested)] CurrentNested { - field_name: Symbol, + field_name: Ident, #[primary_span] #[label] span: Span, @@ -239,7 +239,7 @@ pub(crate) enum FieldAlreadyDeclared { }, #[diag(hir_analysis_field_already_declared_previous_nested)] PreviousNested { - field_name: Symbol, + field_name: Ident, #[primary_span] #[label] span: Span, @@ -252,7 +252,7 @@ pub(crate) enum FieldAlreadyDeclared { }, #[diag(hir_analysis_field_already_declared_both_nested)] BothNested { - field_name: Symbol, + field_name: Ident, #[primary_span] #[label] span: Span, @@ -418,7 +418,7 @@ pub(crate) struct ValueOfAssociatedStructAlreadySpecified { pub(crate) struct UnconstrainedOpaqueType { #[primary_span] pub span: Span, - pub name: Symbol, + pub name: Ident, pub what: &'static str, } @@ -620,48 +620,6 @@ pub(crate) struct TargetFeatureOnMain { } #[derive(Diagnostic)] -#[diag(hir_analysis_start_not_track_caller)] -pub(crate) struct StartTrackCaller { - #[primary_span] - pub span: Span, - #[label] - pub start: Span, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis_start_not_target_feature)] -pub(crate) struct StartTargetFeature { - #[primary_span] - pub span: Span, - #[label] - pub start: Span, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis_start_not_async, code = E0752)] -pub(crate) struct StartAsync { - #[primary_span] - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis_start_function_where, code = E0647)] -pub(crate) struct StartFunctionWhere { - #[primary_span] - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis_start_function_parameters, code = E0132)] -pub(crate) struct StartFunctionParameters { - #[primary_span] - #[label] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(hir_analysis_main_function_return_type_generic, code = E0131)] pub(crate) struct MainFunctionReturnTypeGeneric { #[primary_span] @@ -844,7 +802,7 @@ pub(crate) struct EnumDiscriminantOverflowed { #[label] pub span: Span, pub discr: String, - pub item_name: Symbol, + pub item_name: Ident, pub wrapped_discr: String, } @@ -935,7 +893,7 @@ pub(crate) enum ImplNotMarkedDefault { span: Span, #[label(hir_analysis_ok_label)] ok_label: Span, - ident: Symbol, + ident: Ident, }, #[diag(hir_analysis_impl_not_marked_default_err, code = E0520)] #[note] @@ -943,7 +901,7 @@ pub(crate) enum ImplNotMarkedDefault { #[primary_span] span: Span, cname: Symbol, - ident: Symbol, + ident: Ident, }, } @@ -1019,7 +977,7 @@ pub(crate) struct MissingTraitItemUnstable { pub some_note: bool, #[note(hir_analysis_none_note)] pub none_note: bool, - pub missing_item_name: Symbol, + pub missing_item_name: Ident, pub feature: Symbol, pub reason: String, } @@ -1291,7 +1249,7 @@ pub(crate) struct InherentNominal { pub(crate) struct DispatchFromDynZST<'a> { #[primary_span] pub span: Span, - pub name: Symbol, + pub name: Ident, pub ty: Ty<'a>, } @@ -1431,7 +1389,7 @@ pub(crate) struct TyParamFirstLocal<'tcx> { pub span: Span, #[note(hir_analysis_case_note)] pub note: (), - pub param: Symbol, + pub param: Ident, pub local_type: Ty<'tcx>, } @@ -1443,7 +1401,7 @@ pub(crate) struct TyParamFirstLocalLint<'tcx> { pub span: Span, #[note(hir_analysis_case_note)] pub note: (), - pub param: Symbol, + pub param: Ident, pub local_type: Ty<'tcx>, } @@ -1456,7 +1414,7 @@ pub(crate) struct TyParamSome { pub span: Span, #[note(hir_analysis_only_note)] pub note: (), - pub param: Symbol, + pub param: Ident, } #[derive(LintDiagnostic)] @@ -1467,7 +1425,7 @@ pub(crate) struct TyParamSomeLint { pub span: Span, #[note(hir_analysis_only_note)] pub note: (), - pub param: Symbol, + pub param: Ident, } #[derive(Diagnostic)] @@ -1575,7 +1533,7 @@ pub(crate) struct UnsupportedDelegation<'a> { pub(crate) struct MethodShouldReturnFuture { #[primary_span] pub span: Span, - pub method_name: Symbol, + pub method_name: Ident, #[note] pub trait_item_span: Option<Span>, } @@ -1627,7 +1585,7 @@ pub(crate) struct UnconstrainedGenericParameter { #[primary_span] #[label] pub span: Span, - pub param_name: Symbol, + pub param_name: Ident, pub param_def_kind: &'static str, #[note(hir_analysis_const_param_note)] pub const_param_note: bool, diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs index 5ae7944f6d5..67407349729 100644 --- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs @@ -495,7 +495,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { .iter() .any(|constraint| constraint.ident.name == item.name) }) - .map(|item| item.name.to_ident_string()) + .map(|item| self.tcx.item_ident(item.def_id).to_string()) .collect() } else { Vec::default() diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 39471931461..4c8f2735b97 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -201,7 +201,7 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError use LayoutError::*; match layout_err { - Unknown(ty) => { + TooGeneric(ty) => { match abi { ExternAbi::CCmseNonSecureCall => { // prevent double reporting of this error @@ -211,7 +211,11 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError _ => bug!("invalid ABI: {abi}"), } } - SizeOverflow(..) | NormalizationFailure(..) | ReferencesError(..) | Cycle(..) => { + Unknown(..) + | SizeOverflow(..) + | NormalizationFailure(..) + | ReferencesError(..) + | Cycle(..) => { false // not our job to report these } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 71a5727ed6c..e59ff02642c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -4,13 +4,12 @@ use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; -use rustc_middle::span_bug; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::{ self, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; -use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; +use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{self, hir_ty_lowering_dyn_compatibility_violations}; use rustc_type_ir::elaborate::ClauseWithSupertraitSpan; @@ -30,16 +29,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &self, span: Span, hir_id: hir::HirId, - hir_trait_bounds: &[hir::PolyTraitRef<'tcx>], + hir_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, representation: DynKind, ) -> Ty<'tcx> { let tcx = self.tcx(); + let dummy_self = tcx.types.trait_object_dummy_self; - let mut bounds = Bounds::default(); + let mut user_written_bounds = Bounds::default(); let mut potential_assoc_types = Vec::new(); - let dummy_self = self.tcx().types.trait_object_dummy_self; - for trait_bound in hir_trait_bounds.iter().rev() { + for trait_bound in hir_bounds.iter() { if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity { continue; } @@ -53,92 +52,67 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::BoundConstness::Never, hir::BoundPolarity::Positive, dummy_self, - &mut bounds, + &mut user_written_bounds, PredicateFilter::SelfOnly, ) { potential_assoc_types.extend(cur_potential_assoc_types); } } - let mut trait_bounds = vec![]; - let mut projection_bounds = vec![]; - for (pred, span) in bounds.clauses() { - let bound_pred = pred.kind(); - match bound_pred.skip_binder() { - ty::ClauseKind::Trait(trait_pred) => { - assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); - trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span)); - } - ty::ClauseKind::Projection(proj) => { - projection_bounds.push((bound_pred.rebind(proj), span)); - } - ty::ClauseKind::TypeOutlives(_) => { - // Do nothing, we deal with regions separately - } - ty::ClauseKind::RegionOutlives(_) - | ty::ClauseKind::ConstArgHasType(..) - | ty::ClauseKind::WellFormed(_) - | ty::ClauseKind::ConstEvaluatable(_) - | ty::ClauseKind::HostEffect(..) => { - span_bug!(span, "did not expect {pred} clause in object bounds"); - } - } - } - - // Expand trait aliases recursively and check that only one regular (non-auto) trait - // is used and no 'maybe' bounds are used. - let expanded_traits = - traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); - - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = - expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); + let (trait_bounds, mut projection_bounds) = + traits::expand_trait_aliases(tcx, user_written_bounds.clauses()); + let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds + .into_iter() + .partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); + // We don't support empty trait objects. + if regular_traits.is_empty() && auto_traits.is_empty() { + let guar = + self.report_trait_object_with_no_traits_error(span, user_written_bounds.clauses()); + return Ty::new_error(tcx, guar); + } // We don't support >1 principal if regular_traits.len() > 1 { let guar = self.report_trait_object_addition_traits_error(®ular_traits); return Ty::new_error(tcx, guar); } - // We don't support empty trait objects. - if regular_traits.is_empty() && auto_traits.is_empty() { - let guar = self.report_trait_object_with_no_traits_error(span, &trait_bounds); - return Ty::new_error(tcx, guar); - } // Don't create a dyn trait if we have errors in the principal. - if let Err(guar) = trait_bounds.error_reported() { + if let Err(guar) = regular_traits.error_reported() { return Ty::new_error(tcx, guar); } // Check that there are no gross dyn-compatibility violations; // most importantly, that the supertraits don't contain `Self`, // to avoid ICEs. - for item in ®ular_traits { - let violations = - hir_ty_lowering_dyn_compatibility_violations(tcx, item.trait_ref().def_id()); - if !violations.is_empty() { - let reported = report_dyn_incompatibility( - tcx, - span, - Some(hir_id), - item.trait_ref().def_id(), - &violations, - ) - .emit(); - return Ty::new_error(tcx, reported); + for (clause, span) in user_written_bounds.clauses() { + if let Some(trait_pred) = clause.as_trait_clause() { + let violations = + hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id()); + if !violations.is_empty() { + let reported = report_dyn_incompatibility( + tcx, + span, + Some(hir_id), + trait_pred.def_id(), + &violations, + ) + .emit(); + return Ty::new_error(tcx, reported); + } } } - let mut needed_associated_types = FxIndexSet::default(); - - let principal_span = regular_traits.first().map_or(DUMMY_SP, |info| info.bottom().1); - let regular_traits_refs_spans = trait_bounds - .into_iter() - .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); + let principal_trait = regular_traits.into_iter().next(); - for (base_trait_ref, original_span) in regular_traits_refs_spans { - let base_pred: ty::Predicate<'tcx> = base_trait_ref.upcast(tcx); + let mut needed_associated_types = FxIndexSet::default(); + if let Some((principal_trait, spans)) = &principal_trait { + let pred: ty::Predicate<'tcx> = (*principal_trait).upcast(tcx); for ClauseWithSupertraitSpan { pred, supertrait_span } in - traits::elaborate(tcx, [ClauseWithSupertraitSpan::new(base_pred, original_span)]) - .filter_only_self() + traits::elaborate(tcx, [ClauseWithSupertraitSpan::new( + pred, + *spans.last().unwrap(), + )]) + .filter_only_self() { debug!("observing object predicate `{pred:?}`"); @@ -179,7 +153,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // } // ``` // - // Here, the user could theoretically write `dyn MyTrait<Output = X>`, + // Here, the user could theoretically write `dyn MyTrait<MyOutput = X>`, // but actually supporting that would "expand" to an infinitely-long type // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`. // @@ -188,12 +162,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // the discussion in #56288 for alternatives. if !references_self { // Include projections defined on supertraits. - projection_bounds.push((pred, original_span)); + projection_bounds.push((pred, supertrait_span)); } self.check_elaborated_projection_mentions_input_lifetimes( pred, - original_span, + *spans.first().unwrap(), supertrait_span, ); } @@ -202,11 +176,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where <Self as Trait>::Assoc = Foo`. - // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated - // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a - // corresponding `Projection` clause - for (projection_bound, span) in &projection_bounds { + // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where + // <Self as Trait>::Assoc = Foo`. So every `Projection` clause is an + // `Assoc = Foo` bound. `needed_associated_types` contains all associated + // types that we expect to be provided by the user, so the following loop + // removes all the associated types that have a corresponding `Projection` + // clause, either from expanding trait aliases or written by the user. + for &(projection_bound, span) in &projection_bounds { let def_id = projection_bound.item_def_id(); let trait_ref = tcx.anonymize_bound_vars( projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)), @@ -216,17 +192,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx.emit_node_span_lint( UNUSED_ASSOCIATED_TYPE_BOUNDS, hir_id, - *span, - crate::errors::UnusedAssociatedTypeBounds { span: *span }, + span, + crate::errors::UnusedAssociatedTypeBounds { span }, ); } } if let Err(guar) = self.check_for_required_assoc_tys( - principal_span, + principal_trait.as_ref().map_or(smallvec![], |(_, spans)| spans.clone()), needed_associated_types, potential_assoc_types, - hir_trait_bounds, + hir_bounds, ) { return Ty::new_error(tcx, guar); } @@ -236,45 +212,42 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering // the bounds let mut duplicates = FxHashSet::default(); - auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id())); - debug!(?regular_traits); + auto_traits.retain(|(trait_pred, _)| duplicates.insert(trait_pred.def_id())); + + debug!(?principal_trait); debug!(?auto_traits); // Erase the `dummy_self` (`trait_object_dummy_self`) used above. - let existential_trait_refs = regular_traits.iter().map(|i| { - i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| { + let principal_trait_ref = principal_trait.map(|(trait_pred, spans)| { + trait_pred.map_bound(|trait_pred| { + let trait_ref = trait_pred.trait_ref; + assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive); assert_eq!(trait_ref.self_ty(), dummy_self); + let span = *spans.first().unwrap(); + // Verify that `dummy_self` did not leak inside default type parameters. This // could not be done at path creation, since we need to see through trait aliases. let mut missing_type_params = vec![]; - let mut references_self = false; let generics = tcx.generics_of(trait_ref.def_id); let args: Vec<_> = trait_ref .args .iter() .enumerate() - .skip(1) // Remove `Self` for `ExistentialPredicate`. + // Skip `Self` + .skip(1) .map(|(index, arg)| { - if arg == dummy_self.into() { + if arg.walk().any(|arg| arg == dummy_self.into()) { let param = &generics.own_params[index]; missing_type_params.push(param.name); Ty::new_misc_error(tcx).into() - } else if arg.walk().any(|arg| arg == dummy_self.into()) { - references_self = true; - let guar = self.dcx().span_delayed_bug( - span, - "trait object trait bounds reference `Self`", - ); - replace_dummy_self_with_error(tcx, arg, guar) } else { arg } }) .collect(); - let span = i.bottom().1; - let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| { + let empty_generic_args = hir_bounds.iter().any(|hir_bound| { hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id) && hir_bound.span.contains(span) }); @@ -285,26 +258,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { empty_generic_args, ); - if references_self { - let def_id = i.bottom().0.def_id(); - struct_span_code_err!( - self.dcx(), - i.bottom().1, - E0038, - "the {} `{}` cannot be made into an object", - tcx.def_descr(def_id), - tcx.item_name(def_id), - ) - .with_note( - rustc_middle::traits::DynCompatibilityViolation::SupertraitSelf( - smallvec![], - ) - .error_msg(), - ) - .emit(); - } - - ty::ExistentialTraitRef::new(tcx, trait_ref.def_id, args) + ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::new( + tcx, + trait_ref.def_id, + args, + )) }) }); @@ -327,21 +285,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { b.projection_term = replace_dummy_self_with_error(tcx, b.projection_term, guar); } - ty::ExistentialProjection::erase_self_ty(tcx, b) + ty::ExistentialPredicate::Projection(ty::ExistentialProjection::erase_self_ty( + tcx, b, + )) }) }); - let regular_trait_predicates = existential_trait_refs - .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); - let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { - ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) + let auto_trait_predicates = auto_traits.into_iter().map(|(trait_pred, _)| { + assert_eq!(trait_pred.polarity(), ty::PredicatePolarity::Positive); + assert_eq!(trait_pred.self_ty().skip_binder(), dummy_self); + + ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_pred.def_id())) }); + // N.b. principal, projections, auto traits // FIXME: This is actually wrong with multiple principals in regards to symbol mangling - let mut v = regular_trait_predicates - .chain( - existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)), - ) + let mut v = principal_trait_ref + .into_iter() + .chain(existential_projections) .chain(auto_trait_predicates) .collect::<SmallVec<[_; 8]>>(); v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 7a3d921f00e..36b214b6ae7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -9,9 +9,10 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_middle::bug; +use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _}; use rustc_middle::ty::{ - self, AdtDef, Binder, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeVisitableExt, + self, AdtDef, GenericParamDefKind, Ty, TyCtxt, TypeVisitableExt, suggest_constraining_type_param, }; use rustc_session::parse::feature_err; @@ -19,8 +20,9 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{ - FulfillmentError, TraitAliasExpansionInfo, dyn_compatibility_violations_for_assoc_item, + FulfillmentError, dyn_compatibility_violations_for_assoc_item, }; +use smallvec::SmallVec; use crate::errors::{ self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams, @@ -720,7 +722,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// emit a generic note suggesting using a `where` clause to constraint instead. pub(crate) fn check_for_required_assoc_tys( &self, - principal_span: Span, + spans: SmallVec<[Span; 1]>, missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>, potential_assoc_types: Vec<usize>, trait_bounds: &[hir::PolyTraitRef<'_>], @@ -729,6 +731,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return Ok(()); } + let principal_span = *spans.first().unwrap(); + let tcx = self.tcx(); // FIXME: This logic needs some more care w.r.t handling of conflicts let missing_assoc_types: Vec<_> = missing_assoc_types @@ -995,12 +999,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )), .. }) = node - && let Some(adt_def) = qself_ty.ty_adt_def() - && let [inherent_impl] = tcx.inherent_impls(adt_def.did()) - && let name = format!("{ident2}_{ident3}") - && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx - .associated_items(inherent_impl) - .filter_by_name_unhygienic(Symbol::intern(&name)) + && let Some(inherent_impls) = qself_ty + .ty_adt_def() + .map(|adt_def| tcx.inherent_impls(adt_def.did())) + .or_else(|| { + simplify_type(tcx, qself_ty, TreatParams::InstantiateWithInfer) + .map(|simple_ty| tcx.incoherent_impls(simple_ty)) + }) + && let name = Symbol::intern(&format!("{ident2}_{ident3}")) + && let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = inherent_impls + .iter() + .flat_map(|inherent_impl| { + tcx.associated_items(inherent_impl).filter_by_name_unhygienic(name) + }) .next() { Err(struct_span_code_err!(self.dcx(), span, E0223, "ambiguous associated type") @@ -1124,29 +1135,36 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub fn report_trait_object_addition_traits_error( &self, - regular_traits: &Vec<TraitAliasExpansionInfo<'_>>, + regular_traits: &Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>, ) -> ErrorGuaranteed { - let first_trait = ®ular_traits[0]; - let additional_trait = ®ular_traits[1]; + // we use the last span to point at the traits themselves, + // and all other preceding spans are trait alias expansions. + let (&first_span, first_alias_spans) = regular_traits[0].1.split_last().unwrap(); + let (&second_span, second_alias_spans) = regular_traits[1].1.split_last().unwrap(); let mut err = struct_span_code_err!( self.dcx(), - additional_trait.bottom().1, + *regular_traits[1].1.first().unwrap(), E0225, "only auto traits can be used as additional traits in a trait object" ); - additional_trait.label_with_exp_info( - &mut err, - "additional non-auto trait", - "additional use", - ); - first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use"); + err.span_label(first_span, "first non-auto trait"); + for &alias_span in first_alias_spans { + err.span_label(alias_span, "first non-auto trait comes from this alias"); + } + err.span_label(second_span, "additional non-auto trait"); + for &alias_span in second_alias_spans { + err.span_label(alias_span, "second non-auto trait comes from this alias"); + } err.help(format!( "consider creating a new trait with all of these as supertraits and using that \ trait here instead: `trait NewTrait: {} {{}}`", regular_traits .iter() // FIXME: This should `print_sugared`, but also needs to integrate projection bounds... - .map(|t| t.trait_ref().print_only_trait_path().to_string()) + .map(|(pred, _)| pred + .map_bound(|pred| pred.trait_ref) + .print_only_trait_path() + .to_string()) .collect::<Vec<_>>() .join(" + "), )); @@ -1161,14 +1179,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub fn report_trait_object_with_no_traits_error( &self, span: Span, - trait_bounds: &Vec<(Binder<'tcx, TraitRef<'tcx>>, Span)>, + user_written_clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>, ) -> ErrorGuaranteed { let tcx = self.tcx(); - let trait_alias_span = trait_bounds - .iter() - .map(|&(trait_ref, _)| trait_ref.def_id()) - .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) - .map(|trait_ref| tcx.def_span(trait_ref)); + let trait_alias_span = user_written_clauses + .into_iter() + .filter_map(|(clause, _)| clause.as_trait_clause()) + .find(|trait_ref| tcx.is_trait_alias(trait_ref.def_id())) + .map(|trait_ref| tcx.def_span(trait_ref.def_id())); self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index df00948dd21..fe3dcb35639 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -1,10 +1,9 @@ use rustc_ast::ast::ParamKindOrd; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, struct_span_code_err}; -use rustc_hir as hir; -use rustc_hir::GenericArg; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; +use rustc_hir::{self as hir, GenericArg}; use rustc_middle::ty::{ self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty, }; @@ -41,17 +40,6 @@ fn generic_arg_mismatch_err( param.kind.descr(), ); - if let GenericParamDefKind::Const { .. } = param.kind { - if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. })) { - err.help("const arguments cannot yet be inferred with `_`"); - tcx.disabled_nightly_features( - &mut err, - param.def_id.as_local().map(|local| tcx.local_def_id_to_hir_id(local)), - [(String::new(), sym::generic_arg_infer)], - ); - } - } - let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut Diag<'_>| { let suggestions = vec![ (arg.span().shrink_to_lo(), String::from("{ ")), @@ -270,6 +258,21 @@ pub fn lower_generic_args<'tcx: 'a, 'a>( GenericParamDefKind::Const { .. }, _, ) => { + if let GenericParamDefKind::Const { .. } = param.kind + && let GenericArg::Infer(inf) = arg + && !tcx.features().generic_arg_infer() + { + rustc_session::parse::feature_err( + tcx.sess, + sym::generic_arg_infer, + inf.span, + "const arguments cannot yet be inferred with `_`", + ) + .emit(); + } + + // We lower to an infer even when the feature gate is not enabled + // as it is useful for diagnostics to be able to see a `ConstKind::Infer` args.push(ctx.provided_kind(&args, param, arg)); args_iter.next(); params.next(); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index a1f2b8c7594..539c5f6a20a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -23,9 +23,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Option<ErrorGuaranteed> { let tcx = self.tcx(); - let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = + let poly_trait_ref = if let hir::TyKind::TraitObject([poly_trait_ref, ..], tagged_ptr) = self_ty.kind - else { + && let TraitObjectSyntax::None = tagged_ptr.tag() + { + poly_trait_ref + } else { return None; }; @@ -294,7 +297,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let (dyn_str, paren_dyn_str) = if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") }; - let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { + let sugg = if let hir::TyKind::TraitObject([_, _, ..], _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. vec![ (self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index cb90fff782f..61d5869c19f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -517,14 +517,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lowerer.lower_lifetime(lt, RegionInferReason::Param(param)).into() } (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => { - handle_ty_args(has_default, ty) + // We handle the other parts of `Ty` in the match arm below + handle_ty_args(has_default, ty.as_unambig_ty()) } (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Infer(inf)) => { handle_ty_args(has_default, &inf.to_ty()) } - (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.lowerer.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into() - } + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self + .lowerer + // Ambig portions of `ConstArg` are handled in the match arm below + .lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id)) + .into(), (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { self.lowerer.ct_infer(Some(param), inf.span).into() } @@ -2115,7 +2118,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { format!("Const::lower_const_arg: invalid qpath {qpath:?}"), ), hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon), - hir::ConstArgKind::Infer(span) => self.ct_infer(None, span), + hir::ConstArgKind::Infer(span, ()) => self.ct_infer(None, span), } } @@ -2311,7 +2314,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx.late_bound_vars(hir_ty.hir_id), ), ), - hir::TyKind::TraitObject(bounds, lifetime, repr) => { + hir::TyKind::TraitObject(bounds, tagged_ptr) => { + let lifetime = tagged_ptr.pointer(); + let repr = tagged_ptr.tag(); + if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) { // Don't continue with type analysis if the `dyn` keyword is missing // It generates confusing errors, especially if the user meant to use another @@ -2420,7 +2426,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Ty::new_array_with_const_len(tcx, self.lower_ty(ty), length) } hir::TyKind::Typeof(e) => tcx.type_of(e.def_id).instantiate_identity(), - hir::TyKind::Infer => { + hir::TyKind::Infer(()) => { // Infer also appears as the type of arguments or return // values in an ExprKind::Closure, or as // the type of local variables. Both of these cases are @@ -2553,7 +2559,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub fn lower_arg_ty(&self, ty: &hir::Ty<'tcx>, expected_ty: Option<Ty<'tcx>>) -> Ty<'tcx> { match ty.kind { - hir::TyKind::Infer if let Some(expected_ty) = expected_ty => { + hir::TyKind::Infer(()) if let Some(expected_ty) = expected_ty => { self.record_ty(ty.hir_id, expected_ty, ty.span); expected_ty } diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index c0fb94d2cb2..f5abcd23440 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -1,6 +1,5 @@ -use rustc_hir as hir; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{ForeignItem, ForeignItemKind}; +use rustc_hir::intravisit::{self, Visitor, VisitorExt}; +use rustc_hir::{self as hir, AmbigArg, ForeignItem, ForeignItemKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::bug; @@ -68,11 +67,13 @@ fn diagnostic_hir_wf_check<'tcx>( } impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> { - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { let infcx = self.tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let tcx_ty = self.icx.lower_ty(ty); + // We don't handle infer vars but we wouldn't handle them anyway as we're creating a + // fresh `InferCtxt` in this function. + let tcx_ty = self.icx.lower_ty(ty.as_unambig_ty()); // This visitor can walk into binders, resulting in the `tcx_ty` to // potentially reference escaping bound variables. We simply erase // those here. @@ -149,7 +150,11 @@ fn diagnostic_hir_wf_check<'tcx>( .iter() .flat_map(|seg| seg.args().args) .filter_map(|arg| { - if let hir::GenericArg::Type(ty) = arg { Some(*ty) } else { None } + if let hir::GenericArg::Type(ty) = arg { + Some(ty.as_unambig_ty()) + } else { + None + } }) .chain([impl_.self_ty]) .collect(), @@ -196,7 +201,7 @@ fn diagnostic_hir_wf_check<'tcx>( } }; for ty in tys { - visitor.visit_ty(ty); + visitor.visit_ty_unambig(ty); } visitor.cause } diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 42034736ad6..fd5a7089b4c 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -152,7 +152,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( { let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter { span: tcx.def_span(param.def_id), - param_name: param.name, + param_name: tcx.item_ident(param.def_id), param_def_kind: tcx.def_descr(param.def_id), const_param_note: false, const_param_note2: false, @@ -223,7 +223,7 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained( let const_param_note = matches!(param.kind, ty::GenericParamDefKind::Const { .. }); let mut diag = tcx.dcx().create_err(UnconstrainedGenericParameter { span: tcx.def_span(param.def_id), - param_name: param.name, + param_name: tcx.item_ident(param.def_id), param_def_kind: tcx.def_descr(param.def_id), const_param_note, const_param_note2: const_param_note, diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index a42a168234f..bc7d4365eee 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -63,6 +63,7 @@ This API is completely unstable and subject to change. #![doc(rust_logo)] #![feature(assert_matches)] #![feature(coroutines)] +#![feature(debug_closure_helpers)] #![feature(if_let_guard)] #![feature(iter_from_coroutine)] #![feature(iter_intersperse)] diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 3ff6acd79fc..afc0f627f69 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -402,7 +402,8 @@ impl<'a> State<'a> { self.print_bounds("impl", bounds); } hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false), - hir::TyKind::TraitObject(bounds, lifetime, syntax) => { + hir::TyKind::TraitObject(bounds, lifetime) => { + let syntax = lifetime.tag(); match syntax { ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"), ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"), @@ -421,7 +422,7 @@ impl<'a> State<'a> { if !lifetime.is_elided() { self.nbsp(); self.word_space("+"); - self.print_lifetime(lifetime); + self.print_lifetime(lifetime.pointer()); } } hir::TyKind::Array(ty, ref length) => { @@ -441,7 +442,7 @@ impl<'a> State<'a> { self.word("/*ERROR*/"); self.pclose(); } - hir::TyKind::Infer | hir::TyKind::InferDelegation(..) => { + hir::TyKind::Infer(()) | hir::TyKind::InferDelegation(..) => { self.word("_"); } hir::TyKind::Pat(ty, pat) => { @@ -1799,8 +1800,8 @@ impl<'a> State<'a> { match generic_arg { GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt), GenericArg::Lifetime(_) => {} - GenericArg::Type(ty) => s.print_type(ty), - GenericArg::Const(ct) => s.print_const_arg(ct), + GenericArg::Type(ty) => s.print_type(ty.as_unambig_ty()), + GenericArg::Const(ct) => s.print_const_arg(ct.as_unambig_ct()), GenericArg::Infer(_inf) => s.word("_"), } }); @@ -2150,7 +2151,7 @@ impl<'a> State<'a> { s.ann.nested(s, Nested::BodyParamPat(body_id, i)); i += 1; - if let hir::TyKind::Infer = ty.kind { + if let hir::TyKind::Infer(()) = ty.kind { // Print nothing. } else { s.word(":"); diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 7b07e0ee939..5d00ecbe918 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -45,6 +45,7 @@ use rustc_session::lint; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{DUMMY_SP, Span, sym}; use rustc_trait_selection::infer::InferCtxtExt; +use rustc_type_ir::elaborate; use tracing::{debug, instrument}; use super::FnCtxt; @@ -923,7 +924,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { let src_auto: FxHashSet<_> = src_tty .auto_traits() .chain( - tcx.supertrait_def_ids(src_principal.def_id()) + elaborate::supertrait_def_ids(tcx, src_principal.def_id()) .filter(|def_id| tcx.trait_is_auto(*def_id)), ) .collect(); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 6945dbc3216..47abba1cc29 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -461,9 +461,17 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // to the target type), since that should be the least // confusing. let Some(InferOk { value: ty, mut obligations }) = found else { - let err = first_error.expect("coerce_borrowed_pointer had no error"); - debug!("coerce_borrowed_pointer: failed with err = {:?}", err); - return Err(err); + if let Some(first_error) = first_error { + debug!("coerce_borrowed_pointer: failed with err = {:?}", first_error); + return Err(first_error); + } else { + // This may happen in the new trait solver since autoderef requires + // the pointee to be structurally normalizable, or else it'll just bail. + // So when we have a type like `&<not well formed>`, then we get no + // autoderef steps (even though there should be at least one). That means + // we get no type mismatches, since the loop above just exits early. + return Err(TypeError::Mismatch); + } }; if ty == a && mt_a.mutbl.is_not() && autoderef.step_count() == 1 { @@ -1124,7 +1132,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.next_trait_solver() && let ty::Alias(..) = ty.kind() { - ocx.structurally_normalize(&cause, self.param_env, ty) + ocx.structurally_normalize_ty(&cause, self.param_env, ty) } else { Ok(ty) } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 367e7c6de95..bc076670585 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -851,32 +851,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind // Look for the type corresponding to the argument pattern we have in the argument list. - && let Some(ty_sugg) = fn_decl + && let Some(ty_ref) = fn_decl .inputs .iter() - .filter_map(|ty| { - if ty.span == *ty_span - && let hir::TyKind::Ref(lt, x) = ty.kind - { - // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty` - Some(( - x.ty.span.shrink_to_lo(), - format!( - "{}mut ", - if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " } - ), - )) - } else { - None - } + .filter_map(|ty| match ty.kind { + hir::TyKind::Ref(lt, mut_ty) if ty.span == *ty_span => Some((lt, mut_ty)), + _ => None, }) .next() { - let sugg = vec![ - ty_sugg, + let mut sugg = if ty_ref.1.mutbl.is_mut() { + // Leave `&'name mut Ty` and `&mut Ty` as they are (#136028). + vec![] + } else { + // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty` + vec![( + ty_ref.1.ty.span.shrink_to_lo(), + format!( + "{}mut ", + if ty_ref.0.ident.span.lo() == ty_ref.0.ident.span.hi() { "" } else { " " }, + ), + )] + }; + sugg.extend([ (pat.span.until(ident.span), String::new()), (lhs.span.shrink_to_lo(), "*".to_string()), - ]; + ]); // We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the // assignment from `ident = val;` to `*ident = val;`. err.multipart_suggestion_verbose( diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 01fed72d5a2..1c828591bcb 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2349,6 +2349,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.report_missing_fields( adt_ty, path_span, + expr.span, remaining_fields, variant, hir_fields, @@ -2386,6 +2387,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, adt_ty: Ty<'tcx>, span: Span, + full_span: Span, remaining_fields: UnordMap<Ident, (FieldIdx, &ty::FieldDef)>, variant: &'tcx ty::VariantDef, hir_fields: &'tcx [hir::ExprField<'tcx>], @@ -2425,6 +2427,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(span, format!("missing {remaining_fields_names}{truncated_fields_error}")); + if remaining_fields.items().all(|(_, (_, field))| field.value.is_some()) + && self.tcx.sess.is_nightly_build() + { + let msg = format!( + "all remaining fields have default values, {you_can} use those values with `..`", + you_can = if self.tcx.features().default_field_values() { + "you can" + } else { + "if you added `#![feature(default_field_values)]` to your crate you could" + }, + ); + if let Some(hir_field) = hir_fields.last() { + err.span_suggestion_verbose( + hir_field.span.shrink_to_hi(), + msg, + ", ..".to_string(), + Applicability::MachineApplicable, + ); + } else if hir_fields.is_empty() { + err.span_suggestion_verbose( + span.shrink_to_hi().with_hi(full_span.hi()), + msg, + " { .. }".to_string(), + Applicability::MachineApplicable, + ); + } + } + if let Some(hir_field) = hir_fields.last() { self.suggest_fru_from_range_and_emit(hir_field, variant, args, err); } else { @@ -3307,10 +3337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .map(|mut field_path| { field_path.pop(); - field_path - .iter() - .map(|id| format!("{}.", id.name.to_ident_string())) - .collect::<String>() + field_path.iter().map(|id| format!("{}.", id)).collect::<String>() }) .collect::<Vec<_>>(); candidate_fields.sort(); diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs index c128485d93e..1f3f03b9929 100644 --- a/compiler/rustc_hir_typeck/src/fallback.rs +++ b/compiler/rustc_hir_typeck/src/fallback.rs @@ -10,7 +10,7 @@ use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{InferKind, Visitor}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_session::lint; use rustc_span::def_id::LocalDefId; @@ -641,16 +641,21 @@ impl<'tcx> AnnotateUnitFallbackVisitor<'_, 'tcx> { impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> { type Result = ControlFlow<errors::SuggestAnnotation>; - fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) -> Self::Result { + fn visit_infer( + &mut self, + inf_id: HirId, + inf_span: Span, + _kind: InferKind<'tcx>, + ) -> Self::Result { // Try to replace `_` with `()`. - if let hir::TyKind::Infer = hir_ty.kind - && let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(hir_ty.hir_id) + if let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(inf_id) && let Some(vid) = self.fcx.root_vid(ty) && self.reachable_vids.contains(&vid) { - return ControlFlow::Break(errors::SuggestAnnotation::Unit(hir_ty.span)); + return ControlFlow::Break(errors::SuggestAnnotation::Unit(inf_span)); } - hir::intravisit::walk_ty(self, hir_ty) + + ControlFlow::Continue(()) } fn visit_qpath( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index be6d9570e35..8e647ad3c6a 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -6,9 +6,9 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::VisitorExt; use rustc_hir::lang_items::LangItem; -use rustc_hir::{self as hir, ExprKind, GenericArg, HirId, Node, QPath, intravisit}; +use rustc_hir::{self as hir, AmbigArg, ExprKind, GenericArg, HirId, Node, QPath, intravisit}; use rustc_hir_analysis::hir_ty_lowering::errors::GenericsArgsErrExtend; use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, @@ -470,7 +470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } impl<'tcx> intravisit::Visitor<'tcx> for CollectClauses<'_, 'tcx> { - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { if let Some(clauses) = self.fcx.trait_ascriptions.borrow().get(&ty.hir_id.local_id) { self.clauses.extend(clauses.iter().cloned()); @@ -480,7 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut clauses = CollectClauses { clauses: vec![], fcx: self }; - clauses.visit_ty(hir_ty); + clauses.visit_ty_unambig(hir_ty); self.tcx.mk_clauses(&clauses.clauses) } @@ -1272,14 +1272,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lower_lifetime(lt, RegionInferReason::Param(param)) .into(), (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { - self.fcx.lower_ty(ty).raw.into() - } - (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.fcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into() + // We handle the ambig portions of `Ty` in match arm below + self.fcx.lower_ty(ty.as_unambig_ty()).raw.into() } (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { - self.fcx.ty_infer(Some(param), inf.span).into() + self.fcx.lower_ty(&inf.to_ty()).raw.into() } + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self + .fcx + // Ambiguous parts of `ConstArg` are handled in the match arms below + .lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id)) + .into(), (&GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { self.fcx.ct_infer(Some(param), inf.span).into() } @@ -1433,7 +1436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // in a reentrant borrow, causing an ICE. let result = self .at(&self.misc(sp), self.param_env) - .structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut()); + .structurally_normalize_ty(ty, &mut **self.fulfillment_cx.borrow_mut()); match result { Ok(normalized_ty) => normalized_ty, Err(errors) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 46eed2db236..8e78fb3e219 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1210,7 +1210,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // - foo((), "current", 42u32, "next") // + foo((), 42u32) { - prev_extra_idx.map_or(true, |prev_extra_idx| { + prev_extra_idx.is_none_or(|prev_extra_idx| { prev_extra_idx + 1 == arg_idx.index() }) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 53e055fdeef..928010c03c2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -185,6 +185,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_ty: Ty<'tcx>, can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool, ) -> bool { + if lhs_expr.span.in_derive_expansion() || rhs_expr.span.in_derive_expansion() { + return false; + } let Some((_, lhs_output_ty, lhs_inputs)) = self.extract_callable_info(lhs_ty) else { return false; }; @@ -1143,7 +1146,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.may_coerce(found, ty) } hir::FnRetTy::DefaultReturn(_) if in_closure => { - self.ret_coercion.as_ref().map_or(false, |ret| { + self.ret_coercion.as_ref().is_some_and(|ret| { let ret_ty = ret.borrow().expected_ty(); self.may_coerce(found, ret_ty) }) @@ -1784,14 +1787,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let results = self.typeck_results.borrow(); // First, look for a `Clone::clone` call if segment.ident.name == sym::clone - && results.type_dependent_def_id(expr.hir_id).map_or( - false, - |did| { + && results.type_dependent_def_id(expr.hir_id).is_some_and(|did| { let assoc_item = self.tcx.associated_item(did); assoc_item.container == ty::AssocItemContainer::Trait && assoc_item.container_id(self.tcx) == clone_trait_did - }, - ) + }) // If that clone call hasn't already dereferenced the self type (i.e. don't give this // diagnostic in cases where we have `(&&T).clone()` and we expect `T`). && !results.expr_adjustments(callee_expr).iter().any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(..))) diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index f4929aae599..54e9e699353 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -122,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("generic size {size}") } } - Err(LayoutError::Unknown(bad)) => { + Err(LayoutError::TooGeneric(bad)) => { if *bad == ty { "this type does not have a fixed size".to_owned() } else { diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 9cd9ca040ce..07e013e4afa 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -251,7 +251,8 @@ fn typeck_with_inspect<'tcx>( fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Option<Ty<'tcx>> { let tcx = fcx.tcx; let def_id = fcx.body_id; - let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer, span, .. }) = node.ty() { + let expected_type = if let Some(&hir::Ty { kind: hir::TyKind::Infer(()), span, .. }) = node.ty() + { if let Some(item) = tcx.opt_associated_item(def_id.into()) && let ty::AssocKind::Const = item.kind && let ty::AssocItemContainer::Impl = item.container @@ -452,7 +453,7 @@ fn report_unexpected_variant_res( ); let fields = fields .iter() - .map(|field| format!("{}: _", field.name.to_ident_string())) + .map(|field| format!("{}: _", field.ident(tcx))) .collect::<Vec<_>>() .join(", "); let sugg = format!(" {{ {} }}", fields); diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index f549ced9dc3..880ee83c80a 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -425,14 +425,17 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { .lower_lifetime(lt, RegionInferReason::Param(param)) .into(), (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { - self.cfcx.lower_ty(ty).raw.into() - } - (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { - self.cfcx.lower_const_arg(ct, FeedConstTy::Param(param.def_id)).into() + // We handle the ambig portions of `Ty` in the match arms below + self.cfcx.lower_ty(ty.as_unambig_ty()).raw.into() } (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { - self.cfcx.ty_infer(Some(param), inf.span).into() + self.cfcx.lower_ty(&inf.to_ty()).raw.into() } + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self + .cfcx + // We handle the ambig portions of `ConstArg` in the match arms below + .lower_const_arg(ct.as_unambig_ct(), FeedConstTy::Param(param.def_id)) + .into(), (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { self.cfcx.ct_infer(Some(param), inf.span).into() } diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 116765325a9..b9d1f93bfb8 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1,6 +1,5 @@ use std::cell::{Cell, RefCell}; use std::cmp::max; -use std::iter; use std::ops::Deref; use rustc_data_structures::fx::FxHashSet; @@ -1009,11 +1008,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if self.tcx.is_trait_alias(trait_def_id) { // For trait aliases, recursively assume all explicitly named traits are relevant - for expansion in traits::expand_trait_aliases( - self.tcx, - iter::once((ty::Binder::dummy(trait_ref), self.span)), - ) { - let bound_trait_ref = expansion.trait_ref(); + for (bound_trait_pred, _) in + traits::expand_trait_aliases(self.tcx, [(trait_ref.upcast(self.tcx), self.span)]).0 + { + assert_eq!(bound_trait_pred.polarity(), ty::PredicatePolarity::Positive); + let bound_trait_ref = bound_trait_pred.map_bound(|pred| pred.trait_ref); for item in self.impl_or_trait_item(bound_trait_ref.def_id()) { if !self.has_applicable_self(&item) { self.record_static_candidate(CandidateSource::Trait( diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index b3d87ef4ad2..5d4e67d1a0e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2714,7 +2714,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .map(|field_path| { field_path .iter() - .map(|id| id.name.to_ident_string()) + .map(|id| id.to_string()) .collect::<Vec<String>>() .join(".") }) @@ -3761,18 +3761,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::TraitFn::Required([ident, ..]) => { ident.name == kw::SelfLower } - hir::TraitFn::Provided(body_id) => { - self.tcx.hir().body(*body_id).params.first().map_or( - false, - |param| { - matches!( - param.pat.kind, - hir::PatKind::Binding(_, _, ident, _) - if ident.name == kw::SelfLower - ) - }, - ) - } + hir::TraitFn::Provided(body_id) => self + .tcx + .hir() + .body(*body_id) + .params + .first() + .is_some_and(|param| { + matches!( + param.pat.kind, + hir::PatKind::Binding(_, _, ident, _) + if ident.name == kw::SelfLower + ) + }), _ => false, }; diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 683cacdff7d..1bf5b19d68d 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -6,9 +6,8 @@ use std::mem; use rustc_data_structures::unord::ExtendUnord; use rustc_errors::ErrorGuaranteed; -use rustc_hir as hir; -use rustc_hir::HirId; -use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::intravisit::{self, InferKind, Visitor}; +use rustc_hir::{self as hir, AmbigArg, HirId}; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; @@ -354,7 +353,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { self.write_ty_to_typeck_results(l.hir_id, var_ty); } - fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) { intravisit::walk_ty(self, hir_ty); // If there are type checking errors, Type privacy pass will stop, // so we may not get the type from hid_id, see #104513 @@ -364,12 +363,20 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { } } - fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { - intravisit::walk_inf(self, inf); - // Ignore cases where the inference is a const. - if let Some(ty) = self.fcx.node_ty_opt(inf.hir_id) { - let ty = self.resolve(ty, &inf.span); - self.write_ty_to_typeck_results(inf.hir_id, ty); + fn visit_infer( + &mut self, + inf_id: HirId, + inf_span: Span, + _kind: InferKind<'cx>, + ) -> Self::Result { + self.visit_id(inf_id); + + // We don't currently write inference results of const infer vars to + // the typeck results as there is not yet any part of the compiler that + // needs this information. + if let Some(ty) = self.fcx.node_ty_opt(inf_id) { + let ty = self.resolve(ty, &inf_span); + self.write_ty_to_typeck_results(inf_id, ty); } } } diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index 34f541a8cc6..a3d87f59567 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -258,7 +258,7 @@ impl<I: Idx> IntervalSet<I> { } current = Some(*end); } - current.map_or(true, |x| x < self.domain as u32) + current.is_none_or(|x| x < self.domain as u32) } } diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 5fc9b679c8a..69ab0e69e21 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -114,7 +114,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { ) } - fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>( + fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>>, U>( &self, value: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U, diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 7908733e734..061f7e6c22a 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -24,9 +24,9 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self), ret)] pub fn enter_forall_and_leak_universe<T>(&self, binder: ty::Binder<'tcx, T>) -> T where - T: TypeFoldable<TyCtxt<'tcx>> + Copy, + T: TypeFoldable<TyCtxt<'tcx>>, { - if let Some(inner) = binder.no_bound_vars() { + if let Some(inner) = binder.clone().no_bound_vars() { return inner; } @@ -71,7 +71,7 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self, f))] pub fn enter_forall<T, U>(&self, forall: ty::Binder<'tcx, T>, f: impl FnOnce(T) -> U) -> U where - T: TypeFoldable<TyCtxt<'tcx>> + Copy, + T: TypeFoldable<TyCtxt<'tcx>>, { // FIXME: currently we do nothing to prevent placeholders with the new universe being // used after exiting `f`. For example region subtyping can result in outlives constraints diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 1456255ea14..2113345eda3 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -1,6 +1,5 @@ use std::path::PathBuf; use std::result; -use std::sync::Arc; use rustc_ast::{LitKind, MetaItemKind, token}; use rustc_codegen_ssa::traits::CodegenBackend; @@ -309,6 +308,11 @@ pub struct Config { pub output_dir: Option<PathBuf>, pub output_file: Option<OutFileName>, pub ice_file: Option<PathBuf>, + /// Load files from sources other than the file system. + /// + /// Has no uses within this repository, but may be used in the future by + /// bjorn3 for "hooking rust-analyzer's VFS into rustc at some point for + /// running rustc without having to save". (See #102759.) pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>, /// The list of fluent resources, used for lints declared with /// [`Diagnostic`](rustc_errors::Diagnostic) and [`LintDiagnostic`](rustc_errors::LintDiagnostic). @@ -337,6 +341,11 @@ pub struct Config { pub override_queries: Option<fn(&Session, &mut Providers)>, /// This is a callback from the driver that is called to create a codegen backend. + /// + /// Has no uses within this repository, but is used by bjorn3 for "the + /// hotswapping branch of cg_clif" for "setting the codegen backend from a + /// custom driver where the custom codegen backend has arbitrary data." + /// (See #102759.) pub make_codegen_backend: Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>, @@ -346,8 +355,7 @@ pub struct Config { /// The inner atomic value is set to true when a feature marked as `internal` is /// enabled. Makes it so that "please report a bug" is hidden, as ICEs with /// internal features are wontfix, and they are usually the cause of the ICEs. - /// None signifies that this is not tracked. - pub using_internal_features: Arc<std::sync::atomic::AtomicBool>, + pub using_internal_features: &'static std::sync::atomic::AtomicBool, /// All commandline args used to invoke the compiler, with @file args fully expanded. /// This will only be used within debug info, e.g. in the pdb file on windows @@ -383,7 +391,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se crate::callbacks::setup_callbacks(); let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone()); - let target = config::build_target_config(&early_dcx, &config.opts, &sysroot); + let target = config::build_target_config(&early_dcx, &config.opts.target_triple, &sysroot); let file_loader = config.file_loader.unwrap_or_else(|| Box::new(RealFileLoader)); let path_mapping = config.opts.file_path_mapping(); let hash_kind = config.opts.unstable_opts.src_hash_algorithm(&target); @@ -533,7 +541,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se pub fn try_print_query_stack( dcx: DiagCtxtHandle<'_>, - num_frames: Option<usize>, + limit_frames: Option<usize>, file: Option<std::fs::File>, ) { eprintln!("query stack during panic:"); @@ -541,13 +549,13 @@ pub fn try_print_query_stack( // Be careful relying on global state here: this code is called from // a panic hook, which means that the global `DiagCtxt` may be in a weird // state if it was responsible for triggering the panic. - let i = ty::tls::with_context_opt(|icx| { + let all_frames = ty::tls::with_context_opt(|icx| { if let Some(icx) = icx { ty::print::with_no_queries!(print_query_stack( QueryCtxt::new(icx.tcx), icx.query, dcx, - num_frames, + limit_frames, file, )) } else { @@ -555,9 +563,14 @@ pub fn try_print_query_stack( } }); - if num_frames == None || num_frames >= Some(i) { - eprintln!("end of query stack"); + if let Some(limit_frames) = limit_frames + && all_frames > limit_frames + { + eprintln!( + "... and {} other queries... use `env RUST_BACKTRACE=1` to see the full query stack", + all_frames - limit_frames + ); } else { - eprintln!("we're just showing a limited slice of the query stack"); + eprintln!("end of query stack"); } } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 07c4b898721..74d02ac2227 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::num::NonZero; use std::path::{Path, PathBuf}; -use std::sync::Arc; +use std::sync::atomic::AtomicBool; use rustc_data_structures::profiling::TimePassesFormat; use rustc_errors::emitter::HumanReadableErrorType; @@ -42,7 +42,8 @@ where let matches = optgroups().parse(args).unwrap(); let sessopts = build_session_options(&mut early_dcx, &matches); let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone()); - let target = rustc_session::config::build_target_config(&early_dcx, &sessopts, &sysroot); + let target = + rustc_session::config::build_target_config(&early_dcx, &sessopts.target_triple, &sysroot); let hash_kind = sessopts.unstable_opts.src_hash_algorithm(&target); let checksum_hash_kind = sessopts.unstable_opts.checksum_hash_algorithm(); let sm_inputs = Some(SourceMapInputs { @@ -61,6 +62,8 @@ where temps_dir, }; + static USING_INTERNAL_FEATURES: AtomicBool = AtomicBool::new(false); + let sess = build_session( early_dcx, sessopts, @@ -73,7 +76,7 @@ where sysroot, "", None, - Arc::default(), + &USING_INTERNAL_FEATURES, Default::default(), ); let cfg = parse_cfg(sess.dcx(), matches.opt_strs("cfg")); diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 7522e21d0ef..55c6a122d35 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -69,15 +69,18 @@ lint_builtin_const_no_mangle = const items should never be `#[no_mangle]` lint_builtin_decl_unsafe_fn = declaration of an `unsafe` function lint_builtin_decl_unsafe_method = declaration of an `unsafe` method -lint_builtin_deprecated_attr_default_suggestion = remove this attribute lint_builtin_deprecated_attr_link = use of deprecated attribute `{$name}`: {$reason}. See {$link} .msg_suggestion = {$msg} .default_suggestion = remove this attribute -lint_builtin_deprecated_attr_used = use of deprecated attribute `{$name}`: no longer used lint_builtin_deref_nullptr = dereferencing a null pointer .label = this code causes undefined behavior when executed +lint_builtin_double_negations = use of a double negation + .note = the prefix `--` could be misinterpreted as a decrement operator which exists in other languages + .note_decrement = use `-= 1` if you meant to decrement the value + .add_parens_suggestion = add parentheses for clarity + lint_builtin_ellipsis_inclusive_range_patterns = `...` range patterns are deprecated .suggestion = use `..=` for an inclusive range @@ -209,7 +212,9 @@ lint_dangling_pointers_from_temporaries = a dangling pointer will be produced be .label_ptr = this pointer will immediately be invalid .label_temporary = this `{$ty}` is deallocated at the end of the statement, bind it to a variable to extend its lifetime .note = pointers do not have a lifetime; when calling `{$callee}` the `{$ty}` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned - .help = for more information, see <https://doc.rust-lang.org/reference/destructors.html> + .help_bind = you must make sure that the variable you bind the `{$ty}` to lives at least as long as the pointer returned by the call to `{$callee}` + .help_returned = in particular, if this pointer is returned from the current function, binding the `{$ty}` inside the function will not suffice + .help_visit = for more information, see <https://doc.rust-lang.org/reference/destructors.html> lint_default_hash_types = prefer `{$preferred}` over `{$used}`, it has better performance .note = a `use rustc_data_structures::fx::{$preferred}` may be necessary @@ -970,8 +975,7 @@ lint_unused_result = unused result of type `{$ty}` lint_use_let_underscore_ignore_suggestion = use `let _ = ...` to ignore the expression or result +lint_uses_power_alignment = repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + lint_variant_size_differences = enum variant is more than three times larger ({$largest} bytes) than the next largest - -lint_wasm_c_abi = - older versions of the `wasm-bindgen` crate will be incompatible with future versions of Rust; please update to `wasm-bindgen` v0.2.88 diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index fb3cf5afad0..c03de687a33 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -20,7 +20,7 @@ use rustc_abi::BackendRepr; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; -use rustc_ast_pretty::pprust::{self, expr_to_string}; +use rustc_ast_pretty::pprust::expr_to_string; use rustc_errors::{Applicability, LintDiagnostic}; use rustc_feature::{AttributeGate, BuiltinAttribute, GateIssue, Stability, deprecated_attributes}; use rustc_hir as hir; @@ -49,16 +49,16 @@ use rustc_trait_selection::traits::{self}; use crate::errors::BuiltinEllipsisInclusiveRangePatterns; use crate::lints::{ BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDeprecatedAttrLink, - BuiltinDeprecatedAttrLinkSuggestion, BuiltinDeprecatedAttrUsed, BuiltinDerefNullptr, - BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives, - BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures, - BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, - BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes, - BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, - BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, - BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, - BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, - BuiltinWhileTrue, InvalidAsmLabel, + BuiltinDeprecatedAttrLinkSuggestion, BuiltinDerefNullptr, BuiltinDoubleNegations, + BuiltinDoubleNegationsAddParens, BuiltinEllipsisInclusiveRangePatternsLint, + BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, + BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, + BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, + BuiltinMutablesTransmutes, BuiltinNoMangleGeneric, BuiltinNonShorthandFieldPatterns, + BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, BuiltinTypeAliasBounds, + BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, + BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, + BuiltinUnusedDocCommentSub, BuiltinWhileTrue, InvalidAsmLabel, }; use crate::nonstandard_style::{MethodLateContext, method_context}; use crate::{ @@ -90,19 +90,11 @@ declare_lint! { declare_lint_pass!(WhileTrue => [WHILE_TRUE]); -/// Traverse through any amount of parenthesis and return the first non-parens expression. -fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr { - while let ast::ExprKind::Paren(sub) = &expr.kind { - expr = sub; - } - expr -} - impl EarlyLintPass for WhileTrue { #[inline] fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) { if let ast::ExprKind::While(cond, _, label) = &e.kind - && let ast::ExprKind::Lit(token_lit) = pierce_parens(cond).kind + && let ast::ExprKind::Lit(token_lit) = cond.peel_parens().kind && let token::Lit { kind: token::Bool, symbol: kw::True, .. } = token_lit && !cond.span.from_expansion() { @@ -848,12 +840,6 @@ impl EarlyLintPass for DeprecatedAttr { return; } } - if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) { - cx.emit_span_lint(DEPRECATED, attr.span, BuiltinDeprecatedAttrUsed { - name: pprust::path_to_string(&attr.get_normal_item().path), - suggestion: attr.span, - }); - } } } @@ -1582,6 +1568,58 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { } } +declare_lint! { + /// The `double_negations` lint detects expressions of the form `--x`. + /// + /// ### Example + /// + /// ```rust + /// fn main() { + /// let x = 1; + /// let _b = --x; + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Negating something twice is usually the same as not negating it at all. + /// However, a double negation in Rust can easily be confused with the + /// prefix decrement operator that exists in many languages derived from C. + /// Use `-(-x)` if you really wanted to negate the value twice. + /// + /// To decrement a value, use `x -= 1` instead. + pub DOUBLE_NEGATIONS, + Warn, + "detects expressions of the form `--x`" +} + +declare_lint_pass!( + /// Lint for expressions of the form `--x` that can be confused with C's + /// prefix decrement operator. + DoubleNegations => [DOUBLE_NEGATIONS] +); + +impl EarlyLintPass for DoubleNegations { + #[inline] + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { + // only lint on the innermost `--` in a chain of `-` operators, + // even if there are 3 or more negations + if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind + && let ExprKind::Unary(UnOp::Neg, ref inner2) = inner.kind + && !matches!(inner2.kind, ExprKind::Unary(UnOp::Neg, _)) + { + cx.emit_span_lint(DOUBLE_NEGATIONS, expr.span, BuiltinDoubleNegations { + add_parens: BuiltinDoubleNegationsAddParens { + start_span: inner.span.shrink_to_lo(), + end_span: inner.span.shrink_to_hi(), + }, + }); + } + } +} + declare_lint_pass!( /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. @@ -1600,7 +1638,8 @@ declare_lint_pass!( UNSTABLE_FEATURES, UNREACHABLE_PUB, TYPE_ALIAS_BOUNDS, - TRIVIAL_BOUNDS + TRIVIAL_BOUNDS, + DOUBLE_NEGATIONS ] ); @@ -2657,7 +2696,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue { } declare_lint! { - /// The `deref_nullptr` lint detects when an null pointer is dereferenced, + /// The `deref_nullptr` lint detects when a null pointer is dereferenced, /// which causes [undefined behavior]. /// /// ### Example diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index 98b717a3070..fd6b3e90ada 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -141,7 +141,7 @@ fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) { expr.hir_id, method.ident.span, DanglingPointersFromTemporaries { - callee: method.ident.name, + callee: method.ident, ty, ptr_span: method.ident.span, temporary_span: receiver.span, diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 6d73715562b..92dbc76a7b5 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -430,7 +430,6 @@ pub(super) fn decorate_lint( BuiltinLintDiag::UnusedCrateDependency { extern_crate, local_crate } => { lints::UnusedCrateDependency { extern_crate, local_crate }.decorate_lint(diag) } - BuiltinLintDiag::WasmCAbi => lints::WasmCAbi.decorate_lint(diag), BuiltinLintDiag::IllFormedAttributeInput { suggestions } => { lints::IllFormedAttributeInput { num_suggestions: suggestions.len(), diff --git a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs index eebb131599a..da6dd8161ee 100644 --- a/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs +++ b/compiler/rustc_lint/src/early/diagnostics/check_cfg.rs @@ -10,19 +10,35 @@ use crate::lints; const MAX_CHECK_CFG_NAMES_OR_VALUES: usize = 35; +enum FilterWellKnownNames { + Yes, + No, +} + fn sort_and_truncate_possibilities( sess: &Session, mut possibilities: Vec<Symbol>, + filter_well_known_names: FilterWellKnownNames, ) -> (Vec<Symbol>, usize) { + let possibilities_len = possibilities.len(); + let n_possibilities = if sess.opts.unstable_opts.check_cfg_all_expected { possibilities.len() } else { + match filter_well_known_names { + FilterWellKnownNames::Yes => { + possibilities.retain(|cfg_name| { + !sess.psess.check_config.well_known_names.contains(cfg_name) + }); + } + FilterWellKnownNames::No => {} + }; std::cmp::min(possibilities.len(), MAX_CHECK_CFG_NAMES_OR_VALUES) }; possibilities.sort_by(|s1, s2| s1.as_str().cmp(s2.as_str())); - let and_more = possibilities.len().saturating_sub(n_possibilities); + let and_more = possibilities_len.saturating_sub(n_possibilities); possibilities.truncate(n_possibilities); (possibilities, and_more) } @@ -198,8 +214,10 @@ pub(super) fn unexpected_cfg_name( } else { vec![] }; + + let (possibilities, and_more) = + sort_and_truncate_possibilities(sess, possibilities, FilterWellKnownNames::Yes); let expected_names = if !possibilities.is_empty() { - let (possibilities, and_more) = sort_and_truncate_possibilities(sess, possibilities); let possibilities: Vec<_> = possibilities.into_iter().map(|s| Ident::new(s, name_span)).collect(); Some(lints::unexpected_cfg_name::ExpectedNames { @@ -269,8 +287,11 @@ pub(super) fn unexpected_cfg_value( // for names as the possibilities could be very long let code_sugg = if !possibilities.is_empty() { let expected_values = { - let (possibilities, and_more) = - sort_and_truncate_possibilities(sess, possibilities.clone()); + let (possibilities, and_more) = sort_and_truncate_possibilities( + sess, + possibilities.clone(), + FilterWellKnownNames::No, + ); lints::unexpected_cfg_value::ExpectedValues { name, have_none_possibility, diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 289e2c9b722..ef79f1301e5 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -57,7 +57,7 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) { let expect_id = canonicalize_id(expect_id); if !fulfilled_expectations.contains(&expect_id) - && tool_filter.map_or(true, |filter| expectation.lint_tool == Some(filter)) + && tool_filter.is_none_or(|filter| expectation.lint_tool == Some(filter)) { let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale }); let note = expectation.is_unfulfilled_lint_expectations; diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 259ea908fc6..b5a6159bd0a 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -9,7 +9,7 @@ use rustc_errors::{ use rustc_hir::{self as hir, HirIdSet}; use rustc_macros::LintDiagnostic; use rustc_middle::ty::TyCtxt; -use rustc_session::lint::{FutureIncompatibilityReason, Level}; +use rustc_session::lint::{FutureIncompatibilityReason, LintId}; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::Span; use rustc_span::edition::Edition; @@ -245,12 +245,12 @@ impl_lint_pass!( impl<'tcx> LateLintPass<'tcx> for IfLetRescope { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { - if expr.span.edition().at_least_rust_2024() { - return; - } - if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) { + if expr.span.edition().at_least_rust_2024() + || cx.tcx.lints_that_dont_need_to_run(()).contains(&LintId::of(IF_LET_RESCOPE)) + { return; } + if let hir::ExprKind::Loop(block, _label, hir::LoopSource::While, _span) = expr.kind && let Some(value) = block.expr && let hir::ExprKind::If(cond, _conseq, _alt) = value.kind @@ -290,7 +290,6 @@ struct IfLetRescopeLint { rewrite: Option<IfLetRescopeRewrite>, } -// #[derive(Subdiagnostic)] struct IfLetRescopeRewrite { match_heads: Vec<SingleArmMatchBegin>, consequent_heads: Vec<ConsequentRewrite>, diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index b31a4c74787..166ff60f7e1 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -5,8 +5,8 @@ use rustc_ast as ast; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::{ - BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, PatKind, - Path, PathSegment, QPath, Ty, TyKind, + AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, + PatKind, Path, PathSegment, QPath, Ty, TyKind, }; use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -159,7 +159,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { } } - fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx, AmbigArg>) { match &ty.kind { TyKind::Path(QPath::Resolved(_, path)) => { if lint_ty_kind_usage(cx, &path.res) { diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index a4d50c73104..c6d7b839e19 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -8,9 +8,8 @@ use std::cell::Cell; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::join; -use rustc_hir as hir; use rustc_hir::def_id::{LocalDefId, LocalModDefId}; -use rustc_hir::{HirId, intravisit as hir_visit}; +use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; @@ -214,15 +213,11 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas }) } - fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) { lint_callback!(self, check_ty, t); hir_visit::walk_ty(self, t); } - fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { - hir_visit::walk_inf(self, inf); - } - fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _: Span, n: HirId) { if !self.context.only_module { self.process_mod(m, n); diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 1465c2cff7b..83a168c3f44 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -181,6 +181,7 @@ early_lint_methods!( UnusedDocComment: UnusedDocComment, Expr2024: Expr2024, Precedence: Precedence, + DoubleNegations: DoubleNegations, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index ac995b59caf..09b0e1ed8bd 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -9,6 +9,7 @@ use rustc_errors::{ }; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::VisitorExt; use rustc_hir::{self as hir, MissingLifetimeKind}; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::inhabitedness::InhabitedPredicate; @@ -177,19 +178,6 @@ pub(crate) enum BuiltinDeprecatedAttrLinkSuggestion<'a> { } #[derive(LintDiagnostic)] -#[diag(lint_builtin_deprecated_attr_used)] -pub(crate) struct BuiltinDeprecatedAttrUsed { - pub name: String, - #[suggestion( - lint_builtin_deprecated_attr_default_suggestion, - style = "short", - code = "", - applicability = "machine-applicable" - )] - pub suggestion: Span, -} - -#[derive(LintDiagnostic)] #[diag(lint_builtin_unused_doc_comment)] pub(crate) struct BuiltinUnusedDocComment<'a> { pub kind: &'a str, @@ -293,7 +281,7 @@ impl<'a> LintDiagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { // avoid doing throwaway work in case the lint ends up getting suppressed. let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() }; if let Some(ty) = self.ty { - hir::intravisit::Visitor::visit_ty(&mut collector, ty); + collector.visit_ty_unambig(ty); } let affect_object_lifetime_defaults = self @@ -344,6 +332,24 @@ pub(crate) struct BuiltinTrivialBounds<'a> { } #[derive(LintDiagnostic)] +#[diag(lint_builtin_double_negations)] +#[note(lint_note)] +#[note(lint_note_decrement)] +pub(crate) struct BuiltinDoubleNegations { + #[subdiagnostic] + pub add_parens: BuiltinDoubleNegationsAddParens, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(lint_add_parens_suggestion, applicability = "maybe-incorrect")] +pub(crate) struct BuiltinDoubleNegationsAddParens { + #[suggestion_part(code = "(")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + +#[derive(LintDiagnostic)] pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { #[diag(lint_builtin_ellipsis_inclusive_range_patterns)] Parenthesise { @@ -1139,10 +1145,12 @@ pub(crate) struct IgnoredUnlessCrateSpecified<'a> { #[derive(LintDiagnostic)] #[diag(lint_dangling_pointers_from_temporaries)] #[note] -#[help] +#[help(lint_help_bind)] +#[help(lint_help_returned)] +#[help(lint_help_visit)] // FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts pub(crate) struct DanglingPointersFromTemporaries<'tcx> { - pub callee: Symbol, + pub callee: Ident, pub ty: Ty<'tcx>, #[label(lint_label_ptr)] pub ptr_span: Span, @@ -1343,7 +1351,7 @@ pub(crate) enum NonUpperCaseGlobalSub { #[diag(lint_noop_method_call)] #[note] pub(crate) struct NoopMethodCallDiag<'a> { - pub method: Symbol, + pub method: Ident, pub orig_ty: Ty<'a>, pub trait_: Symbol, #[suggestion(code = "", applicability = "machine-applicable")] @@ -1693,6 +1701,10 @@ pub(crate) struct OverflowingLiteral<'a> { } #[derive(LintDiagnostic)] +#[diag(lint_uses_power_alignment)] +pub(crate) struct UsesPowerAlignment; + +#[derive(LintDiagnostic)] #[diag(lint_unused_comparisons)] pub(crate) struct UnusedComparisons; @@ -2560,10 +2572,6 @@ pub(crate) struct UnusedCrateDependency { } #[derive(LintDiagnostic)] -#[diag(lint_wasm_c_abi)] -pub(crate) struct WasmCAbi; - -#[derive(LintDiagnostic)] #[diag(lint_ill_formed_attribute_input)] pub(crate) struct IllFormedAttributeInput { pub num_suggestions: usize, diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index a1cc3a85109..4e9d793be5b 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -1,6 +1,6 @@ use rustc_errors::MultiSpan; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::intravisit::{self, Visitor, VisitorExt}; use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind}; use rustc_middle::ty::TyCtxt; use rustc_session::{declare_lint, impl_lint_pass}; @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // 1. We collect all the `hir::Path` from the `Self` type and `Trait` ref // of the `impl` definition let mut collector = PathCollector { paths: Vec::new() }; - collector.visit_ty(&impl_.self_ty); + collector.visit_ty_unambig(&impl_.self_ty); if let Some(of_trait) = &impl_.of_trait { collector.visit_trait_ref(of_trait); } @@ -343,5 +343,5 @@ fn path_span_without_args(path: &Path<'_>) -> Span { /// Return a "error message-able" ident for the last segment of the `Path` fn path_name_to_string(path: &Path<'_>) -> String { - path.segments.last().unwrap().ident.name.to_ident_string() + path.segments.last().unwrap().ident.to_string() } diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index fa519281be5..790ef910b04 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -129,7 +129,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { _ => None, }; cx.emit_span_lint(NOOP_METHOD_CALL, span, NoopMethodCallDiag { - method: call.ident.name, + method: call.ident, orig_ty, trait_, label: span, diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 53a411e2b87..d347a8c1bc7 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -1,4 +1,4 @@ -use rustc_hir as hir; +use rustc_hir::{self as hir, AmbigArg}; use rustc_infer::infer::TyCtxtInferExt; use rustc_macros::{LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::fold::BottomUpFolder; @@ -67,7 +67,7 @@ declare_lint! { declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]); impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { - fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { let hir::TyKind::OpaqueDef(opaque) = &ty.kind else { return; }; diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index 3f264859d48..a1d66047058 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -1,6 +1,5 @@ -use rustc_hir as hir; use rustc_hir::def::Res; -use rustc_hir::{GenericArg, PathSegment, QPath, TyKind}; +use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind}; use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::sym; @@ -22,7 +21,7 @@ declare_tool_lint! { declare_lint_pass!(PassByValue => [PASS_BY_VALUE]); impl<'tcx> LateLintPass<'tcx> for PassByValue { - fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { match &ty.kind { TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) { @@ -46,7 +45,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind { match path.res { Res::Def(_, def_id) if cx.tcx.has_attr(def_id, sym::rustc_pass_by_value) => { - let name = cx.tcx.item_name(def_id).to_ident_string(); + let name = cx.tcx.item_ident(def_id); let path_segment = path.segments.last().unwrap(); return Some(format!("{}{}", name, gen_args(cx, path_segment))); } diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 3a323298bee..8cc8f911d3a 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -25,7 +25,7 @@ macro_rules! late_lint_methods { fn check_pat(a: &'tcx rustc_hir::Pat<'tcx>); fn check_expr(a: &'tcx rustc_hir::Expr<'tcx>); fn check_expr_post(a: &'tcx rustc_hir::Expr<'tcx>); - fn check_ty(a: &'tcx rustc_hir::Ty<'tcx>); + fn check_ty(a: &'tcx rustc_hir::Ty<'tcx, rustc_hir::AmbigArg>); fn check_generic_param(a: &'tcx rustc_hir::GenericParam<'tcx>); fn check_generics(a: &'tcx rustc_hir::Generics<'tcx>); fn check_poly_trait_ref(a: &'tcx rustc_hir::PolyTraitRef<'tcx>); diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index a9797c3b32a..e0937e43c9a 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -1,4 +1,4 @@ -use rustc_hir::{self as hir, LangItem}; +use rustc_hir::{self as hir, AmbigArg, LangItem}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; @@ -110,8 +110,10 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { } } - fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx>) { - let hir::TyKind::TraitObject(bounds, _lifetime, _syntax) = &ty.kind else { return }; + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { + let hir::TyKind::TraitObject(bounds, _lifetime_and_syntax_pointer) = &ty.kind else { + return; + }; for bound in &bounds[..] { let def_id = bound.trait_ref.trait_def_id(); if def_id.is_some_and(|def_id| cx.tcx.is_lang_item(def_id, LangItem::Drop)) { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 3bd27a224e7..0060f33888e 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1,14 +1,16 @@ use std::iter; use std::ops::ControlFlow; -use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, Variants, WrappingRange}; +use rustc_abi::{BackendRepr, ExternAbi, TagEncoding, VariantIdx, Variants, WrappingRange}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagMessage; -use rustc_hir::{Expr, ExprKind, LangItem}; +use rustc_hir::intravisit::VisitorExt; +use rustc_hir::{AmbigArg, Expr, ExprKind, LangItem}; use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton}; use rustc_middle::ty::{ - self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + self, Adt, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, + TypeVisitableExt, }; use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::def_id::LocalDefId; @@ -23,7 +25,7 @@ use crate::lints::{ AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion, UnpredictableFunctionPointerComparisons, - UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, + UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, UsesPowerAlignment, VariantSizeDifferencesDiag, }; use crate::{LateContext, LateLintPass, LintContext, fluent_generated as fluent}; @@ -727,7 +729,60 @@ declare_lint! { "proper use of libc types in foreign item definitions" } -declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS]); +declare_lint! { + /// The `uses_power_alignment` lint detects specific `repr(C)` + /// aggregates on AIX. + /// In its platform C ABI, AIX uses the "power" (as in PowerPC) alignment + /// rule (detailed in https://www.ibm.com/docs/en/xl-c-and-cpp-aix/16.1?topic=data-using-alignment-modes#alignment), + /// which can also be set for XLC by `#pragma align(power)` or + /// `-qalign=power`. Aggregates with a floating-point type as the + /// recursively first field (as in "at offset 0") modify the layout of + /// *subsequent* fields of the associated structs to use an alignment value + /// where the floating-point type is aligned on a 4-byte boundary. + /// + /// The power alignment rule for structs needed for C compatibility is + /// unimplementable within `repr(C)` in the compiler without building in + /// handling of references to packed fields and infectious nested layouts, + /// so a warning is produced in these situations. + /// + /// ### Example + /// + /// ```rust,ignore (fails on non-powerpc64-ibm-aix) + /// #[repr(C)] + /// pub struct Floats { + /// a: f64, + /// b: u8, + /// c: f64, + /// } + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + /// --> <source>:5:3 + /// | + /// 5 | c: f64, + /// | ^^^^^^ + /// | + /// = note: `#[warn(uses_power_alignment)]` on by default + /// ``` + /// + /// ### Explanation + /// + /// The power alignment rule specifies that the above struct has the + /// following alignment: + /// - offset_of!(Floats, a) == 0 + /// - offset_of!(Floats, b) == 8 + /// - offset_of!(Floats, c) == 12 + /// However, rust currently aligns `c` at offset_of!(Floats, c) == 16. + /// Thus, a warning should be produced for the above struct in this case. + USES_POWER_ALIGNMENT, + Warn, + "Structs do not follow the power alignment rule under repr(C)" +} + +declare_lint_pass!(ImproperCTypesDefinitions => [IMPROPER_CTYPES_DEFINITIONS, USES_POWER_ALIGNMENT]); #[derive(Clone, Copy)] pub(crate) enum CItemKind { @@ -1472,7 +1527,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } impl<'a, 'b, 'tcx> hir::intravisit::Visitor<'_> for FnPtrFinder<'a, 'b, 'tcx> { - fn visit_ty(&mut self, ty: &'_ hir::Ty<'_>) { + fn visit_ty(&mut self, ty: &'_ hir::Ty<'_, AmbigArg>) { debug!(?ty); if let hir::TyKind::BareFn(hir::BareFnTy { abi, .. }) = ty.kind && !self.visitor.is_internal_abi(*abi) @@ -1500,7 +1555,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { let mut visitor = FnPtrFinder { visitor: self, spans: Vec::new(), tys: Vec::new() }; ty.visit_with(&mut visitor); - hir::intravisit::Visitor::visit_ty(&mut visitor, hir_ty); + visitor.visit_ty_unambig(hir_ty); iter::zip(visitor.tys.drain(..), visitor.spans.drain(..)).collect() } @@ -1539,6 +1594,71 @@ impl ImproperCTypesDefinitions { vis.check_type_for_ffi_and_report_errors(span, fn_ptr_ty, true, false); } } + + fn check_arg_for_power_alignment<'tcx>( + &mut self, + cx: &LateContext<'tcx>, + ty: Ty<'tcx>, + ) -> bool { + // Structs (under repr(C)) follow the power alignment rule if: + // - the first field of the struct is a floating-point type that + // is greater than 4-bytes, or + // - the first field of the struct is an aggregate whose + // recursively first field is a floating-point type greater than + // 4 bytes. + if cx.tcx.sess.target.os != "aix" { + return false; + } + if ty.is_floating_point() && ty.primitive_size(cx.tcx).bytes() > 4 { + return true; + } else if let Adt(adt_def, _) = ty.kind() + && adt_def.is_struct() + { + let struct_variant = adt_def.variant(VariantIdx::ZERO); + // Within a nested struct, all fields are examined to correctly + // report if any fields after the nested struct within the + // original struct are misaligned. + for struct_field in &struct_variant.fields { + let field_ty = cx.tcx.type_of(struct_field.did).instantiate_identity(); + if self.check_arg_for_power_alignment(cx, field_ty) { + return true; + } + } + } + return false; + } + + fn check_struct_for_power_alignment<'tcx>( + &mut self, + cx: &LateContext<'tcx>, + item: &'tcx hir::Item<'tcx>, + ) { + let adt_def = cx.tcx.adt_def(item.owner_id.to_def_id()); + if adt_def.repr().c() + && !adt_def.repr().packed() + && cx.tcx.sess.target.os == "aix" + && !adt_def.all_fields().next().is_none() + { + let struct_variant_data = item.expect_struct().0; + for (index, ..) in struct_variant_data.fields().iter().enumerate() { + // Struct fields (after the first field) are checked for the + // power alignment rule, as fields after the first are likely + // to be the fields that are misaligned. + if index != 0 { + let first_field_def = struct_variant_data.fields()[index]; + let def_id = first_field_def.def_id; + let ty = cx.tcx.type_of(def_id).instantiate_identity(); + if self.check_arg_for_power_alignment(cx, ty) { + cx.emit_span_lint( + USES_POWER_ALIGNMENT, + first_field_def.span, + UsesPowerAlignment, + ); + } + } + } + } + } } /// `ImproperCTypesDefinitions` checks items outside of foreign items (e.g. stuff that isn't in @@ -1562,8 +1682,13 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDefinitions { } // See `check_fn`.. hir::ItemKind::Fn { .. } => {} + // Structs are checked based on if they follow the power alignment + // rule (under repr(C)). + hir::ItemKind::Struct(..) => { + self.check_struct_for_power_alignment(cx, item); + } // See `check_field_def`.. - hir::ItemKind::Union(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) => {} + hir::ItemKind::Union(..) | hir::ItemKind::Enum(..) => {} // Doesn't define something that can contain a external type to be checked. hir::ItemKind::Impl(..) | hir::ItemKind::TraitAlias(..) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 9fc527a6a3a..5b4a1f174cb 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -60,6 +60,7 @@ declare_lint_pass! { LARGE_ASSIGNMENTS, LATE_BOUND_LIFETIME_ARGUMENTS, LEGACY_DERIVE_HELPERS, + LINKER_MESSAGES, LONG_RUNNING_CONST_EVAL, LOSSY_PROVENANCE_CASTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, @@ -143,7 +144,6 @@ declare_lint_pass! { UNUSED_VARIABLES, USELESS_DEPRECATED, WARNINGS, - WASM_C_ABI, // tidy-alphabetical-end ] } @@ -4086,6 +4086,47 @@ declare_lint! { } declare_lint! { + /// The `linker_messages` lint forwards warnings from the linker. + /// + /// ### Example + /// + /// ```rust,ignore (needs CLI args, platform-specific) + /// #[warn(linker_messages)] + /// extern "C" { + /// fn foo(); + /// } + /// fn main () { unsafe { foo(); } } + /// ``` + /// + /// On Linux, using `gcc -Wl,--warn-unresolved-symbols` as a linker, this will produce + /// + /// ```text + /// warning: linker stderr: rust-lld: undefined symbol: foo + /// >>> referenced by rust_out.69edbd30df4ae57d-cgu.0 + /// >>> rust_out.rust_out.69edbd30df4ae57d-cgu.0.rcgu.o:(rust_out::main::h3a90094b06757803) + /// | + /// note: the lint level is defined here + /// --> warn.rs:1:9 + /// | + /// 1 | #![warn(linker_messages)] + /// | ^^^^^^^^^^^^^^^ + /// warning: 1 warning emitted + /// ``` + /// + /// ### Explanation + /// + /// Linkers emit platform-specific and program-specific warnings that cannot be predicted in + /// advance by the Rust compiler. Such messages are ignored by default for now. While linker + /// warnings could be very useful they have been ignored for many years by essentially all + /// users, so we need to do a bit more work than just surfacing their text to produce a clear + /// and actionable warning of similar quality to our other diagnostics. See this tracking + /// issue for more details: <https://github.com/rust-lang/rust/issues/136096>. + pub LINKER_MESSAGES, + Allow, + "warnings emitted at runtime by the target-specific linker program" +} + +declare_lint! { /// The `named_arguments_used_positionally` lint detects cases where named arguments are only /// used positionally in format strings. This usage is valid but potentially very confusing. /// @@ -4648,44 +4689,6 @@ declare_lint! { } declare_lint! { - /// The `wasm_c_abi` lint detects crate dependencies that are incompatible - /// with future versions of Rust that will emit spec-compliant C ABI. - /// - /// ### Example - /// - /// ```rust,ignore (needs extern crate) - /// #![deny(wasm_c_abi)] - /// ``` - /// - /// This will produce: - /// - /// ```text - /// error: the following packages contain code that will be rejected by a future version of Rust: wasm-bindgen v0.2.87 - /// | - /// note: the lint level is defined here - /// --> src/lib.rs:1:9 - /// | - /// 1 | #![deny(wasm_c_abi)] - /// | ^^^^^^^^^^ - /// ``` - /// - /// ### Explanation - /// - /// Rust has historically emitted non-spec-compliant C ABI. This has caused - /// incompatibilities between other compilers and Wasm targets. In a future - /// version of Rust this will be fixed and therefore dependencies relying - /// on the non-spec-compliant C ABI will stop functioning. - pub WASM_C_ABI, - Deny, - "detects dependencies that are incompatible with the Wasm C ABI", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, - reference: "issue #71871 <https://github.com/rust-lang/rust/issues/71871>", - }; - crate_level_only -} - -declare_lint! { /// The `uncovered_param_in_projection` lint detects a violation of one of Rust's orphan rules for /// foreign trait implementations that concerns the use of type parameters inside trait associated /// type paths ("projections") whose output may not be a local type that is mistakenly considered diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 7786d3eb59a..3f1e98556ef 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -161,7 +161,19 @@ impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectation /// Setting for how to handle a lint. /// /// See: <https://doc.rust-lang.org/rustc/lints/levels.html> -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash, HashStable_Generic)] +#[derive( + Clone, + Copy, + PartialEq, + PartialOrd, + Eq, + Ord, + Debug, + Hash, + Encodable, + Decodable, + HashStable_Generic +)] pub enum Level { /// The `allow` level will not issue any message. Allow, @@ -783,7 +795,6 @@ pub enum BuiltinLintDiag { extern_crate: Symbol, local_crate: Symbol, }, - WasmCAbi, IllFormedAttributeInput { suggestions: Vec<String>, }, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index dd72ea2497f..35186778671 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -2,6 +2,7 @@ #include "llvm-c/Analysis.h" #include "llvm-c/Core.h" +#include "llvm-c/DebugInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" @@ -676,120 +677,73 @@ template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) { #define DIArray DINodeArray #define unwrapDI unwrapDIPtr -// These values **must** match debuginfo::DIFlags! They also *happen* -// to match LLVM, but that isn't required as we do giant sets of -// matching below. The value shouldn't be directly passed to LLVM. -enum class LLVMRustDIFlags : uint32_t { - FlagZero = 0, - FlagPrivate = 1, - FlagProtected = 2, - FlagPublic = 3, - FlagFwdDecl = (1 << 2), - FlagAppleBlock = (1 << 3), - FlagBlockByrefStruct = (1 << 4), - FlagVirtual = (1 << 5), - FlagArtificial = (1 << 6), - FlagExplicit = (1 << 7), - FlagPrototyped = (1 << 8), - FlagObjcClassComplete = (1 << 9), - FlagObjectPointer = (1 << 10), - FlagVector = (1 << 11), - FlagStaticMember = (1 << 12), - FlagLValueReference = (1 << 13), - FlagRValueReference = (1 << 14), - FlagExternalTypeRef = (1 << 15), - FlagIntroducedVirtual = (1 << 18), - FlagBitField = (1 << 19), - FlagNoReturn = (1 << 20), - // Do not add values that are not supported by the minimum LLVM - // version we support! see llvm/include/llvm/IR/DebugInfoFlags.def -}; - -inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) & - static_cast<uint32_t>(B)); -} - -inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) | - static_cast<uint32_t>(B)); -} - -inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) { - return A = A | B; -} - -inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; } - -inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) { - return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3); -} - -static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) { - DINode::DIFlags Result = DINode::DIFlags::FlagZero; - - switch (visibility(Flags)) { - case LLVMRustDIFlags::FlagPrivate: - Result |= DINode::DIFlags::FlagPrivate; - break; - case LLVMRustDIFlags::FlagProtected: - Result |= DINode::DIFlags::FlagProtected; - break; - case LLVMRustDIFlags::FlagPublic: - Result |= DINode::DIFlags::FlagPublic; - break; - default: - // The rest are handled below - break; - } - - if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) { - Result |= DINode::DIFlags::FlagFwdDecl; - } - if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) { - Result |= DINode::DIFlags::FlagAppleBlock; - } - if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) { - Result |= DINode::DIFlags::FlagVirtual; - } - if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) { - Result |= DINode::DIFlags::FlagArtificial; - } - if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) { - Result |= DINode::DIFlags::FlagExplicit; - } - if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) { - Result |= DINode::DIFlags::FlagPrototyped; - } - if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) { - Result |= DINode::DIFlags::FlagObjcClassComplete; - } - if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) { - Result |= DINode::DIFlags::FlagObjectPointer; - } - if (isSet(Flags & LLVMRustDIFlags::FlagVector)) { - Result |= DINode::DIFlags::FlagVector; - } - if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) { - Result |= DINode::DIFlags::FlagStaticMember; - } - if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) { - Result |= DINode::DIFlags::FlagLValueReference; - } - if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) { - Result |= DINode::DIFlags::FlagRValueReference; - } - if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) { - Result |= DINode::DIFlags::FlagIntroducedVirtual; - } - if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) { - Result |= DINode::DIFlags::FlagBitField; - } - if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) { - Result |= DINode::DIFlags::FlagNoReturn; - } - - return Result; +// FIXME(Zalathar): This is a temporary typedef to avoid churning dozens of +// bindings that are going to be deleted and replaced with their LLVM-C +// equivalents, as part of #134009. After that happens, the remaining bindings +// can be adjusted to use `LLVMDIFlags` instead of relying on this typedef. +typedef LLVMDIFlags LLVMRustDIFlags; + +// Statically assert that `LLVMDIFlags` (C) and `DIFlags` (C++) have the same +// layout, at least for the flags we know about. This isn't guaranteed, but is +// likely to remain true, and as long as it is true it makes conversions easy. +#define ASSERT_DIFLAG_VALUE(FLAG, VALUE) \ + static_assert((LLVMDI##FLAG == (VALUE)) && (DINode::DIFlags::FLAG == (VALUE))) +ASSERT_DIFLAG_VALUE(FlagZero, 0); +ASSERT_DIFLAG_VALUE(FlagPrivate, 1); +ASSERT_DIFLAG_VALUE(FlagProtected, 2); +ASSERT_DIFLAG_VALUE(FlagPublic, 3); +// Bit (1 << 1) is part of the private/protected/public values above. +ASSERT_DIFLAG_VALUE(FlagFwdDecl, 1 << 2); +ASSERT_DIFLAG_VALUE(FlagAppleBlock, 1 << 3); +ASSERT_DIFLAG_VALUE(FlagReservedBit4, 1 << 4); +ASSERT_DIFLAG_VALUE(FlagVirtual, 1 << 5); +ASSERT_DIFLAG_VALUE(FlagArtificial, 1 << 6); +ASSERT_DIFLAG_VALUE(FlagExplicit, 1 << 7); +ASSERT_DIFLAG_VALUE(FlagPrototyped, 1 << 8); +ASSERT_DIFLAG_VALUE(FlagObjcClassComplete, 1 << 9); +ASSERT_DIFLAG_VALUE(FlagObjectPointer, 1 << 10); +ASSERT_DIFLAG_VALUE(FlagVector, 1 << 11); +ASSERT_DIFLAG_VALUE(FlagStaticMember, 1 << 12); +ASSERT_DIFLAG_VALUE(FlagLValueReference, 1 << 13); +ASSERT_DIFLAG_VALUE(FlagRValueReference, 1 << 14); +// Bit (1 << 15) has been recycled, but the C API value hasn't been renamed. +static_assert((LLVMDIFlagReserved == (1 << 15)) && + (DINode::DIFlags::FlagExportSymbols == (1 << 15))); +ASSERT_DIFLAG_VALUE(FlagSingleInheritance, 1 << 16); +ASSERT_DIFLAG_VALUE(FlagMultipleInheritance, 2 << 16); +ASSERT_DIFLAG_VALUE(FlagVirtualInheritance, 3 << 16); +// Bit (1 << 17) is part of the inheritance values above. +ASSERT_DIFLAG_VALUE(FlagIntroducedVirtual, 1 << 18); +ASSERT_DIFLAG_VALUE(FlagBitField, 1 << 19); +ASSERT_DIFLAG_VALUE(FlagNoReturn, 1 << 20); +// Bit (1 << 21) is unused, but was `LLVMDIFlagMainSubprogram`. +ASSERT_DIFLAG_VALUE(FlagTypePassByValue, 1 << 22); +ASSERT_DIFLAG_VALUE(FlagTypePassByReference, 1 << 23); +ASSERT_DIFLAG_VALUE(FlagEnumClass, 1 << 24); +ASSERT_DIFLAG_VALUE(FlagThunk, 1 << 25); +ASSERT_DIFLAG_VALUE(FlagNonTrivial, 1 << 26); +ASSERT_DIFLAG_VALUE(FlagBigEndian, 1 << 27); +ASSERT_DIFLAG_VALUE(FlagLittleEndian, 1 << 28); +ASSERT_DIFLAG_VALUE(FlagIndirectVirtualBase, (1 << 2) | (1 << 5)); +#undef ASSERT_DIFLAG_VALUE + +// There are two potential ways to convert `LLVMDIFlags` to `DIFlags`: +// - Check and copy every individual bit/subvalue from input to output. +// - Statically assert that both have the same layout, and cast. +// As long as the static assertions succeed, a cast is easier and faster. +// In the (hopefully) unlikely event that the assertions do fail someday, and +// LLVM doesn't expose its own conversion function, we'll have to switch over +// to copying each bit/subvalue. +static DINode::DIFlags fromRust(LLVMDIFlags Flags) { + // Check that all set bits are covered by the static assertions above. + const unsigned UNKNOWN_BITS = (1 << 31) | (1 << 30) | (1 << 29) | (1 << 21); + if (Flags & UNKNOWN_BITS) { + report_fatal_error("bad LLVMDIFlags"); + } + + // As long as the static assertions are satisfied and no unknown bits are + // present, we can convert from `LLVMDIFlags` to `DIFlags` with a cast. + return static_cast<DINode::DIFlags>(Flags); } // These values **must** match debuginfo::DISPFlags! They also *happen* diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 6d7d88fa8d7..d2b5ae53185 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -290,6 +290,9 @@ metadata_unsupported_abi = metadata_unsupported_abi_i686 = ABI not supported by `#[link(kind = "raw-dylib")]` on i686 +metadata_wasm_c_abi = + older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88 + metadata_wasm_import_form = wasm import module must be of the form `wasm_import_module = "string"` diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 6512176cc4a..a6cd0ecafd0 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -417,7 +417,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Any descendants of `std` should be private. These crates are usually not marked // private in metadata, so we ignore that field. if extern_private.is_none() - && dep_root.map_or(false, |d| STDLIB_STABLE_CRATES.contains(&d.name)) + && let Some(dep) = dep_root + && STDLIB_STABLE_CRATES.contains(&dep.name) { return true; } @@ -1075,12 +1076,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> { // Make a point span rather than covering the whole file let span = krate.spans.inner_span.shrink_to_lo(); - self.sess.psess.buffer_lint( - lint::builtin::WASM_C_ABI, - span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::WasmCAbi, - ); + self.sess.dcx().emit_err(errors::WasmCAbi { span }); } } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index b6c5619ec18..cefc6498f68 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -732,3 +732,10 @@ pub struct ImportNameTypeRaw { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(metadata_wasm_c_abi)] +pub(crate) struct WasmCAbi { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index 5dd85978f00..8dc529b4d7a 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -100,6 +100,8 @@ middle_strict_coherence_needs_negative_coherence = to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled .label = due to this attribute +middle_too_generic = `{$ty}` does not have a fixed size + middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}` middle_unknown_layout = @@ -107,4 +109,5 @@ middle_unknown_layout = middle_values_too_big = values of the type `{$ty}` are too big for the target architecture + middle_written_to_path = the full type name has been written to '{$path}' diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index 6300d856393..b0187a1848c 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -129,6 +129,9 @@ pub enum LayoutError<'tcx> { #[diag(middle_unknown_layout)] Unknown { ty: Ty<'tcx> }, + #[diag(middle_too_generic)] + TooGeneric { ty: Ty<'tcx> }, + #[diag(middle_values_too_big)] Overflow { ty: Ty<'tcx> }, diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 5d78bed5cf8..926760b84aa 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -12,7 +12,7 @@ use rustc_hir::*; use rustc_hir_pretty as pprust_hir; use rustc_middle::hir::nested_filter; use rustc_span::def_id::StableCrateId; -use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; +use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spans}; use crate::hir::ModuleItems; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; @@ -1117,6 +1117,9 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { // the fly in the resolver, storing only their accumulated hash in `ResolverGlobalCtxt`, // and combining it with other hashes here. resolutions.visibilities_for_hashing.hash_stable(&mut hcx, &mut stable_hasher); + with_metavar_spans(|mspans| { + mspans.freeze_and_get_read_spans().hash_stable(&mut hcx, &mut stable_hasher); + }); stable_hasher.finish() }); diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 04a06ba7464..bbe23d8abe8 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -40,6 +40,7 @@ #![feature(const_type_name)] #![feature(core_intrinsics)] #![feature(coroutines)] +#![feature(debug_closure_helpers)] #![feature(decl_macro)] #![feature(discriminant_kind)] #![feature(extern_types)] diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 620d9f1c357..cae980cde61 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_errors::{Diag, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; -use rustc_macros::HashStable; +use rustc_macros::{Decodable, Encodable, HashStable}; use rustc_session::Session; use rustc_session::lint::builtin::{self, FORBIDDEN_LINT_GROUPS}; use rustc_session::lint::{FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId}; @@ -15,7 +15,7 @@ use tracing::instrument; use crate::ty::TyCtxt; /// How a lint level was set. -#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Encodable, Decodable, HashStable, Debug)] pub enum LintLevelSource { /// Lint is at the default level as declared in rustc. Default, @@ -173,7 +173,7 @@ impl TyCtxt<'_> { /// This struct represents a lint expectation and holds all required information /// to emit the `unfulfilled_lint_expectations` lint if it is unfulfilled after /// the `LateLintPass` has completed. -#[derive(Clone, Debug, HashStable)] +#[derive(Clone, Debug, Encodable, Decodable, HashStable)] pub struct LintExpectation { /// The reason for this expectation that can optionally be added as part of /// the attribute. It will be displayed as part of the lint message. diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index e05f42af6fd..cc980f6e62a 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -147,7 +147,7 @@ impl CodegenFnAttrs { CodegenFnAttrs { flags: CodegenFnAttrFlags::empty(), inline: InlineAttr::None, - optimize: OptimizeAttr::None, + optimize: OptimizeAttr::Default, export_name: None, link_name: None, link_ordinal: None, diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 60e1ff1d049..66d97fda433 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -460,17 +460,6 @@ impl<'tcx> Const<'tcx> { Self::Val(val, ty) } - pub fn from_ty_const(c: ty::Const<'tcx>, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Self { - match c.kind() { - ty::ConstKind::Value(ty, valtree) => { - // Make sure that if `c` is normalized, then the return value is normalized. - let const_val = tcx.valtree_to_const_val((ty, valtree)); - Self::Val(const_val, ty) - } - _ => Self::Ty(ty, c), - } - } - /// Return true if any evaluation of this constant always returns the same value, /// taking into account even pointer identity tests. pub fn is_deterministic(&self) -> bool { diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 65f51ae9d39..46534697e1d 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Formatter}; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_span::Span; rustc_index::newtype_index! { @@ -72,7 +72,7 @@ impl ConditionId { /// Enum that can hold a constant zero value, the ID of an physical coverage /// counter, or the ID of a coverage-counter expression. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub enum CovTerm { Zero, Counter(CounterId), @@ -89,7 +89,7 @@ impl Debug for CovTerm { } } -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum CoverageKind { /// Marks a span that might otherwise not be represented in MIR, so that /// coverage instrumentation can associate it with its enclosing block/BCB. @@ -151,7 +151,7 @@ impl Debug for CoverageKind { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] -#[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable)] pub enum Op { Subtract, Add, @@ -168,7 +168,7 @@ impl Op { } #[derive(Clone, Debug, PartialEq, Eq)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct Expression { pub lhs: CovTerm, pub op: Op, @@ -176,7 +176,7 @@ pub struct Expression { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub enum MappingKind { /// Associates a normal region of code with a counter/expression/zero. Code(CovTerm), @@ -208,7 +208,7 @@ impl MappingKind { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct Mapping { pub kind: MappingKind, pub span: Span, @@ -218,7 +218,7 @@ pub struct Mapping { /// to be used in conjunction with the individual coverage statements injected /// into the function's basic blocks. #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct FunctionCoverageInfo { pub function_source_hash: u64, pub body_span: Span, @@ -238,7 +238,7 @@ pub struct FunctionCoverageInfo { /// ("Hi" indicates that this is "high-level" information collected at the /// THIR/MIR boundary, before the MIR-based coverage instrumentation pass.) #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct CoverageInfoHi { /// 1 more than the highest-numbered [`CoverageKind::BlockMarker`] that was /// injected into the MIR body. This makes it possible to allocate per-ID @@ -252,7 +252,7 @@ pub struct CoverageInfoHi { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct BranchSpan { pub span: Span, pub true_marker: BlockMarkerId, @@ -260,7 +260,7 @@ pub struct BranchSpan { } #[derive(Copy, Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct ConditionInfo { pub condition_id: ConditionId, pub true_next_id: Option<ConditionId>, @@ -268,7 +268,7 @@ pub struct ConditionInfo { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct MCDCBranchSpan { pub span: Span, pub condition_info: ConditionInfo, @@ -277,14 +277,14 @@ pub struct MCDCBranchSpan { } #[derive(Copy, Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct DecisionInfo { pub bitmap_idx: u32, pub num_conditions: u16, } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct MCDCDecisionSpan { pub span: Span, pub end_markers: Vec<BlockMarkerId>, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index d6f8fed755f..1b07846e0cf 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -222,7 +222,7 @@ impl AllocError { } /// The information that makes up a memory access: offset and size. -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq)] pub struct AllocRange { pub start: Size, pub size: Size, diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs index 3a83b184d83..78196b05361 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs @@ -97,7 +97,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { debug_assert!(prov.len() <= 1); if let Some(entry) = prov.first() { // If it overlaps with this byte, it is on this byte. - debug_assert!(self.bytes.as_ref().map_or(true, |b| b.get(&offset).is_none())); + debug_assert!(self.bytes.as_ref().is_none_or(|b| !b.contains_key(&offset))); Some(entry.1) } else { // Look up per-byte provenance. @@ -301,7 +301,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> { // For really small copies, make sure we don't start before `src` does. let entry_start = cmp::max(entry.0, src.start); for offset in entry_start..src.end() { - if bytes.last().map_or(true, |bytes_entry| bytes_entry.0 < offset) { + if bytes.last().is_none_or(|bytes_entry| bytes_entry.0 < offset) { // The last entry, if it exists, has a lower offset than us. bytes.push((offset, entry.1)); } else { diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index bbb8bdce4a0..0f3fca434ee 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -358,6 +358,8 @@ pub struct Body<'tcx> { /// /// Only present if coverage is enabled and this function is eligible. /// Boxed to limit space overhead in non-coverage builds. + #[type_foldable(identity)] + #[type_visitable(ignore)] pub coverage_info_hi: Option<Box<coverage::CoverageInfoHi>>, /// Per-function coverage information added by the `InstrumentCoverage` @@ -366,6 +368,8 @@ pub struct Body<'tcx> { /// /// If `-Cinstrument-coverage` is not active, or if an individual function /// is not eligible for coverage, then this should always be `None`. + #[type_foldable(identity)] + #[type_visitable(ignore)] pub function_coverage_info: Option<Box<coverage::FunctionCoverageInfo>>, } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 111c3b6956a..3eccf56d8c4 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher, ToStableHashKey}; use rustc_data_structures::unord::UnordMap; use rustc_hir::ItemId; -use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE}; use rustc_index::Idx; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; use rustc_query_system::ich::StableHashingContext; @@ -247,6 +247,12 @@ impl ToStableHashKey<StableHashingContext<'_>> for MonoItem<'_> { } } +#[derive(Debug, HashStable, Copy, Clone)] +pub struct MonoItemPartitions<'tcx> { + pub codegen_units: &'tcx [CodegenUnit<'tcx>], + pub all_mono_items: &'tcx DefIdSet, +} + #[derive(Debug, HashStable)] pub struct CodegenUnit<'tcx> { /// A name for this CGU. Incremental compilation requires that diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index ea35323ccc7..3b4fba97e60 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1,8 +1,7 @@ use std::collections::BTreeSet; use std::fmt::{Display, Write as _}; -use std::fs; -use std::io::{self, Write as _}; use std::path::{Path, PathBuf}; +use std::{fs, io}; use rustc_abi::Size; use rustc_ast::InlineAsmTemplatePiece; @@ -149,37 +148,59 @@ pub fn dump_enabled(tcx: TyCtxt<'_>, pass_name: &str, def_id: DefId) -> bool { // `def_path_str()` would otherwise trigger `type_of`, and this can // run while we are already attempting to evaluate `type_of`. +/// Most use-cases of dumping MIR should use the [dump_mir] entrypoint instead, which will also +/// check if dumping MIR is enabled, and if this body matches the filters passed on the CLI. +/// +/// That being said, if the above requirements have been validated already, this function is where +/// most of the MIR dumping occurs, if one needs to export it to a file they have created with +/// [create_dump_file], rather than to a new file created as part of [dump_mir], or to stdout/stderr +/// for debugging purposes. +pub fn dump_mir_to_writer<'tcx, F>( + tcx: TyCtxt<'tcx>, + pass_name: &str, + disambiguator: &dyn Display, + body: &Body<'tcx>, + w: &mut dyn io::Write, + mut extra_data: F, + options: PrettyPrintMirOptions, +) -> io::Result<()> +where + F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>, +{ + // see notes on #41697 above + let def_path = + ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())); + // ignore-tidy-odd-backticks the literal below is fine + write!(w, "// MIR for `{def_path}")?; + match body.source.promoted { + None => write!(w, "`")?, + Some(promoted) => write!(w, "::{promoted:?}`")?, + } + writeln!(w, " {disambiguator} {pass_name}")?; + if let Some(ref layout) = body.coroutine_layout_raw() { + writeln!(w, "/* coroutine_layout = {layout:#?} */")?; + } + writeln!(w)?; + extra_data(PassWhere::BeforeCFG, w)?; + write_user_type_annotations(tcx, body, w)?; + write_mir_fn(tcx, body, &mut extra_data, w, options)?; + extra_data(PassWhere::AfterCFG, w) +} + fn dump_matched_mir_node<'tcx, F>( tcx: TyCtxt<'tcx>, pass_num: bool, pass_name: &str, disambiguator: &dyn Display, body: &Body<'tcx>, - mut extra_data: F, + extra_data: F, options: PrettyPrintMirOptions, ) where F: FnMut(PassWhere, &mut dyn io::Write) -> io::Result<()>, { let _: io::Result<()> = try { let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body)?; - // see notes on #41697 above - let def_path = - ty::print::with_forced_impl_filename_line!(tcx.def_path_str(body.source.def_id())); - // ignore-tidy-odd-backticks the literal below is fine - write!(file, "// MIR for `{def_path}")?; - match body.source.promoted { - None => write!(file, "`")?, - Some(promoted) => write!(file, "::{promoted:?}`")?, - } - writeln!(file, " {disambiguator} {pass_name}")?; - if let Some(ref layout) = body.coroutine_layout_raw() { - writeln!(file, "/* coroutine_layout = {layout:#?} */")?; - } - writeln!(file)?; - extra_data(PassWhere::BeforeCFG, &mut file)?; - write_user_type_annotations(tcx, body, &mut file)?; - write_mir_fn(tcx, body, &mut extra_data, &mut file, options)?; - extra_data(PassWhere::AfterCFG, &mut file)?; + dump_mir_to_writer(tcx, pass_name, disambiguator, body, &mut file, extra_data, options)?; }; if tcx.sess.opts.unstable_opts.dump_mir_graphviz { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index db5da941f1e..50494355e3e 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -1,6 +1,5 @@ //! Values computed by queries that use MIR. -use std::cell::Cell; use std::fmt::{self, Debug}; use rustc_abi::{FieldIdx, VariantIdx}; @@ -62,55 +61,26 @@ pub struct CoroutineLayout<'tcx> { impl Debug for CoroutineLayout<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - /// Prints an iterator of (key, value) tuples as a map. - struct MapPrinter<'a, K, V>(Cell<Option<Box<dyn Iterator<Item = (K, V)> + 'a>>>); - impl<'a, K, V> MapPrinter<'a, K, V> { - fn new(iter: impl Iterator<Item = (K, V)> + 'a) -> Self { - Self(Cell::new(Some(Box::new(iter)))) - } - } - impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt.debug_map().entries(self.0.take().unwrap()).finish() - } - } - - /// Prints the coroutine variant name. - struct GenVariantPrinter(VariantIdx); - impl From<VariantIdx> for GenVariantPrinter { - fn from(idx: VariantIdx) -> Self { - GenVariantPrinter(idx) - } - } - impl Debug for GenVariantPrinter { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let variant_name = ty::CoroutineArgs::variant_name(self.0); - if fmt.alternate() { - write!(fmt, "{:9}({:?})", variant_name, self.0) - } else { - write!(fmt, "{variant_name}") - } - } - } - - /// Forces its contents to print in regular mode instead of alternate mode. - struct OneLinePrinter<T>(T); - impl<T: Debug> Debug for OneLinePrinter<T> { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "{:?}", self.0) - } - } - fmt.debug_struct("CoroutineLayout") - .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated())) - .field( - "variant_fields", - &MapPrinter::new( - self.variant_fields - .iter_enumerated() - .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))), - ), - ) + .field_with("field_tys", |fmt| { + fmt.debug_map().entries(self.field_tys.iter_enumerated()).finish() + }) + .field_with("variant_fields", |fmt| { + let mut map = fmt.debug_map(); + for (idx, fields) in self.variant_fields.iter_enumerated() { + map.key_with(|fmt| { + let variant_name = ty::CoroutineArgs::variant_name(idx); + if fmt.alternate() { + write!(fmt, "{variant_name:9}({idx:?})") + } else { + write!(fmt, "{variant_name}") + } + }); + // Force variant fields to print in regular mode instead of alternate mode. + map.value_with(|fmt| write!(fmt, "{fields:?}")); + } + map.finish() + }) .field("storage_conflicts", &self.storage_conflicts) .finish() } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 0c17a2e0fe5..29ae2e1bd6b 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -417,7 +417,14 @@ pub enum StatementKind<'tcx> { /// /// Interpreters and codegen backends that don't support coverage instrumentation /// can usually treat this as a no-op. - Coverage(CoverageKind), + Coverage( + // Coverage statements are unlikely to ever contain type information in + // the foreseeable future, so excluding them from TypeFoldable/TypeVisitable + // avoids some unhelpful derive boilerplate. + #[type_foldable(identity)] + #[type_visitable(ignore)] + CoverageKind, + ), /// Denotes a call to an intrinsic that does not require an unwind path and always returns. /// This avoids adding a new block and a terminator for simple intrinsics. diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 473b817aed0..c04a8251fbc 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -581,9 +581,11 @@ impl<'tcx> TerminatorKind<'tcx> { pub enum TerminatorEdges<'mir, 'tcx> { /// For terminators that have no successor, like `return`. None, - /// For terminators that a single successor, like `goto`, and `assert` without cleanup block. + /// For terminators that have a single successor, like `goto`, and `assert` without a cleanup + /// block. Single(BasicBlock), - /// For terminators that two successors, `assert` with cleanup block and `falseEdge`. + /// For terminators that have two successors, like `assert` with a cleanup block, and + /// `falseEdge`. Double(BasicBlock, BasicBlock), /// Special action for `Yield`, `Call` and `InlineAsm` terminators. AssignOnReturn { diff --git a/compiler/rustc_middle/src/query/arena_cached.rs b/compiler/rustc_middle/src/query/arena_cached.rs new file mode 100644 index 00000000000..ec6e466ff68 --- /dev/null +++ b/compiler/rustc_middle/src/query/arena_cached.rs @@ -0,0 +1,47 @@ +/// Helper trait that allows `arena_cache` queries to return `Option<&T>` +/// instead of `&Option<T>`, and avoid allocating `None` in the arena. +/// +/// An arena-cached query must be declared to return a type that implements +/// this trait, i.e. either `&'tcx T` or `Option<&'tcx T>`. This trait then +/// determines the types returned by the provider and stored in the arena, +/// and provides a function to bridge between the three types. +pub trait ArenaCached<'tcx>: Sized { + /// Type that is returned by the query provider. + type Provided; + /// Type that is stored in the arena. + type Allocated: 'tcx; + + /// Takes a provided value, and allocates it in the arena (if appropriate) + /// with the help of the given `arena_alloc` closure. + fn alloc_in_arena( + arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, + value: Self::Provided, + ) -> Self; +} + +impl<'tcx, T> ArenaCached<'tcx> for &'tcx T { + type Provided = T; + type Allocated = T; + + fn alloc_in_arena( + arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, + value: Self::Provided, + ) -> Self { + // Just allocate in the arena normally. + arena_alloc(value) + } +} + +impl<'tcx, T> ArenaCached<'tcx> for Option<&'tcx T> { + type Provided = Option<T>; + /// The provide value is `Option<T>`, but we only store `T` in the arena. + type Allocated = T; + + fn alloc_in_arena( + arena_alloc: impl Fn(Self::Allocated) -> &'tcx Self::Allocated, + value: Self::Provided, + ) -> Self { + // Don't store None in the arena, and wrap the allocated reference in Some. + value.map(arena_alloc) + } +} diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 1676afb4b6e..14f871cbbdc 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -349,6 +349,7 @@ tcx_lifetime! { rustc_middle::mir::interpret::GlobalId, rustc_middle::mir::interpret::LitToConstInput, rustc_middle::mir::interpret::EvalStaticInitializerRawResult, + rustc_middle::mir::mono::MonoItemPartitions, rustc_middle::traits::query::MethodAutoderefStepsResult, rustc_middle::traits::query::type_op::AscribeUserType, rustc_middle::traits::query::type_op::Eq, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 65e93c3a1cc..e27a9823639 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -7,7 +7,6 @@ #![allow(unused_parens)] use std::mem; -use std::ops::Deref; use std::path::PathBuf; use std::sync::Arc; @@ -24,7 +23,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::{DefKind, DocLinkResMap}; use rustc_hir::def_id::{ - CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, + CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap, LocalDefIdSet, LocalModDefId, }; use rustc_hir::lang_items::{LangItem, LanguageItems}; use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate}; @@ -59,7 +58,7 @@ use crate::mir::interpret::{ EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId, LitToConstInput, }; -use crate::mir::mono::{CodegenUnit, CollectionMode, MonoItem}; +use crate::mir::mono::{CodegenUnit, CollectionMode, MonoItem, MonoItemPartitions}; use crate::query::erase::{Erase, erase, restore}; use crate::query::plumbing::{ CyclePlaceholder, DynamicQuery, query_ensure, query_ensure_error_guaranteed, query_get_at, @@ -85,6 +84,7 @@ use crate::ty::{ }; use crate::{dep_graph, mir, thir}; +mod arena_cached; pub mod erase; mod keys; pub use keys::{AsLocalKey, Key, LocalCrate}; @@ -586,7 +586,7 @@ rustc_queries! { separate_provide_extern } - query mir_coroutine_witnesses(key: DefId) -> &'tcx Option<mir::CoroutineLayout<'tcx>> { + query mir_coroutine_witnesses(key: DefId) -> Option<&'tcx mir::CoroutineLayout<'tcx>> { arena_cache desc { |tcx| "coroutine witness types for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } @@ -618,7 +618,9 @@ rustc_queries! { /// Summarizes coverage IDs inserted by the `InstrumentCoverage` MIR pass /// (for compiler option `-Cinstrument-coverage`), after MIR optimizations /// have had a chance to potentially remove some of them. - query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> &'tcx mir::coverage::CoverageIdsInfo { + /// + /// Returns `None` for functions that were not instrumented. + query coverage_ids_info(key: ty::InstanceKind<'tcx>) -> Option<&'tcx mir::coverage::CoverageIdsInfo> { desc { |tcx| "retrieving coverage IDs info from MIR for `{}`", tcx.def_path_str(key.def_id()) } arena_cache } @@ -2164,7 +2166,7 @@ rustc_queries! { separate_provide_extern } - query collect_and_partition_mono_items(_: ()) -> (&'tcx DefIdSet, &'tcx [CodegenUnit<'tcx>]) { + query collect_and_partition_mono_items(_: ()) -> MonoItemPartitions<'tcx> { eval_always desc { "collect_and_partition_mono_items" } } @@ -2415,7 +2417,7 @@ rustc_queries! { /// because the `ty::Ty`-based wfcheck is always run. query diagnostic_hir_wf_check( key: (ty::Predicate<'tcx>, WellFormedLoc) - ) -> &'tcx Option<ObligationCause<'tcx>> { + ) -> Option<&'tcx ObligationCause<'tcx>> { arena_cache eval_always no_hash diff --git a/compiler/rustc_middle/src/query/plumbing.rs b/compiler/rustc_middle/src/query/plumbing.rs index 2cb6f6d8c6e..1c157f33a81 100644 --- a/compiler/rustc_middle/src/query/plumbing.rs +++ b/compiler/rustc_middle/src/query/plumbing.rs @@ -289,10 +289,10 @@ macro_rules! define_callbacks { /// This type alias specifies the type returned from query providers and the type /// used for decoding. For regular queries this is the declared returned type `V`, - /// but `arena_cache` will use `<V as Deref>::Target` instead. + /// but `arena_cache` will use `<V as ArenaCached>::Provided` instead. pub type ProvidedValue<'tcx> = query_if_arena!( [$($modifiers)*] - (<$V as Deref>::Target) + (<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Provided) ($V) ); @@ -307,10 +307,18 @@ macro_rules! define_callbacks { ) -> Erase<Value<'tcx>> { erase(query_if_arena!([$($modifiers)*] { - if mem::needs_drop::<ProvidedValue<'tcx>>() { - &*_tcx.query_system.arenas.$name.alloc(value) + use $crate::query::arena_cached::ArenaCached; + + if mem::needs_drop::<<$V as ArenaCached<'tcx>>::Allocated>() { + <$V as ArenaCached>::alloc_in_arena( + |v| _tcx.query_system.arenas.$name.alloc(v), + value, + ) } else { - &*_tcx.arena.dropless.alloc(value) + <$V as ArenaCached>::alloc_in_arena( + |v| _tcx.arena.dropless.alloc(v), + value, + ) } } (value) @@ -354,7 +362,7 @@ macro_rules! define_callbacks { pub struct QueryArenas<'tcx> { $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*] - (TypedArena<<$V as Deref>::Target>) + (TypedArena<<$V as $crate::query::arena_cached::ArenaCached<'tcx>>::Allocated>) () ),)* } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index db2bb8a7248..55d78e083e0 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -345,9 +345,6 @@ pub enum ObligationCauseCode<'tcx> { /// `main` has wrong type MainFunctionType, - /// `start` has wrong type - StartFunctionType, - /// language function has wrong type LangFunctionType(Symbol), diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 33d39b137b6..c4d5367e2f0 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -433,7 +433,7 @@ pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>( // A parent matches a child if they share the same prefix of projections. // The child may have more, if it is capturing sub-fields out of // something that is captured by-move in the parent closure. - while child_captures.peek().map_or(false, |(_, child_capture)| { + while child_captures.peek().is_some_and(|(_, child_capture)| { child_prefix_matches_parent_projections(parent_capture, child_capture) }) { let (child_field_idx, child_capture) = child_captures.next().unwrap(); diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 7035e641f39..1f0710e2415 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -33,7 +33,7 @@ use rustc_errors::{ use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::Definitions; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::VisitorExt; use rustc_hir::lang_items::LangItem; use rustc_hir::{self as hir, Attribute, HirId, Node, TraitCandidate}; use rustc_index::IndexVec; @@ -52,7 +52,9 @@ use rustc_type_ir::TyKind::*; use rustc_type_ir::fold::TypeFoldable; use rustc_type_ir::lang_items::TraitSolverLangItem; pub use rustc_type_ir::lift::Lift; -use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph}; +use rustc_type_ir::{ + CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, elaborate, search_graph, +}; use tracing::{debug, instrument}; use crate::arena::Arena; @@ -1347,6 +1349,33 @@ pub struct GlobalCtxt<'tcx> { /// Stores memory for globals (statics/consts). pub(crate) alloc_map: Lock<interpret::AllocMap<'tcx>>, + + current_gcx: CurrentGcx, +} + +impl<'tcx> GlobalCtxt<'tcx> { + /// Installs `self` in a `TyCtxt` and `ImplicitCtxt` for the duration of + /// `f`. + pub fn enter<F, R>(&'tcx self, f: F) -> R + where + F: FnOnce(TyCtxt<'tcx>) -> R, + { + let icx = tls::ImplicitCtxt::new(self); + + // Reset `current_gcx` to `None` when we exit. + let _on_drop = defer(move || { + *self.current_gcx.value.write() = None; + }); + + // Set this `GlobalCtxt` as the current one. + { + let mut guard = self.current_gcx.value.write(); + assert!(guard.is_none(), "no `GlobalCtxt` is currently set"); + *guard = Some(self as *const _ as *const ()); + } + + tls::enter_context(&icx, || f(icx.tcx)) + } } /// This is used to get a reference to a `GlobalCtxt` if one is available. @@ -1537,23 +1566,11 @@ impl<'tcx> TyCtxt<'tcx> { canonical_param_env_cache: Default::default(), data_layout, alloc_map: Lock::new(interpret::AllocMap::new()), + current_gcx, }); - let icx = tls::ImplicitCtxt::new(&gcx); - - // Reset `current_gcx` to `None` when we exit. - let _on_drop = defer(|| { - *current_gcx.value.write() = None; - }); - - // Set this `GlobalCtxt` as the current one. - { - let mut guard = current_gcx.value.write(); - assert!(guard.is_none(), "no `GlobalCtxt` is currently set"); - *guard = Some(&gcx as *const _ as *const ()); - } - - tls::enter_context(&icx, || f(icx.tcx)) + // This is a separate function to work around a crash with parallel rustc (#135870) + gcx.enter(f) } /// Obtain all lang items of this crate and all dependencies (recursively) @@ -2026,7 +2043,7 @@ impl<'tcx> TyCtxt<'tcx> { }; let mut v = TraitObjectVisitor(vec![], self.hir()); - v.visit_ty(hir_output); + v.visit_ty_unambig(hir_output); v.0 } @@ -2048,7 +2065,7 @@ impl<'tcx> TyCtxt<'tcx> { && let Some(alias_ty) = self.hir_node_by_def_id(local_id).alias_ty() // it is type alias && let Some(alias_generics) = self.hir_node_by_def_id(local_id).generics() { - v.visit_ty(alias_ty); + v.visit_ty_unambig(alias_ty); if !v.0.is_empty() { return Some(( v.0, @@ -2323,51 +2340,41 @@ macro_rules! sty_debug_print { } impl<'tcx> TyCtxt<'tcx> { - pub fn debug_stats(self) -> impl std::fmt::Debug + 'tcx { - struct DebugStats<'tcx>(TyCtxt<'tcx>); - - impl<'tcx> std::fmt::Debug for DebugStats<'tcx> { - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - sty_debug_print!( - fmt, - self.0, - Adt, - Array, - Slice, - RawPtr, - Ref, - FnDef, - FnPtr, - UnsafeBinder, - Placeholder, - Coroutine, - CoroutineWitness, - Dynamic, - Closure, - CoroutineClosure, - Tuple, - Bound, - Param, - Infer, - Alias, - Pat, - Foreign - )?; - - writeln!(fmt, "GenericArgs interner: #{}", self.0.interners.args.len())?; - writeln!(fmt, "Region interner: #{}", self.0.interners.region.len())?; - writeln!( - fmt, - "Const Allocation interner: #{}", - self.0.interners.const_allocation.len() - )?; - writeln!(fmt, "Layout interner: #{}", self.0.interners.layout.len())?; - - Ok(()) - } - } - - DebugStats(self) + pub fn debug_stats(self) -> impl fmt::Debug + 'tcx { + fmt::from_fn(move |fmt| { + sty_debug_print!( + fmt, + self, + Adt, + Array, + Slice, + RawPtr, + Ref, + FnDef, + FnPtr, + UnsafeBinder, + Placeholder, + Coroutine, + CoroutineWitness, + Dynamic, + Closure, + CoroutineClosure, + Tuple, + Bound, + Param, + Infer, + Alias, + Pat, + Foreign + )?; + + writeln!(fmt, "GenericArgs interner: #{}", self.interners.args.len())?; + writeln!(fmt, "Region interner: #{}", self.interners.region.len())?; + writeln!(fmt, "Const Allocation interner: #{}", self.interners.const_allocation.len())?; + writeln!(fmt, "Layout interner: #{}", self.interners.layout.len())?; + + Ok(()) + }) } } @@ -2558,7 +2565,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name` /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`. pub fn trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool { - self.supertrait_def_ids(trait_def_id).any(|trait_did| { + elaborate::supertrait_def_ids(self, trait_def_id).any(|trait_did| { self.associated_items(trait_did) .filter_by_name_unhygienic(assoc_name.name) .any(|item| self.hygienic_eq(assoc_name, item.ident(self), trait_did)) @@ -2579,14 +2586,6 @@ impl<'tcx> TyCtxt<'tcx> { }) } - /// Computes the def-ids of the transitive supertraits of `trait_def_id`. This (intentionally) - /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used - /// to identify which traits may define a given associated type to help avoid cycle errors, - /// and to make size estimates for vtable layout computation. - pub fn supertrait_def_ids(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx { - rustc_type_ir::elaborate::supertrait_def_ids(self, trait_def_id) - } - /// Given a closure signature, returns an equivalent fn signature. Detuples /// and so forth -- so e.g., if we have a sig with `Fn<(u32, i32)>` then /// you would get a `fn(u32, i32)`. diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 77745599afb..b4b66a8133a 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -9,7 +9,7 @@ use rustc_errors::{ }; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem, PredicateOrigin, WherePredicateKind}; +use rustc_hir::{self as hir, AmbigArg, LangItem, PredicateOrigin, WherePredicateKind}; use rustc_span::{BytePos, Span}; use rustc_type_ir::TyKind::*; @@ -336,7 +336,7 @@ pub fn suggest_constraining_type_params<'a>( .collect(); constraints - .retain(|(_, def_id, _)| def_id.map_or(true, |def| !bound_trait_defs.contains(&def))); + .retain(|(_, def_id, _)| def_id.is_none_or(|def| !bound_trait_defs.contains(&def))); if constraints.is_empty() { continue; @@ -570,18 +570,18 @@ pub fn suggest_constraining_type_params<'a>( pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>, pub crate::hir::map::Map<'tcx>); impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> { - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { match ty.kind { - hir::TyKind::TraitObject( - _, - hir::Lifetime { + hir::TyKind::TraitObject(_, tagged_ptr) + if let hir::Lifetime { res: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static, .. - }, - _, - ) - | hir::TyKind::OpaqueDef(..) => self.0.push(ty), + } = tagged_ptr.pointer() => + { + self.0.push(ty.as_unambig_ty()) + } + hir::TyKind::OpaqueDef(..) => self.0.push(ty.as_unambig_ty()), _ => {} } hir::intravisit::walk_ty(self, ty); diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index e4ded2c30f5..b7a648aae3f 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -328,7 +328,7 @@ impl<'tcx> InstanceKind<'tcx> { // We include enums without destructors to allow, say, optimizing // drops of `Option::None` before LTO. We also respect the intent of // `#[inline]` on `Drop::drop` implementations. - return ty.ty_adt_def().map_or(true, |adt_def| { + return ty.ty_adt_def().is_none_or(|adt_def| { match *self { ty::InstanceKind::DropGlue(..) => adt_def.destructor(tcx).map(|dtor| dtor.did), ty::InstanceKind::AsyncDropGlueCtorShim(..) => { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 1e67cdfc32a..0d41a1d7dbf 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -231,6 +231,7 @@ impl fmt::Display for ValidityRequirement { pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), SizeOverflow(Ty<'tcx>), + TooGeneric(Ty<'tcx>), NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), ReferencesError(ErrorGuaranteed), Cycle(ErrorGuaranteed), @@ -244,6 +245,7 @@ impl<'tcx> LayoutError<'tcx> { match self { Unknown(_) => middle_unknown_layout, SizeOverflow(_) => middle_values_too_big, + TooGeneric(_) => middle_too_generic, NormalizationFailure(_, _) => middle_cannot_be_normalized, Cycle(_) => middle_cycle, ReferencesError(_) => middle_layout_references_error, @@ -257,6 +259,7 @@ impl<'tcx> LayoutError<'tcx> { match self { Unknown(ty) => E::Unknown { ty }, SizeOverflow(ty) => E::Overflow { ty }, + TooGeneric(ty) => E::TooGeneric { ty }, NormalizationFailure(ty, e) => { E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() } } @@ -272,6 +275,9 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"), + LayoutError::TooGeneric(ty) => { + write!(f, "`{ty}` does not have a fixed size") + } LayoutError::SizeOverflow(ty) => { write!(f, "values of the type `{ty}` are too big for the target architecture") } @@ -350,10 +356,11 @@ impl<'tcx> SizeSkeleton<'tcx> { return Err(tcx.arena.alloc(LayoutError::Unknown(ty))); } } - Err(err @ LayoutError::Unknown(_)) => err, + Err(err @ LayoutError::TooGeneric(_)) => err, // We can't extract SizeSkeleton info from other layout errors Err( e @ LayoutError::Cycle(_) + | e @ LayoutError::Unknown(_) | e @ LayoutError::SizeOverflow(_) | e @ LayoutError::NormalizationFailure(..) | e @ LayoutError::ReferencesError(_), @@ -413,10 +420,9 @@ impl<'tcx> SizeSkeleton<'tcx> { // Alignment is unchanged by arrays. return Ok(SizeSkeleton::Known(Size::from_bytes(size), a)); } - Err(tcx.arena.alloc(LayoutError::Unknown(ty))) + Err(err) } - SizeSkeleton::Pointer { .. } => Err(err), - SizeSkeleton::Generic(_) => Err(tcx.arena.alloc(LayoutError::Unknown(ty))), + SizeSkeleton::Pointer { .. } | SizeSkeleton::Generic(_) => Err(err), } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ca70ae794c5..8cd632790a8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1596,6 +1596,15 @@ impl<'tcx> TyCtxt<'tcx> { Some(Ident::new(def, span)) } + /// Look up the name and span of a definition. + /// + /// See [`item_name`][Self::item_name] for more information. + pub fn item_ident(self, def_id: DefId) -> Ident { + self.opt_item_ident(def_id).unwrap_or_else(|| { + bug!("item_ident: no name for {:?}", self.def_path(def_id)); + }) + } + pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> { if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = self.def_kind(def_id) { Some(self.associated_item(def_id)) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index bf37ae05c82..a9a47c87a38 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1894,11 +1894,11 @@ impl<'tcx> Ty<'tcx> { ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false, - ty::Tuple(tys) => tys.last().map_or(true, |ty| ty.is_trivially_sized(tcx)), + ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.is_trivially_sized(tcx)), ty::Adt(def, args) => def .sized_constraint(tcx) - .map_or(true, |ty| ty.instantiate(tcx, args).is_trivially_sized(tcx)), + .is_none_or(|ty| ty.instantiate(tcx, args).is_trivially_sized(tcx)), ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 75893da0e58..7d5e5c2e823 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -20,6 +20,7 @@ use tracing::{debug, instrument}; use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use crate::mir; use crate::query::Providers; use crate::ty::fold::fold_regions; use crate::ty::layout::{FloatExt, IntegerExt}; @@ -1183,18 +1184,18 @@ impl<'tcx> Ty<'tcx> { /// Returns the maximum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. - pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> { + pub fn numeric_max_val(self, tcx: TyCtxt<'tcx>) -> Option<mir::Const<'tcx>> { let typing_env = TypingEnv::fully_monomorphized(); self.numeric_min_and_max_as_bits(tcx) - .map(|(_, max)| ty::Const::from_bits(tcx, max, typing_env, self)) + .map(|(_, max)| mir::Const::from_bits(tcx, max, typing_env, self)) } /// Returns the minimum value for the given numeric type (including `char`s) /// or returns `None` if the type is not numeric. - pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<ty::Const<'tcx>> { + pub fn numeric_min_val(self, tcx: TyCtxt<'tcx>) -> Option<mir::Const<'tcx>> { let typing_env = TypingEnv::fully_monomorphized(); self.numeric_min_and_max_as_bits(tcx) - .map(|(min, _)| ty::Const::from_bits(tcx, min, typing_env, self)) + .map(|(min, _)| mir::Const::from_bits(tcx, min, typing_env, self)) } /// Checks whether values of this type `T` have a size known at diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs index 09a05104e49..23e2e8ad3d3 100644 --- a/compiler/rustc_middle/src/ty/vtable.rs +++ b/compiler/rustc_middle/src/ty/vtable.rs @@ -2,6 +2,7 @@ use std::fmt; use rustc_ast::Mutability; use rustc_macros::HashStable; +use rustc_type_ir::elaborate; use crate::mir::interpret::{AllocId, Allocation, CTFE_ALLOC_SALT, Pointer, Scalar, alloc_range}; use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt}; @@ -64,7 +65,7 @@ pub(crate) fn vtable_min_entries<'tcx>( }; // This includes self in supertraits. - for def_id in tcx.supertrait_def_ids(trait_ref.def_id()) { + for def_id in elaborate::supertrait_def_ids(tcx, trait_ref.def_id()) { count += tcx.own_existential_vtable_entries(def_id).len(); } diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index 390909bb0ab..867f8f63969 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -360,7 +360,7 @@ fn find_item_ty_spans( if let Res::Def(kind, def_id) = path.res && matches!(kind, DefKind::Enum | DefKind::Struct | DefKind::Union) { - let check_params = def_id.as_local().map_or(true, |def_id| { + let check_params = def_id.as_local().is_none_or(|def_id| { if def_id == needle { spans.push(ty.span); } @@ -374,7 +374,13 @@ fn find_item_ty_spans( if let hir::GenericArg::Type(ty) = arg && params_in_repr.contains(i as u32) { - find_item_ty_spans(tcx, ty, needle, spans, seen_representable); + find_item_ty_spans( + tcx, + ty.as_unambig_ty(), + needle, + spans, + seen_representable, + ); } } } diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index ffdb721fb18..053775b4937 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -25,6 +25,8 @@ mir_build_borrow_of_moved_value = borrow of moved value .occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait .value_borrowed_label = value borrowed here after move .suggestion = borrow this binding in the pattern to avoid moving the value + .full_type_name = the full type name has been written to '{$path}' + .consider_verbose = consider using `--verbose` to print the full type name to the console mir_build_call_to_deprecated_safe_fn_requires_unsafe = call to deprecated safe function `{$function}` is unsafe and requires unsafe block diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index b944d13fb0d..b21ec8f3083 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -1986,6 +1986,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { return; } + let false_edge_start_block = candidate.subcandidates[0].false_edge_start_block; candidate.subcandidates.retain_mut(|candidate| { if candidate.extra_data.is_never { candidate.visit_leaves(|subcandidate| { @@ -2000,8 +2001,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } }); if candidate.subcandidates.is_empty() { - // If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block`. - candidate.pre_binding_block = Some(self.cfg.start_new_block()); + // If `candidate` has become a leaf candidate, ensure it has a `pre_binding_block` and `otherwise_block`. + let next_block = self.cfg.start_new_block(); + candidate.pre_binding_block = Some(next_block); + candidate.otherwise_block = Some(next_block); + // In addition, if `candidate` doesn't have `false_edge_start_block`, it should be assigned here. + if candidate.false_edge_start_block.is_none() { + candidate.false_edge_start_block = false_edge_start_block; + } } } diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 20441530a47..945f02821d9 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -785,6 +785,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local = place.as_local().unwrap_or_else(|| bug!("projection in tail call args")); + if !self.local_decls[local].ty.needs_drop(self.tcx, self.typing_env()) { + return None; + } + Some(DropData { source_info, local, kind: DropKind::Value }) } Operand::Constant(_) => None, @@ -795,6 +799,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.scopes.scopes.iter().rev().nth(1).unwrap().region_scope, DUMMY_SP, ); + let typing_env = self.typing_env(); let unwind_drops = &mut self.scopes.unwind_drops; // the innermost scope contains only the destructors for the tail call arguments @@ -805,6 +810,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = drop_data.source_info; let local = drop_data.local; + if !self.local_decls[local].ty.needs_drop(self.tcx, typing_env) { + continue; + } + match drop_data.kind { DropKind::Value => { // `unwind_to` should drop the value that we're about to diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 5eed9ef798d..995bc311b7c 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -266,7 +266,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for LayoutConstrainedPlaceVisitor<'a, 'tcx> { // place, i.e. the expression is a place expression and not a dereference // (since dereferencing something leads us to a different place). ExprKind::Deref { .. } => {} - ref kind if ExprCategory::of(kind).map_or(true, |cat| cat == ExprCategory::Place) => { + ref kind if ExprCategory::of(kind).is_none_or(|cat| cat == ExprCategory::Place) => { visit::walk_expr(self, expr); } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 83aec9ccdef..1f87bf0dbbb 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -7,7 +7,7 @@ use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; use rustc_pattern_analysis::errors::Uncovered; use rustc_pattern_analysis::rustc::RustcPatCtxt; -use rustc_span::{Span, Symbol}; +use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; @@ -753,7 +753,7 @@ pub(crate) struct BindingsWithVariantName { #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")] pub(crate) suggestion: Option<Span>, pub(crate) ty_path: String, - pub(crate) name: Symbol, + pub(crate) name: Ident, } #[derive(LintDiagnostic)] @@ -790,17 +790,21 @@ pub(crate) struct IrrefutableLetPatternsWhileLet { #[derive(Diagnostic)] #[diag(mir_build_borrow_of_moved_value)] -pub(crate) struct BorrowOfMovedValue<'tcx> { +pub(crate) struct BorrowOfMovedValue { #[primary_span] #[label] #[label(mir_build_occurs_because_label)] pub(crate) binding_span: Span, #[label(mir_build_value_borrowed_label)] pub(crate) conflicts_ref: Vec<Span>, - pub(crate) name: Symbol, - pub(crate) ty: Ty<'tcx>, + pub(crate) name: Ident, + pub(crate) ty: String, #[suggestion(code = "ref ", applicability = "machine-applicable")] pub(crate) suggest_borrowing: Option<Span>, + #[note(mir_build_full_type_name)] + #[note(mir_build_consider_verbose)] + pub(crate) has_path: bool, + pub(crate) path: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 66310867200..e0a1117f905 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -25,7 +25,7 @@ use rustc_session::lint::builtin::{ }; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; -use rustc_span::{Span, sym}; +use rustc_span::{Ident, Span, sym}; use rustc_trait_selection::infer::InferCtxtExt; use tracing::instrument; @@ -795,12 +795,16 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: } }); if !conflicts_ref.is_empty() { + let mut path = None; + let ty = cx.tcx.short_ty_string(ty, &mut path); sess.dcx().emit_err(BorrowOfMovedValue { binding_span: pat.span, conflicts_ref, - name, + name: Ident::new(name, pat.span), ty, suggest_borrowing: Some(pat.span.shrink_to_lo()), + has_path: path.is_some(), + path: path.map(|p| p.display().to_string()).unwrap_or_default(), }); } return; @@ -904,7 +908,7 @@ fn check_for_bindings_named_same_as_variants( None }, ty_path, - name, + name: Ident::new(name, pat.span), }, ) } @@ -1086,6 +1090,12 @@ fn find_fallback_pattern_typo<'tcx>( let vis = cx.tcx.visibility(item.owner_id); if vis.is_accessible_from(parent, cx.tcx) { accessible.push(item_name); + // FIXME: the line below from PR #135310 is a workaround for the ICE in issue + // #135289, where a macro in a dependency can create unreachable patterns in the + // current crate. Path trimming expects diagnostics for a typoed const, but no + // diagnostics are emitted and we ICE. See + // `tests/ui/resolve/const-with-typo-in-pattern-binding-ice-135289.rs` for a + // test that reproduces the ICE if we don't use `with_no_trimmed_paths!`. let path = with_no_trimmed_paths!(cx.tcx.def_path_str(item.owner_id)); accessible_path.push(path); } else if name == item_name { diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index e457b514936..9ccabb46c63 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -608,7 +608,7 @@ where let before = diffs_before.as_mut().map(next_in_dataflow_order); assert!(diffs_after.is_empty()); - assert!(diffs_before.as_ref().map_or(true, ExactSizeIterator::is_empty)); + assert!(diffs_before.as_ref().is_none_or(ExactSizeIterator::is_empty)); let terminator = self.cursor.body()[block].terminator(); let mut terminator_str = String::new(); diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 03f11885d58..5bd6fdcf485 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -116,4 +116,8 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { // We may have invalidated some `cleanup` blocks so clean those up now. super::simplify::remove_dead_blocks(body); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index 24c955c0c78..55694cacd92 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -75,4 +75,8 @@ impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { body.basic_blocks_mut().extend(new_blocks); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 12a2fe23b14..87ae2b71654 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -68,6 +68,10 @@ impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { patch.apply(body); } + + fn is_required(&self) -> bool { + true + } } fn add_move_for_packed_drop<'tcx>( diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 53176eec9bc..1fc788a2dad 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -176,4 +176,8 @@ impl<'tcx> crate::MirPass<'tcx> for AddRetag { } } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index e585e338613..e41f47db545 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -61,4 +61,8 @@ impl<'tcx> crate::MirPass<'tcx> for Subtyper { } checker.patcher.apply(body); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 1b7c89fd251..d7e22c12394 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -60,6 +60,10 @@ impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { } } } + + fn is_required(&self) -> bool { + true + } } struct PointerFinder<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 6a22a58470c..cb844019857 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -72,4 +72,8 @@ impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { decl.user_ty = None; } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index f149bf97cde..27af5818982 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -56,6 +56,10 @@ impl<'tcx> crate::MirPass<'tcx> for CopyProp { crate::simplify::remove_unused_definitions(body); } } + + fn is_required(&self) -> bool { + false + } } /// `SsaLocals` computed equivalence classes between locals considering copy/move assignments. diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index a3715b5d485..3b75be58e43 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1688,6 +1688,10 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform { // Run derefer to fix Derefs that are not in the first place deref_finder(tcx, body); } + + fn is_required(&self) -> bool { + true + } } /// Looks for any assignments between locals (e.g., `_4 = _5`) that will both be converted to fields diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 8d397f63cc7..adb99a75a9e 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -10,12 +10,12 @@ use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::coverage::{CounterId, CovTerm, Expression, ExpressionId, Op}; use crate::coverage::counters::balanced_flow::BalancedFlowGraph; -use crate::coverage::counters::iter_nodes::IterNodes; -use crate::coverage::counters::node_flow::{CounterTerm, MergedNodeFlowGraph, NodeCounters}; +use crate::coverage::counters::node_flow::{ + CounterTerm, NodeCounters, make_node_counters, node_flow_data_for_balanced_graph, +}; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; mod balanced_flow; -mod iter_nodes; mod node_flow; mod union_find; @@ -27,12 +27,12 @@ pub(super) fn make_bcb_counters( ) -> CoverageCounters { // Create the derived graphs that are necessary for subsequent steps. let balanced_graph = BalancedFlowGraph::for_graph(graph, |n| !graph[n].is_out_summable); - let merged_graph = MergedNodeFlowGraph::for_balanced_graph(&balanced_graph); + let node_flow_data = node_flow_data_for_balanced_graph(&balanced_graph); // Use those graphs to determine which nodes get physical counters, and how // to compute the execution counts of other nodes from those counters. - let nodes = make_node_counter_priority_list(graph, balanced_graph); - let node_counters = merged_graph.make_node_counters(&nodes); + let priority_list = make_node_flow_priority_list(graph, balanced_graph); + let node_counters = make_node_counters(&node_flow_data, &priority_list); // Convert the counters into a form suitable for embedding into MIR. transcribe_counters(&node_counters, bcb_needs_counter) @@ -40,7 +40,7 @@ pub(super) fn make_bcb_counters( /// Arranges the nodes in `balanced_graph` into a list, such that earlier nodes /// take priority in being given a counter expression instead of a physical counter. -fn make_node_counter_priority_list( +fn make_node_flow_priority_list( graph: &CoverageGraph, balanced_graph: BalancedFlowGraph<&CoverageGraph>, ) -> Vec<BasicCoverageBlock> { @@ -81,11 +81,11 @@ fn transcribe_counters( let mut new = CoverageCounters::with_num_bcbs(bcb_needs_counter.domain_size()); for bcb in bcb_needs_counter.iter() { - // Our counter-creation algorithm doesn't guarantee that a counter - // expression starts or ends with a positive term, so partition the + // Our counter-creation algorithm doesn't guarantee that a node's list + // of terms starts or ends with a positive term, so partition the // counters into "positive" and "negative" lists for easier handling. let (mut pos, mut neg): (Vec<_>, Vec<_>) = - old.counter_expr(bcb).iter().partition_map(|&CounterTerm { node, op }| match op { + old.counter_terms[bcb].iter().partition_map(|&CounterTerm { node, op }| match op { Op::Add => Either::Left(node), Op::Subtract => Either::Right(node), }); diff --git a/compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs b/compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs index c108f96a564..4c20722a043 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters/balanced_flow.rs @@ -20,8 +20,6 @@ use rustc_data_structures::graph::reversed::ReversedGraph; use rustc_index::Idx; use rustc_index::bit_set::DenseBitSet; -use crate::coverage::counters::iter_nodes::IterNodes; - /// A view of an underlying graph that has been augmented to have “balanced flow”. /// This means that the flow (execution count) of each node is equal to the /// sum of its in-edge flows, and also equal to the sum of its out-edge flows. diff --git a/compiler/rustc_mir_transform/src/coverage/counters/iter_nodes.rs b/compiler/rustc_mir_transform/src/coverage/counters/iter_nodes.rs deleted file mode 100644 index 9d87f7af1b0..00000000000 --- a/compiler/rustc_mir_transform/src/coverage/counters/iter_nodes.rs +++ /dev/null @@ -1,16 +0,0 @@ -use rustc_data_structures::graph; -use rustc_index::Idx; - -pub(crate) trait IterNodes: graph::DirectedGraph { - /// Iterates over all nodes of a graph in ascending numeric order. - /// Assumes that nodes are densely numbered, i.e. every index in - /// `0..num_nodes` is a valid node. - /// - /// FIXME: Can this just be part of [`graph::DirectedGraph`]? - fn iter_nodes( - &self, - ) -> impl Iterator<Item = Self::Node> + DoubleEndedIterator + ExactSizeIterator { - (0..self.num_nodes()).map(<Self::Node as Idx>::new) - } -} -impl<G: graph::DirectedGraph> IterNodes for G {} diff --git a/compiler/rustc_mir_transform/src/coverage/counters/node_flow.rs b/compiler/rustc_mir_transform/src/coverage/counters/node_flow.rs index 610498c6c0e..9d80b3af42d 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters/node_flow.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters/node_flow.rs @@ -8,18 +8,16 @@ use rustc_data_structures::graph; use rustc_index::bit_set::DenseBitSet; -use rustc_index::{Idx, IndexVec}; +use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::mir::coverage::Op; -use smallvec::SmallVec; -use crate::coverage::counters::iter_nodes::IterNodes; -use crate::coverage::counters::union_find::{FrozenUnionFind, UnionFind}; +use crate::coverage::counters::union_find::UnionFind; #[cfg(test)] mod tests; -/// View of some underlying graph, in which each node's successors have been -/// merged into a single "supernode". +/// Data representing a view of some underlying graph, in which each node's +/// successors have been merged into a single "supernode". /// /// The resulting supernodes have no obvious meaning on their own. /// However, merging successor nodes means that a node's out-edges can all @@ -30,10 +28,10 @@ mod tests; /// in the merged graph, it becomes possible to analyze the original node flows /// using techniques for analyzing edge flows. #[derive(Debug)] -pub(crate) struct MergedNodeFlowGraph<Node: Idx> { +pub(crate) struct NodeFlowData<Node: Idx> { /// Maps each node to the supernode that contains it, indicated by some /// arbitrary "root" node that is part of that supernode. - supernodes: FrozenUnionFind<Node>, + supernodes: IndexVec<Node, Node>, /// For each node, stores the single supernode that all of its successors /// have been merged into. /// @@ -42,84 +40,71 @@ pub(crate) struct MergedNodeFlowGraph<Node: Idx> { succ_supernodes: IndexVec<Node, Node>, } -impl<Node: Idx> MergedNodeFlowGraph<Node> { - /// Creates a "merged" view of an underlying graph. - /// - /// The given graph is assumed to have [“balanced flow”](balanced-flow), - /// though it does not necessarily have to be a `BalancedFlowGraph`. - /// - /// [balanced-flow]: `crate::coverage::counters::balanced_flow::BalancedFlowGraph`. - pub(crate) fn for_balanced_graph<G>(graph: G) -> Self - where - G: graph::DirectedGraph<Node = Node> + graph::Successors, - { - let mut supernodes = UnionFind::<G::Node>::new(graph.num_nodes()); - - // For each node, merge its successors into a single supernode, and - // arbitrarily choose one of those successors to represent all of them. - let successors = graph - .iter_nodes() - .map(|node| { - graph - .successors(node) - .reduce(|a, b| supernodes.unify(a, b)) - .expect("each node in a balanced graph must have at least one out-edge") - }) - .collect::<IndexVec<G::Node, G::Node>>(); - - // Now that unification is complete, freeze the supernode forest, - // and resolve each arbitrarily-chosen successor to its canonical root. - // (This avoids having to explicitly resolve them later.) - let supernodes = supernodes.freeze(); - let succ_supernodes = successors.into_iter().map(|succ| supernodes.find(succ)).collect(); - - Self { supernodes, succ_supernodes } - } - - fn num_nodes(&self) -> usize { - self.succ_supernodes.len() - } +/// Creates a "merged" view of an underlying graph. +/// +/// The given graph is assumed to have [“balanced flow”](balanced-flow), +/// though it does not necessarily have to be a `BalancedFlowGraph`. +/// +/// [balanced-flow]: `crate::coverage::counters::balanced_flow::BalancedFlowGraph`. +pub(crate) fn node_flow_data_for_balanced_graph<G>(graph: G) -> NodeFlowData<G::Node> +where + G: graph::Successors, +{ + let mut supernodes = UnionFind::<G::Node>::new(graph.num_nodes()); + + // For each node, merge its successors into a single supernode, and + // arbitrarily choose one of those successors to represent all of them. + let successors = graph + .iter_nodes() + .map(|node| { + graph + .successors(node) + .reduce(|a, b| supernodes.unify(a, b)) + .expect("each node in a balanced graph must have at least one out-edge") + }) + .collect::<IndexVec<G::Node, G::Node>>(); + + // Now that unification is complete, take a snapshot of the supernode forest, + // and resolve each arbitrarily-chosen successor to its canonical root. + // (This avoids having to explicitly resolve them later.) + let supernodes = supernodes.snapshot(); + let succ_supernodes = successors.into_iter().map(|succ| supernodes[succ]).collect(); + + NodeFlowData { supernodes, succ_supernodes } +} - fn is_supernode(&self, node: Node) -> bool { - self.supernodes.find(node) == node +/// Uses the graph information in `node_flow_data`, together with a given +/// permutation of all nodes in the graph, to create physical counters and +/// counter expressions for each node in the underlying graph. +/// +/// The given list must contain exactly one copy of each node in the +/// underlying balanced-flow graph. The order of nodes is used as a hint to +/// influence counter allocation: +/// - Earlier nodes are more likely to receive counter expressions. +/// - Later nodes are more likely to receive physical counters. +pub(crate) fn make_node_counters<Node: Idx>( + node_flow_data: &NodeFlowData<Node>, + priority_list: &[Node], +) -> NodeCounters<Node> { + let mut builder = SpantreeBuilder::new(node_flow_data); + + for &node in priority_list { + builder.visit_node(node); } - /// Using the information in this merged graph, together with a given - /// permutation of all nodes in the graph, to create physical counters and - /// counter expressions for each node in the underlying graph. - /// - /// The given list must contain exactly one copy of each node in the - /// underlying balanced-flow graph. The order of nodes is used as a hint to - /// influence counter allocation: - /// - Earlier nodes are more likely to receive counter expressions. - /// - Later nodes are more likely to receive physical counters. - pub(crate) fn make_node_counters(&self, all_nodes_permutation: &[Node]) -> NodeCounters<Node> { - let mut builder = SpantreeBuilder::new(self); - - for &node in all_nodes_permutation { - builder.visit_node(node); - } - - NodeCounters { counter_exprs: builder.finish() } - } + NodeCounters { counter_terms: builder.finish() } } /// End result of allocating physical counters and counter expressions for the /// nodes of a graph. #[derive(Debug)] pub(crate) struct NodeCounters<Node: Idx> { - counter_exprs: IndexVec<Node, CounterExprVec<Node>>, -} - -impl<Node: Idx> NodeCounters<Node> { /// For the given node, returns the finished list of terms that represent /// its physical counter or counter expression. Always non-empty. /// - /// If a node was given a physical counter, its "expression" will contain + /// If a node was given a physical counter, the term list will contain /// that counter as its sole element. - pub(crate) fn counter_expr(&self, this: Node) -> &[CounterTerm<Node>] { - self.counter_exprs[this].as_slice() - } + pub(crate) counter_terms: IndexVec<Node, Vec<CounterTerm<Node>>>, } #[derive(Debug)] @@ -146,12 +131,11 @@ pub(crate) struct CounterTerm<Node> { pub(crate) node: Node, } -/// Stores the list of counter terms that make up a node's counter expression. -type CounterExprVec<Node> = SmallVec<[CounterTerm<Node>; 2]>; - #[derive(Debug)] struct SpantreeBuilder<'a, Node: Idx> { - graph: &'a MergedNodeFlowGraph<Node>, + supernodes: &'a IndexSlice<Node, Node>, + succ_supernodes: &'a IndexSlice<Node, Node>, + is_unvisited: DenseBitSet<Node>, /// Links supernodes to each other, gradually forming a spanning tree of /// the merged-flow graph. @@ -163,26 +147,32 @@ struct SpantreeBuilder<'a, Node: Idx> { yank_buffer: Vec<Node>, /// An in-progress counter expression for each node. Each expression is /// initially empty, and will be filled in as relevant nodes are visited. - counter_exprs: IndexVec<Node, CounterExprVec<Node>>, + counter_terms: IndexVec<Node, Vec<CounterTerm<Node>>>, } impl<'a, Node: Idx> SpantreeBuilder<'a, Node> { - fn new(graph: &'a MergedNodeFlowGraph<Node>) -> Self { - let num_nodes = graph.num_nodes(); + fn new(node_flow_data: &'a NodeFlowData<Node>) -> Self { + let NodeFlowData { supernodes, succ_supernodes } = node_flow_data; + let num_nodes = supernodes.len(); Self { - graph, + supernodes, + succ_supernodes, is_unvisited: DenseBitSet::new_filled(num_nodes), span_edges: IndexVec::from_fn_n(|_| None, num_nodes), yank_buffer: vec![], - counter_exprs: IndexVec::from_fn_n(|_| SmallVec::new(), num_nodes), + counter_terms: IndexVec::from_fn_n(|_| vec![], num_nodes), } } + fn is_supernode(&self, node: Node) -> bool { + self.supernodes[node] == node + } + /// Given a supernode, finds the supernode that is the "root" of its /// spantree component. Two nodes that have the same spantree root are /// connected in the spantree. fn spantree_root(&self, this: Node) -> Node { - debug_assert!(self.graph.is_supernode(this)); + debug_assert!(self.is_supernode(this)); match self.span_edges[this] { None => this, @@ -193,7 +183,7 @@ impl<'a, Node: Idx> SpantreeBuilder<'a, Node> { /// Rotates edges in the spantree so that `this` is the root of its /// spantree component. fn yank_to_spantree_root(&mut self, this: Node) { - debug_assert!(self.graph.is_supernode(this)); + debug_assert!(self.is_supernode(this)); // The rotation is done iteratively, by first traversing from `this` to // its root and storing the path in a buffer, and then traversing the @@ -235,12 +225,12 @@ impl<'a, Node: Idx> SpantreeBuilder<'a, Node> { // Get the supernode containing `this`, and make it the root of its // component of the spantree. - let this_supernode = self.graph.supernodes.find(this); + let this_supernode = self.supernodes[this]; self.yank_to_spantree_root(this_supernode); // Get the supernode containing all of this's successors. - let succ_supernode = self.graph.succ_supernodes[this]; - debug_assert!(self.graph.is_supernode(succ_supernode)); + let succ_supernode = self.succ_supernodes[this]; + debug_assert!(self.is_supernode(succ_supernode)); // If two supernodes are already connected in the spantree, they will // have the same spantree root. (Each supernode is connected to itself.) @@ -268,8 +258,8 @@ impl<'a, Node: Idx> SpantreeBuilder<'a, Node> { // `this_supernode`. // Instead of setting `this.measure = true` as in the original paper, - // we just add the node's ID to its own "expression". - self.counter_exprs[this].push(CounterTerm { node: this, op: Op::Add }); + // we just add the node's ID to its own list of terms. + self.counter_terms[this].push(CounterTerm { node: this, op: Op::Add }); // Walk the spantree from `this.successor` back to `this`. For each // spantree edge along the way, add this node's physical counter to @@ -279,7 +269,7 @@ impl<'a, Node: Idx> SpantreeBuilder<'a, Node> { let &SpantreeEdge { is_reversed, claiming_node, span_parent } = self.span_edges[curr].as_ref().unwrap(); let op = if is_reversed { Op::Subtract } else { Op::Add }; - self.counter_exprs[claiming_node].push(CounterTerm { node: this, op }); + self.counter_terms[claiming_node].push(CounterTerm { node: this, op }); curr = span_parent; } @@ -288,19 +278,20 @@ impl<'a, Node: Idx> SpantreeBuilder<'a, Node> { /// Asserts that all nodes have been visited, and returns the computed /// counter expressions (made up of physical counters) for each node. - fn finish(self) -> IndexVec<Node, CounterExprVec<Node>> { - let Self { graph, is_unvisited, span_edges, yank_buffer: _, counter_exprs } = self; + fn finish(self) -> IndexVec<Node, Vec<CounterTerm<Node>>> { + let Self { ref span_edges, ref is_unvisited, ref counter_terms, .. } = self; assert!(is_unvisited.is_empty(), "some nodes were never visited: {is_unvisited:?}"); debug_assert!( span_edges .iter_enumerated() - .all(|(node, span_edge)| { span_edge.is_some() <= graph.is_supernode(node) }), + .all(|(node, span_edge)| { span_edge.is_some() <= self.is_supernode(node) }), "only supernodes can have a span edge", ); debug_assert!( - counter_exprs.iter().all(|expr| !expr.is_empty()), - "after visiting all nodes, every node should have a non-empty expression", + counter_terms.iter().all(|terms| !terms.is_empty()), + "after visiting all nodes, every node should have at least one term", ); - counter_exprs + + self.counter_terms } } diff --git a/compiler/rustc_mir_transform/src/coverage/counters/node_flow/tests.rs b/compiler/rustc_mir_transform/src/coverage/counters/node_flow/tests.rs index 9e7f754523d..b509a14514b 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters/node_flow/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters/node_flow/tests.rs @@ -4,10 +4,12 @@ use rustc_data_structures::graph::vec_graph::VecGraph; use rustc_index::Idx; use rustc_middle::mir::coverage::Op; -use super::{CounterTerm, MergedNodeFlowGraph, NodeCounters}; +use crate::coverage::counters::node_flow::{ + CounterTerm, NodeCounters, NodeFlowData, make_node_counters, node_flow_data_for_balanced_graph, +}; -fn merged_node_flow_graph<G: graph::Successors>(graph: G) -> MergedNodeFlowGraph<G::Node> { - MergedNodeFlowGraph::for_balanced_graph(graph) +fn node_flow_data<G: graph::Successors>(graph: G) -> NodeFlowData<G::Node> { + node_flow_data_for_balanced_graph(graph) } fn make_graph<Node: Idx + Ord>(num_nodes: usize, edge_pairs: Vec<(Node, Node)>) -> VecGraph<Node> { @@ -30,8 +32,8 @@ fn example_driver() { (4, 0), ]); - let merged = merged_node_flow_graph(&graph); - let counters = merged.make_node_counters(&[3, 1, 2, 0, 4]); + let node_flow_data = node_flow_data(&graph); + let counters = make_node_counters(&node_flow_data, &[3, 1, 2, 0, 4]); assert_eq!(format_counter_expressions(&counters), &[ // (comment to force vertical formatting for clarity) @@ -53,12 +55,12 @@ fn format_counter_expressions<Node: Idx>(counters: &NodeCounters<Node>) -> Vec<S }; counters - .counter_exprs + .counter_terms .indices() .map(|node| { - let mut expr = counters.counter_expr(node).iter().collect::<Vec<_>>(); - expr.sort_by_key(|item| item.node.index()); - format!("[{node:?}]: {}", expr.into_iter().map(format_item).join(" ")) + let mut terms = counters.counter_terms[node].iter().collect::<Vec<_>>(); + terms.sort_by_key(|item| item.node.index()); + format!("[{node:?}]: {}", terms.into_iter().map(format_item).join(" ")) }) .collect() } diff --git a/compiler/rustc_mir_transform/src/coverage/counters/union_find.rs b/compiler/rustc_mir_transform/src/coverage/counters/union_find.rs index 2da4f5f5fce..a826a953fa6 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters/union_find.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters/union_find.rs @@ -88,29 +88,9 @@ impl<Key: Idx> UnionFind<Key> { a } - /// Creates a snapshot of this disjoint-set forest that can no longer be - /// mutated, but can be queried without mutation. - pub(crate) fn freeze(&mut self) -> FrozenUnionFind<Key> { - // Just resolve each key to its actual root. - let roots = self.table.indices().map(|key| self.find(key)).collect(); - FrozenUnionFind { roots } - } -} - -/// Snapshot of a disjoint-set forest that can no longer be mutated, but can be -/// queried in O(1) time without mutation. -/// -/// This is really just a wrapper around a direct mapping from keys to roots, -/// but with a [`Self::find`] method that resembles [`UnionFind::find`]. -#[derive(Debug)] -pub(crate) struct FrozenUnionFind<Key: Idx> { - roots: IndexVec<Key, Key>, -} - -impl<Key: Idx> FrozenUnionFind<Key> { - /// Returns the "root" key of the disjoint-set containing the given key. - /// If two keys have the same root, they belong to the same set. - pub(crate) fn find(&self, key: Key) -> Key { - self.roots[key] + /// Takes a "snapshot" of the current state of this disjoint-set forest, in + /// the form of a vector that directly maps each key to its current root. + pub(crate) fn snapshot(&mut self) -> IndexVec<Key, Key> { + self.table.indices().map(|key| self.find(key)).collect() } } diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index 25dc7f31227..392b54c8d81 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -135,7 +135,7 @@ impl CoverageGraph { bb_to_bcb[bb] = Some(bcb); } - let is_out_summable = basic_blocks.last().map_or(false, |&bb| { + let is_out_summable = basic_blocks.last().is_some_and(|&bb| { bcb_filtered_successors(mir_body[bb].terminator()).is_out_summable() }); let bcb_data = BasicCoverageBlockData { basic_blocks, is_out_summable }; diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 19568735df7..15487d05a30 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -61,6 +61,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage { instrument_function_for_coverage(tcx, mir_body); } + + fn is_required(&self) -> bool { + false + } } fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) { @@ -180,7 +184,12 @@ fn create_mappings( )); for (decision, branches) in mcdc_mappings { - let num_conditions = branches.len() as u16; + // FIXME(#134497): Previously it was possible for some of these branch + // conversions to fail, in which case the remaining branches in the + // decision would be degraded to plain `MappingKind::Branch`. + // The changes in #134497 made that failure impossible, because the + // fallible step was deferred to codegen. But the corresponding code + // in codegen wasn't updated to detect the need for a degrade step. let conditions = branches .into_iter() .map( @@ -206,24 +215,13 @@ fn create_mappings( ) .collect::<Vec<_>>(); - if conditions.len() == num_conditions as usize { - // LLVM requires end index for counter mapping regions. - let kind = MappingKind::MCDCDecision(DecisionInfo { - bitmap_idx: (decision.bitmap_idx + decision.num_test_vectors) as u32, - num_conditions, - }); - let span = decision.span; - mappings.extend(std::iter::once(Mapping { kind, span }).chain(conditions.into_iter())); - } else { - mappings.extend(conditions.into_iter().map(|mapping| { - let MappingKind::MCDCBranch { true_term, false_term, mcdc_params: _ } = - mapping.kind - else { - unreachable!("all mappings here are MCDCBranch as shown above"); - }; - Mapping { kind: MappingKind::Branch { true_term, false_term }, span: mapping.span } - })) - } + // LLVM requires end index for counter mapping regions. + let kind = MappingKind::MCDCDecision(DecisionInfo { + bitmap_idx: (decision.bitmap_idx + decision.num_test_vectors) as u32, + num_conditions: u16::try_from(conditions.len()).unwrap(), + }); + let span = decision.span; + mappings.extend(std::iter::once(Mapping { kind, span }).chain(conditions.into_iter())); } mappings diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 3e7cf8541c2..5e7b46182dc 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -87,15 +87,9 @@ fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { fn coverage_ids_info<'tcx>( tcx: TyCtxt<'tcx>, instance_def: ty::InstanceKind<'tcx>, -) -> CoverageIdsInfo { +) -> Option<CoverageIdsInfo> { let mir_body = tcx.instance_mir(instance_def); - - let Some(fn_cov_info) = mir_body.function_coverage_info.as_deref() else { - return CoverageIdsInfo { - counters_seen: DenseBitSet::new_empty(0), - zero_expressions: DenseBitSet::new_empty(0), - }; - }; + let fn_cov_info = mir_body.function_coverage_info.as_deref()?; let mut counters_seen = DenseBitSet::new_empty(fn_cov_info.num_counters); let mut expressions_seen = DenseBitSet::new_filled(fn_cov_info.expressions.len()); @@ -129,7 +123,7 @@ fn coverage_ids_info<'tcx>( let zero_expressions = identify_zero_expressions(fn_cov_info, &counters_seen, &expressions_seen); - CoverageIdsInfo { counters_seen, zero_expressions } + Some(CoverageIdsInfo { counters_seen, zero_expressions }) } fn all_coverage_in_mir_body<'a, 'tcx>( diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 8fce856687c..4f45d9588a8 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -69,7 +69,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { // Don't do any inference if codegen optimizations are disabled and also MIR inlining is not // enabled. This ensures that we do inference even if someone only passes -Zinline-mir, // which is less confusing than having to also enable -Copt-level=1. - let inliner_will_run = pm::should_run_pass(tcx, &inline::Inline) + let inliner_will_run = pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed) || inline::ForceInline::should_run_pass_for_callee(tcx, def_id.to_def_id()); if matches!(tcx.sess.opts.optimize, OptLevel::No) && !inliner_will_run { return false; diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index bd58b1b6689..d0b313e149a 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -36,6 +36,10 @@ impl<'tcx> crate::MirPass<'tcx> for CtfeLimit { ); } } + + fn is_required(&self) -> bool { + true + } } fn has_back_edge( diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 51af77778af..8879e029346 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -71,6 +71,10 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { let mut patch = visitor.patch; debug_span!("patch").in_scope(|| patch.visit_body_preserves_cfg(body)); } + + fn is_required(&self) -> bool { + false + } } // Note: Currently, places that have their reference taken cannot be tracked. Although this would diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 434e921d439..eea2b0990d7 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -147,4 +147,8 @@ impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { eliminate(tcx, body); } + + fn is_required(&self) -> bool { + false + } } diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index 26b28c8c487..63257df66fb 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -31,6 +31,10 @@ impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks { simplify_cfg(body); } } + + fn is_required(&self) -> bool { + false + } } struct OptApplier<'tcx> { diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index ad7ccef4976..a54bdaa4075 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -81,4 +81,8 @@ impl<'tcx> crate::MirPass<'tcx> for Derefer { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { deref_finder(tcx, body); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index b4f9f1f08ef..41de1b58b91 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -240,6 +240,10 @@ impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { trace!(round_count); } + + fn is_required(&self) -> bool { + false + } } #[derive(Debug, Default)] diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 5dd84975b88..e4fcbaa483d 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for Marker { } fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} + + fn is_required(&self) -> bool { + false + } } pub fn emit_mir(tcx: TyCtxt<'_>) -> io::Result<()> { diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 91e1395e764..eb335a1e4a7 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -227,6 +227,10 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { simplify_cfg(body); } } + + fn is_required(&self) -> bool { + false + } } #[derive(Debug)] diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index d6ecadbfe29..6d3b5d9851b 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -150,4 +150,8 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { } } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 988f1a25561..cb869160c80 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -88,6 +88,10 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { elaborate_patch.apply(body); deref_finder(tcx, body); } + + fn is_required(&self) -> bool { + true + } } /// Records unwind edges which are known to be unreachable, because they are in `drop` terminators diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index a2fd46043ca..29698b0c2e4 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -5,7 +5,7 @@ use rustc_middle::mir::AssertKind; use rustc_middle::ty::TyCtxt; use rustc_session::lint::{self, Lint}; use rustc_span::def_id::DefId; -use rustc_span::{Span, Symbol}; +use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; @@ -114,7 +114,7 @@ pub(crate) struct FnItemRef { #[suggestion(code = "{sugg}", applicability = "unspecified")] pub span: Span, pub sugg: String, - pub ident: String, + pub ident: Ident, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index fb21bf9977f..7e88925b2e1 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -168,7 +168,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { s } }; - let ident = self.tcx.item_name(fn_id).to_ident_string(); + let ident = self.tcx.item_ident(fn_id); let ty_params = fn_args.types().map(|ty| format!("{ty}")); let const_params = fn_args.consts().map(|c| format!("{c}")); let params = ty_params.chain(const_params).join(", "); @@ -177,7 +177,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" }; let sugg = format!( "{} as {}{}fn({}{}){}", - if params.is_empty() { ident.clone() } else { format!("{ident}::<{params}>") }, + if params.is_empty() { ident.to_string() } else { format!("{ident}::<{params}>") }, unsafety, abi, vec!["_"; num_args].join(", "), diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index cb03b422d9e..1c2c82d4cd5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -163,6 +163,10 @@ impl<'tcx> crate::MirPass<'tcx> for GVN { // statements. StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); } + + fn is_required(&self) -> bool { + false + } } newtype_index! { @@ -1174,11 +1178,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { ) if let ty::Slice(..) = to.builtin_deref(true).unwrap().kind() && let ty::Array(_, len) = from.builtin_deref(true).unwrap().kind() => { - return self.insert_constant(Const::from_ty_const( - *len, - self.tcx.types.usize, - self.tcx, - )); + return self.insert_constant(Const::Ty(self.tcx.types.usize, *len)); } _ => Value::UnaryOp(op, arg_index), }; @@ -1488,11 +1488,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Trivial case: we are fetching a statically known length. let place_ty = place.ty(self.local_decls, self.tcx).ty; if let ty::Array(_, len) = place_ty.kind() { - return self.insert_constant(Const::from_ty_const( - *len, - self.tcx.types.usize, - self.tcx, - )); + return self.insert_constant(Const::Ty(self.tcx.types.usize, *len)); } let mut inner = self.simplify_place_value(place, location)?; @@ -1514,11 +1510,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let Some(to) = to.builtin_deref(true) && let ty::Slice(..) = to.kind() { - return self.insert_constant(Const::from_ty_const( - *len, - self.tcx.types.usize, - self.tcx, - )); + return self.insert_constant(Const::Ty(self.tcx.types.usize, *len)); } // Fallback: a symbolic `Len`. diff --git a/compiler/rustc_mir_transform/src/impossible_predicates.rs b/compiler/rustc_mir_transform/src/impossible_predicates.rs index ba8389bbe2f..86e2bf6cb3c 100644 --- a/compiler/rustc_mir_transform/src/impossible_predicates.rs +++ b/compiler/rustc_mir_transform/src/impossible_predicates.rs @@ -53,4 +53,8 @@ impl<'tcx> MirPass<'tcx> for ImpossiblePredicates { body.local_decls.raw.truncate(body.arg_count + 1); } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 2052e28325c..95aeccfdda6 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -66,6 +66,10 @@ impl<'tcx> crate::MirPass<'tcx> for Inline { deref_finder(tcx, body); } } + + fn is_required(&self) -> bool { + false + } } pub struct ForceInline; @@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ForceInline { false } + fn is_required(&self) -> bool { + true + } + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let span = trace_span!("force_inline", body = %tcx.def_path_str(body.source.def_id())); let _guard = span.enter(); diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 5a36519e6a3..4b9ebd40b85 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap()); } } + + fn is_required(&self) -> bool { + false + } } struct InstSimplifyContext<'a, 'tcx> { @@ -167,7 +171,7 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { if let Rvalue::Len(ref place) = *rvalue { let place_ty = place.ty(self.local_decls, self.tcx).ty; if let ty::Array(_, len) = *place_ty.kind() { - let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx); + let const_ = Const::Ty(self.tcx.types.usize, len); let constant = ConstOperand { span: DUMMY_SP, const_, user_ty: None }; *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index c73a03489c5..17084eca6e3 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -105,6 +105,10 @@ impl<'tcx> crate::MirPass<'tcx> for JumpThreading { } OpportunitySet::new(body, opportunities).apply(body); } + + fn is_required(&self) -> bool { + false + } } #[derive(Debug)] diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index 490e7dd8f7e..e201763468b 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -200,6 +200,10 @@ impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { }); } } + + fn is_required(&self) -> bool { + false + } } impl EnumSizeOpt { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index d1bacf1f598..2dc55e3614e 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -388,6 +388,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> { &Lint(sanity_check::SanityCheck), ], None, + pm::Optimizations::Allowed, ); tcx.alloc_steal_mir(body) } @@ -440,6 +441,7 @@ fn mir_promoted( &mut body, &[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage], Some(MirPhase::Analysis(AnalysisPhase::Initial)), + pm::Optimizations::Allowed, ); lint_tail_expr_drop_order::run_lint(tcx, def, &body); @@ -473,7 +475,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { }; let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const); - pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None); + pm::run_passes(tcx, &mut body, &[&ctfe_limit::CtfeLimit], None, pm::Optimizations::Allowed); body } @@ -493,7 +495,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & let is_fn_like = tcx.def_kind(def).is_fn_like(); if is_fn_like { // Do not compute the mir call graph without said call graph actually being used. - if pm::should_run_pass(tcx, &inline::Inline) + if pm::should_run_pass(tcx, &inline::Inline, pm::Optimizations::Allowed) || inline::ForceInline::should_run_pass_for_callee(tcx, def.to_def_id()) { tcx.ensure_with_value().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id())); @@ -533,6 +535,7 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' &Lint(post_drop_elaboration::CheckLiveDrops), ], None, + pm::Optimizations::Allowed, ); } @@ -557,7 +560,13 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &deref_separator::Derefer, ]; - pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup))); + pm::run_passes( + tcx, + body, + passes, + Some(MirPhase::Analysis(AnalysisPhase::PostCleanup)), + pm::Optimizations::Allowed, + ); } /// Returns the sequence of passes that lowers analysis to runtime MIR. @@ -597,7 +606,13 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &simplify::SimplifyCfg::PreOptimizations, ]; - pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup))); + pm::run_passes( + tcx, + body, + passes, + Some(MirPhase::Runtime(RuntimePhase::PostCleanup)), + pm::Optimizations::Allowed, + ); // Clear this by anticipation. Optimizations and runtime MIR have no reason to look // into this information, which is meant for borrowck diagnostics. @@ -611,6 +626,15 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { WithMinOptLevel(1, x) } + let def_id = body.source.def_id(); + let optimizations = if tcx.def_kind(def_id).has_codegen_attrs() + && tcx.codegen_fn_attrs(def_id).optimize.do_not_optimize() + { + pm::Optimizations::Suppressed + } else { + pm::Optimizations::Allowed + }; + // The main optimizations that we do on MIR. pm::run_passes( tcx, @@ -683,6 +707,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &dump_mir::Marker("PreCodegen"), ], Some(MirPhase::Runtime(RuntimePhase::Optimized)), + optimizations, ); } diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index 942c6144ea6..9a9f66ed4fd 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -325,4 +325,8 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { } } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 420661f29c8..aca80e36e33 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -26,6 +26,10 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { lower_slice_len_call(block, slice_len_fn_item_def_id); } } + + fn is_required(&self) -> bool { + false + } } fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>, slice_len_fn_item_def_id: DefId) { diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 534ba991780..500116580d5 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -49,6 +49,10 @@ impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { simplify_cfg(body); } } + + fn is_required(&self) -> bool { + false + } } trait SimplifyMatch<'tcx> { diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index cf5c5f85a9f..f5c57418467 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -27,6 +27,10 @@ impl<'tcx> crate::MirPass<'tcx> for MentionedItems { visitor.visit_body(body); body.set_mentioned_items(visitor.mentioned_items); } + + fn is_required(&self) -> bool { + true + } } // This visitor is carefully in sync with the one in `rustc_monomorphize::collector`. We are diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index 6dfa14d6b52..c63bfdcee85 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -36,4 +36,8 @@ impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { simplify::remove_dead_blocks(body) } + + fn is_required(&self) -> bool { + false + } } diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index 35872de3852..965002aae04 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -71,6 +71,10 @@ impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace { // The return place is always mutable. ret_decl.mutability = Mutability::Mut; } + + fn is_required(&self) -> bool { + false + } } /// MIR that is eligible for the NRVO must fulfill two conditions: diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index c3f0a989ce1..7a8d3ba1ff1 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -90,6 +90,11 @@ pub(super) trait MirPass<'tcx> { fn is_mir_dump_enabled(&self) -> bool { true } + + /// Returns `true` if this pass must be run (i.e. it is required for soundness). + /// For passes which are strictly optimizations, this should return `false`. + /// If this is `false`, `#[optimize(none)]` will disable the pass. + fn is_required(&self) -> bool; } /// Just like `MirPass`, except it cannot mutate `Body`, and MIR dumping is @@ -134,6 +139,10 @@ where fn is_mir_dump_enabled(&self) -> bool { false } + + fn is_required(&self) -> bool { + true + } } pub(super) struct WithMinOptLevel<T>(pub u32, pub T); @@ -153,6 +162,19 @@ where fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.1.run_pass(tcx, body) } + + fn is_required(&self) -> bool { + self.1.is_required() + } +} + +/// Whether to allow non-[required] optimizations +/// +/// [required]: MirPass::is_required +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub(crate) enum Optimizations { + Suppressed, + Allowed, } /// Run the sequence of passes without validating the MIR after each pass. The MIR is still @@ -163,7 +185,7 @@ pub(super) fn run_passes_no_validate<'tcx>( passes: &[&dyn MirPass<'tcx>], phase_change: Option<MirPhase>, ) { - run_passes_inner(tcx, body, passes, phase_change, false); + run_passes_inner(tcx, body, passes, phase_change, false, Optimizations::Allowed); } /// The optional `phase_change` is applied after executing all the passes, if present @@ -172,11 +194,16 @@ pub(super) fn run_passes<'tcx>( body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], phase_change: Option<MirPhase>, + optimizations: Optimizations, ) { - run_passes_inner(tcx, body, passes, phase_change, true); + run_passes_inner(tcx, body, passes, phase_change, true, optimizations); } -pub(super) fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool +pub(super) fn should_run_pass<'tcx, P>( + tcx: TyCtxt<'tcx>, + pass: &P, + optimizations: Optimizations, +) -> bool where P: MirPass<'tcx> + ?Sized, { @@ -196,7 +223,8 @@ where ); *polarity }); - overridden.unwrap_or_else(|| pass.is_enabled(tcx.sess)) + let suppressed = !pass.is_required() && matches!(optimizations, Optimizations::Suppressed); + overridden.unwrap_or_else(|| !suppressed && pass.is_enabled(tcx.sess)) } fn run_passes_inner<'tcx>( @@ -205,6 +233,7 @@ fn run_passes_inner<'tcx>( passes: &[&dyn MirPass<'tcx>], phase_change: Option<MirPhase>, validate_each: bool, + optimizations: Optimizations, ) { let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes; trace!(?overridden_passes); @@ -243,7 +272,7 @@ fn run_passes_inner<'tcx>( for pass in passes { let name = pass.name(); - if !should_run_pass(tcx, *pass) { + if !should_run_pass(tcx, *pass, optimizations) { continue; }; diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index 3eecf79a7ea..76c2f082c0b 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -15,6 +15,10 @@ impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize { let typing_env = ty::TypingEnv::post_analysis(tcx, body.source.def_id()); PostAnalysisNormalizeVisitor { tcx, typing_env }.visit_body_preserves_cfg(body); } + + fn is_required(&self) -> bool { + true + } } struct PostAnalysisNormalizeVisitor<'tcx> { diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index 51abd4da86e..8ccfbe2f194 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -35,6 +35,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks { permute(body.basic_blocks.as_mut(), &updater.map); } + + fn is_required(&self) -> bool { + false + } } /// Rearranges the locals into *use* order. @@ -85,6 +89,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { permute(&mut body.local_decls, &updater.map); } + + fn is_required(&self) -> bool { + false + } } fn permute<I: rustc_index::Idx + Ord, T>(data: &mut IndexVec<I, T>, map: &IndexSlice<I, I>) { diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 6be95b1f0f1..6aa3343bb6e 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -61,6 +61,10 @@ impl<'tcx> crate::MirPass<'tcx> for PromoteTemps<'tcx> { let promoted = promote_candidates(body, tcx, temps, promotable_candidates); self.promoted_fragments.set(promoted); } + + fn is_required(&self) -> bool { + true + } } /// State of a temporary during collection and promotion. diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 95b05f94270..368d5340ac3 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -81,6 +81,10 @@ impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { debug!(def_id = ?body.source.def_id()); while propagate_ssa(tcx, body) {} } + + fn is_required(&self) -> bool { + false + } } fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 76a3edfe0be..9cdd52bec7b 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -74,6 +74,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { debug!("removed {:?} jumps and {:?} landing pads", jumps_folded, landing_pads_removed); } + + fn is_required(&self) -> bool { + true + } } impl RemoveNoopLandingPads { diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs index 71399eb72f0..15fe77d5319 100644 --- a/compiler/rustc_mir_transform/src/remove_place_mention.rs +++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs @@ -20,4 +20,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention { }) } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index 3ecb4a8994f..1ae33c00968 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -22,4 +22,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers { }) } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index e955d8277a4..9044a88295c 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -62,6 +62,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { block.terminator_mut().kind = TerminatorKind::Goto { target: *target }; } } + + fn is_required(&self) -> bool { + true + } } fn is_needs_drop_and_init<'tcx>( diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index e335051d656..8a8cdafc690 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -38,4 +38,8 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { simplify_cfg(body); } } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 55e5701bd0a..78d94a03867 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -27,6 +27,10 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { replacer.visit_basic_block_data(bb, data); } } + + fn is_required(&self) -> bool { + true + } } struct Replacer<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 4648ec33c93..f7ec0f740d3 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -119,6 +119,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< &add_call_guards::CriticalCallEdges, ], Some(MirPhase::Runtime(RuntimePhase::Optimized)), + pm::Optimizations::Allowed, ); return body; diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 4f312ed2aaa..67070f03ded 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -83,6 +83,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source); simplify_cfg(body); } + + fn is_required(&self) -> bool { + false + } } struct CfgSimplifier<'a, 'tcx> { @@ -405,6 +409,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { body.local_decls.shrink_to_fit(); } } + + fn is_required(&self) -> bool { + false + } } pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) { diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index bea3d0d8557..12c3503879f 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -60,4 +60,8 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { }; } } + + fn is_required(&self) -> bool { + false + } } diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index b6d80173086..c0f25c7ecfe 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -140,6 +140,10 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { body.basic_blocks_mut()[idx].statements.insert(0, stmt); } } + + fn is_required(&self) -> bool { + false + } } struct OptimizationFinder<'a, 'tcx> { diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 10b3c0ae94f..c5e951eb8b2 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -81,6 +81,10 @@ impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { } } } + + fn is_required(&self) -> bool { + true + } } #[derive(Copy, Clone, Debug)] diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index d54ea3feab6..92e5c8a9ca4 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -48,6 +48,10 @@ impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { } } } + + fn is_required(&self) -> bool { + false + } } /// Identify all locals that are not eligible for SROA. diff --git a/compiler/rustc_mir_transform/src/strip_debuginfo.rs b/compiler/rustc_mir_transform/src/strip_debuginfo.rs index 438c75726bb..9ede8aa79c4 100644 --- a/compiler/rustc_mir_transform/src/strip_debuginfo.rs +++ b/compiler/rustc_mir_transform/src/strip_debuginfo.rs @@ -31,4 +31,8 @@ impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo { ) }); } + + fn is_required(&self) -> bool { + true + } } diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 55dcad0680a..1ff7043ed14 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -208,4 +208,8 @@ impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { patch.apply(body); } + + fn is_required(&self) -> bool { + false + } } diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index 734703ec78b..1e5d9469c03 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -52,6 +52,10 @@ impl crate::MirPass<'_> for UnreachablePropagation { body.basic_blocks_mut()[bb].statements.clear(); } } + + fn is_required(&self) -> bool { + false + } } /// Return whether the current terminator is fully unreachable. diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index b62e34ac08d..026923ad786 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -91,6 +91,10 @@ impl<'tcx> crate::MirPass<'tcx> for Validator { } } } + + fn is_required(&self) -> bool { + true + } } struct CfgChecker<'a, 'tcx> { diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 7b179663430..e08c348a64d 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -110,7 +110,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; use rustc_middle::mir::mono::{ CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData, - Visibility, + MonoItemPartitions, Visibility, }; use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths}; use rustc_middle::ty::{self, InstanceKind, TyCtxt}; @@ -1114,7 +1114,7 @@ where } } -fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) { +fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitions<'_> { let collection_strategy = match tcx.sess.opts.unstable_opts.print_mono_items { Some(ref s) => { let mode = s.to_lowercase(); @@ -1236,7 +1236,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co } } - (tcx.arena.alloc(mono_items), codegen_units) + MonoItemPartitions { all_mono_items: tcx.arena.alloc(mono_items), codegen_units } } /// Outputs stats about instantiation counts and estimated size, per `MonoItem`'s @@ -1319,14 +1319,13 @@ fn dump_mono_items_stats<'tcx>( pub(crate) fn provide(providers: &mut Providers) { providers.collect_and_partition_mono_items = collect_and_partition_mono_items; - providers.is_codegened_item = |tcx, def_id| { - let (all_mono_items, _) = tcx.collect_and_partition_mono_items(()); - all_mono_items.contains(&def_id) - }; + providers.is_codegened_item = + |tcx, def_id| tcx.collect_and_partition_mono_items(()).all_mono_items.contains(&def_id); providers.codegen_unit = |tcx, name| { - let (_, all) = tcx.collect_and_partition_mono_items(()); - all.iter() + tcx.collect_and_partition_mono_items(()) + .codegen_units + .iter() .find(|cgu| cgu.name() == name) .unwrap_or_else(|| panic!("failed to find cgu with name {name:?}")) }; diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index f9168112216..451c215566b 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -13,7 +13,6 @@ rustc_macros = { path = "../rustc_macros", optional = true } rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_type_ir = { path = "../rustc_type_ir", default-features = false } rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } -smallvec = "1.8.1" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 8a54a4ece98..62a7c84bc28 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -273,7 +273,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> { // // For this we set `next_orig_uv` to the next smallest, not yet compressed, // universe of the input. - if next_orig_uv.map_or(true, |curr_next_uv| uv.cannot_name(curr_next_uv)) { + if next_orig_uv.is_none_or(|curr_next_uv| uv.cannot_name(curr_next_uv)) { next_orig_uv = Some(uv); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 37678bfd880..8d1194ee539 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -277,23 +277,7 @@ where param_env: I::ParamEnv, ty: I::Ty, ) -> Result<I::Ty, NoSolution> { - if let ty::Alias(..) = ty.kind() { - let normalized_ty = self.next_ty_infer(); - let alias_relate_goal = Goal::new( - self.cx(), - param_env, - ty::PredicateKind::AliasRelate( - ty.into(), - normalized_ty.into(), - ty::AliasRelationDirection::Equate, - ), - ); - self.add_goal(GoalSource::Misc, alias_relate_goal); - self.try_evaluate_added_goals()?; - Ok(self.resolve_vars_if_possible(normalized_ty)) - } else { - Ok(ty) - } + self.structurally_normalize_term(param_env, ty.into()).map(|term| term.expect_ty()) } /// Normalize a const for when it is structurally matched on, or more likely @@ -308,22 +292,34 @@ where param_env: I::ParamEnv, ct: I::Const, ) -> Result<I::Const, NoSolution> { - if let ty::ConstKind::Unevaluated(..) = ct.kind() { - let normalized_ct = self.next_const_infer(); + self.structurally_normalize_term(param_env, ct.into()).map(|term| term.expect_const()) + } + + /// Normalize a term for when it is structurally matched on. + /// + /// This function is necessary in nearly all cases before matching on a ty/const. + /// Not doing so is likely to be incomplete and therefore unsound during coherence. + fn structurally_normalize_term( + &mut self, + param_env: I::ParamEnv, + term: I::Term, + ) -> Result<I::Term, NoSolution> { + if let Some(_) = term.to_alias_term() { + let normalized_term = self.next_term_infer_of_kind(term); let alias_relate_goal = Goal::new( self.cx(), param_env, ty::PredicateKind::AliasRelate( - ct.into(), - normalized_ct.into(), + term, + normalized_term, ty::AliasRelationDirection::Equate, ), ); self.add_goal(GoalSource::Misc, alias_relate_goal); self.try_evaluate_added_goals()?; - Ok(self.resolve_vars_if_possible(normalized_ct)) + Ok(self.resolve_vars_if_possible(normalized_term)) } else { - Ok(ct) + Ok(term) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 4faa243c02a..513fc9355c8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -8,7 +8,6 @@ use rustc_type_ir::lang_items::TraitSolverLangItem; use rustc_type_ir::solve::CanonicalResponse; use rustc_type_ir::visit::TypeVisitableExt as _; use rustc_type_ir::{self as ty, Interner, TraitPredicate, TypingMode, Upcast as _, elaborate}; -use smallvec::SmallVec; use tracing::{instrument, trace}; use crate::delegate::SolverDelegate; @@ -1199,33 +1198,42 @@ where // nested requirements, over all others. This is a fix for #53123 and // prevents where-bounds from accidentally extending the lifetime of a // variable. - if candidates - .iter() - .any(|c| matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial))) - { - let trivial_builtin_impls: SmallVec<[_; 1]> = candidates - .iter() - .filter(|c| { - matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial)) - }) - .map(|c| c.result) - .collect(); + let mut trivial_builtin_impls = candidates.iter().filter(|c| { + matches!(c.source, CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial)) + }); + if let Some(candidate) = trivial_builtin_impls.next() { // There should only ever be a single trivial builtin candidate // as they would otherwise overlap. - assert_eq!(trivial_builtin_impls.len(), 1); - return if let Some(response) = self.try_merge_responses(&trivial_builtin_impls) { - Ok((response, Some(TraitGoalProvenVia::Misc))) - } else { - Ok((self.bail_with_ambiguity(&trivial_builtin_impls), None)) - }; + assert!(trivial_builtin_impls.next().is_none()); + return Ok((candidate.result, Some(TraitGoalProvenVia::Misc))); } // If there are non-global where-bounds, prefer where-bounds // (including global ones) over everything else. let has_non_global_where_bounds = candidates.iter().any(|c| match c.source { CandidateSource::ParamEnv(idx) => { - let where_bound = goal.param_env.caller_bounds().get(idx); - where_bound.has_bound_vars() || !where_bound.is_global() + let where_bound = goal.param_env.caller_bounds().get(idx).unwrap(); + let ty::ClauseKind::Trait(trait_pred) = where_bound.kind().skip_binder() else { + unreachable!("expected trait-bound: {where_bound:?}"); + }; + + if trait_pred.has_bound_vars() || !trait_pred.is_global() { + return true; + } + + // We don't consider a trait-bound global if it has a projection bound. + // + // See ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs + // for an example where this is necessary. + for p in goal.param_env.caller_bounds().iter() { + if let ty::ClauseKind::Projection(proj) = p.kind().skip_binder() { + if proj.projection_term.trait_ref(self.cx()) == trait_pred.trait_ref { + return true; + } + } + } + + false } _ => false, }); diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index f78d9dc2bfc..50287b706ce 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3233,7 +3233,7 @@ pub(crate) struct MalformedCfgAttr { pub(crate) struct UnknownBuiltinConstruct { #[primary_span] pub span: Span, - pub name: Symbol, + pub name: Ident, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index f963a424a7f..e681987ff07 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -11,18 +11,21 @@ #![feature(if_let_guard)] #![feature(iter_intersperse)] #![feature(let_chains)] +#![feature(string_from_utf8_lossy_owned)] #![warn(unreachable_pub)] // tidy-alphabetical-end -use std::path::Path; +use std::path::{Path, PathBuf}; +use std::str::Utf8Error; use rustc_ast as ast; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrItem, Attribute, MetaItemInner, token}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Diag, FatalError, PResult}; +use rustc_errors::{Diag, EmissionGuarantee, FatalError, PResult, pluralize}; use rustc_session::parse::ParseSess; +use rustc_span::source_map::SourceMap; use rustc_span::{FileName, SourceFile, Span}; pub use unicode_normalization::UNICODE_VERSION as UNICODE_NORMALIZATION_VERSION; @@ -73,9 +76,22 @@ pub fn new_parser_from_file<'a>( path: &Path, sp: Option<Span>, ) -> Result<Parser<'a>, Vec<Diag<'a>>> { - let source_file = psess.source_map().load_file(path).unwrap_or_else(|e| { - let msg = format!("couldn't read {}: {}", path.display(), e); + let sm = psess.source_map(); + let source_file = sm.load_file(path).unwrap_or_else(|e| { + let msg = format!("couldn't read `{}`: {}", path.display(), e); let mut err = psess.dcx().struct_fatal(msg); + if let Ok(contents) = std::fs::read(path) + && let Err(utf8err) = String::from_utf8(contents.clone()) + { + utf8_error( + sm, + &path.display().to_string(), + sp, + &mut err, + utf8err.utf8_error(), + &contents, + ); + } if let Some(sp) = sp { err.span(sp); } @@ -84,6 +100,49 @@ pub fn new_parser_from_file<'a>( new_parser_from_source_file(psess, source_file) } +pub fn utf8_error<E: EmissionGuarantee>( + sm: &SourceMap, + path: &str, + sp: Option<Span>, + err: &mut Diag<'_, E>, + utf8err: Utf8Error, + contents: &[u8], +) { + // The file exists, but it wasn't valid UTF-8. + let start = utf8err.valid_up_to(); + let note = format!("invalid utf-8 at byte `{start}`"); + let msg = if let Some(len) = utf8err.error_len() { + format!( + "byte{s} `{bytes}` {are} not valid utf-8", + bytes = if len == 1 { + format!("{:?}", contents[start]) + } else { + format!("{:?}", &contents[start..start + len]) + }, + s = pluralize!(len), + are = if len == 1 { "is" } else { "are" }, + ) + } else { + note.clone() + }; + let contents = String::from_utf8_lossy(contents).to_string(); + let source = sm.new_source_file(PathBuf::from(path).into(), contents); + let span = Span::with_root_ctxt( + source.normalized_byte_pos(start as u32), + source.normalized_byte_pos(start as u32), + ); + if span.is_dummy() { + err.note(note); + } else { + if sp.is_some() { + err.span_note(span, msg); + } else { + err.span(span); + err.span_label(span, msg); + } + } +} + /// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing /// the initial token stream. fn new_parser_from_source_file( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 7533e75ffe2..a5b73ce4098 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1958,7 +1958,7 @@ impl<'a> Parser<'a> { } else { let err = self.dcx().create_err(errors::UnknownBuiltinConstruct { span: lo.to(ident.span), - name: ident.name, + name: ident, }); return Err(err); }; @@ -2095,7 +2095,7 @@ impl<'a> Parser<'a> { // point literal here, since there's no use of the exponent // syntax that also constitutes a valid integer, so we need // not check for that. - if suffix.map_or(true, |s| s == sym::f32 || s == sym::f64) + if suffix.is_none_or(|s| s == sym::f32 || s == sym::f64) && symbol.as_str().chars().all(|c| c.is_numeric() || c == '_') && self.token.span.hi() == next_token.span.lo() { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 10756be6afb..714a60cb179 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -189,8 +189,9 @@ pub struct Parser<'a> { } // This type is used a lot, e.g. it's cloned when matching many declarative macro rules with -// nonterminals. Make sure it doesn't unintentionally get bigger. -#[cfg(all(target_pointer_width = "64", not(target_arch = "s390x")))] +// nonterminals. Make sure it doesn't unintentionally get bigger. We only check a few arches +// though, because `TokenTypeSet(u128)` alignment varies on others, changing the total size. +#[cfg(all(target_pointer_width = "64", any(target_arch = "aarch64", target_arch = "x86_64")))] rustc_data_structures::static_assert_size!(Parser<'_>, 288); /// Stores span information about a closure. @@ -1597,45 +1598,35 @@ impl<'a> Parser<'a> { // Only used when debugging. #[allow(unused)] pub(crate) fn debug_lookahead(&self, lookahead: usize) -> impl fmt::Debug + '_ { - struct DebugParser<'dbg> { - parser: &'dbg Parser<'dbg>, - lookahead: usize, - } - - impl fmt::Debug for DebugParser<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { parser, lookahead } = self; - let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of - - // we don't need N spans, but we want at least one, so print all of prev_token - dbg_fmt.field("prev_token", &parser.prev_token); - let mut tokens = vec![]; - for i in 0..*lookahead { - let tok = parser.look_ahead(i, |tok| tok.kind.clone()); - let is_eof = tok == TokenKind::Eof; - tokens.push(tok); - if is_eof { - // Don't look ahead past EOF. - break; - } - } - dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish()); - dbg_fmt.field("approx_token_stream_pos", &parser.num_bump_calls); - - // some fields are interesting for certain values, as they relate to macro parsing - if let Some(subparser) = parser.subparser_name { - dbg_fmt.field("subparser_name", &subparser); - } - if let Recovery::Forbidden = parser.recovery { - dbg_fmt.field("recovery", &parser.recovery); + fmt::from_fn(move |f| { + let mut dbg_fmt = f.debug_struct("Parser"); // or at least, one view of + + // we don't need N spans, but we want at least one, so print all of prev_token + dbg_fmt.field("prev_token", &self.prev_token); + let mut tokens = vec![]; + for i in 0..lookahead { + let tok = self.look_ahead(i, |tok| tok.kind.clone()); + let is_eof = tok == TokenKind::Eof; + tokens.push(tok); + if is_eof { + // Don't look ahead past EOF. + break; } + } + dbg_fmt.field_with("tokens", |field| field.debug_list().entries(tokens).finish()); + dbg_fmt.field("approx_token_stream_pos", &self.num_bump_calls); - // imply there's "more to know" than this view - dbg_fmt.finish_non_exhaustive() + // some fields are interesting for certain values, as they relate to macro parsing + if let Some(subparser) = self.subparser_name { + dbg_fmt.field("subparser_name", &subparser); + } + if let Recovery::Forbidden = self.recovery { + dbg_fmt.field("recovery", &self.recovery); } - } - DebugParser { parser: self, lookahead } + // imply there's "more to know" than this view + dbg_fmt.finish_non_exhaustive() + }) } pub fn clear_expected_token_types(&mut self) { diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 8b6b37c0f8f..86f673c100c 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -11,7 +11,7 @@ use rustc_session::errors::report_lit_error; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE}; use rustc_session::parse::ParseSess; -use rustc_span::{BytePos, Span, Symbol, sym}; +use rustc_span::{Span, Symbol, sym}; use crate::{errors, parse_in}; @@ -164,11 +164,7 @@ pub fn check_attribute_safety(psess: &ParseSess, safety: AttributeSafety, attr: // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the // `unsafe(`, `)` right after and right before the opening and closing // square bracket respectively. - let diag_span = if attr_item.span().can_be_used_for_suggestions() { - attr_item.span() - } else { - attr.span.with_lo(attr.span.lo() + BytePos(2)).with_hi(attr.span.hi() - BytePos(1)) - }; + let diag_span = attr_item.span(); if attr.span.at_least_rust_2024() { psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe { diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 9eb335cb34c..5418f054beb 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -514,13 +514,7 @@ impl<'a> Parser<'a> { /// Consumes all whitespace characters until the first non-whitespace character fn ws(&mut self) { - while let Some(&(_, c)) = self.cur.peek() { - if c.is_whitespace() { - self.cur.next(); - } else { - break; - } - } + while let Some(_) = self.cur.next_if(|&(_, c)| c.is_whitespace()) {} } /// Parses all of a string which is to be considered a "raw literal" in a @@ -545,7 +539,7 @@ impl<'a> Parser<'a> { } } } - &self.input[start..self.input.len()] + &self.input[start..] } /// Parses an `Argument` structure, or what's contained within braces inside the format string. diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 3ed600a717f..978cb7af242 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -502,11 +502,6 @@ passes_multiple_rustc_main = .first = first `#[rustc_main]` function .additional = additional `#[rustc_main]` function -passes_multiple_start_functions = - multiple `start` functions - .label = multiple `start` functions - .previous = previous `#[start]` function here - passes_must_not_suspend = `must_not_suspend` attribute should be applied to a struct, enum, union, or trait .label = is not a struct, enum, union, or trait @@ -817,6 +812,9 @@ passes_unused_duplicate = passes_unused_empty_lints_note = attribute `{$name}` with an empty list has no effect +passes_unused_linker_warnings_note = + the `linker_warnings` lint can only be controlled at the root of a crate that needs to be linked + passes_unused_multiple = multiple `{$name}` attributes .suggestion = remove this attribute diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1b2b8ac5dd9..e19819a22b4 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -25,6 +25,7 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, TyCtxt, TypingMode}; use rustc_middle::{bug, span_bug}; +use rustc_session::config::CrateType; use rustc_session::lint::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, @@ -275,7 +276,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::lang | sym::needs_allocator | sym::default_lib_allocator - | sym::start | sym::custom_mir, .. ] => {} @@ -2328,6 +2328,42 @@ impl<'tcx> CheckAttrVisitor<'tcx> { && item.path == sym::reason { errors::UnusedNote::NoLints { name: attr.name_or_empty() } + } else if matches!( + attr.name_or_empty(), + sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect + ) && let Some(meta) = attr.meta_item_list() + && meta.iter().any(|meta| { + meta.meta_item().map_or(false, |item| item.path == sym::linker_messages) + }) + { + if hir_id != CRATE_HIR_ID { + match attr.style { + ast::AttrStyle::Outer => self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::OuterCrateLevelAttr, + ), + ast::AttrStyle::Inner => self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::InnerCrateLevelAttr, + ), + }; + return; + } else { + let never_needs_link = self + .tcx + .crate_types() + .iter() + .all(|kind| matches!(kind, CrateType::Rlib | CrateType::Staticlib)); + if never_needs_link { + errors::UnusedNote::LinkerWarningsBinaryCrateOnly + } else { + return; + } + } } else if attr.name_or_empty() == sym::default_method_body_is_const { errors::UnusedNote::DefaultMethodBodyConst } else { @@ -2655,7 +2691,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) { sym::repr, sym::path, sym::automatically_derived, - sym::start, sym::rustc_main, sym::derive, sym::test, @@ -2810,7 +2845,7 @@ fn doc_fake_variadic_is_allowed_self_ty(self_ty: &hir::Ty<'_>) -> bool { && let Some(&[hir::GenericArg::Type(ty)]) = path.segments.last().map(|last| last.args().args) { - doc_fake_variadic_is_allowed_self_ty(ty) + doc_fake_variadic_is_allowed_self_ty(ty.as_unambig_ty()) } else { false }) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index c5dc8e68fe8..e5b63b9b4a6 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -460,7 +460,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } // mark self_ty live - intravisit::walk_ty(self, impl_ref.self_ty); + intravisit::walk_unambig_ty(self, impl_ref.self_ty); if let Some(&impl_item_id) = self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id) { @@ -1231,7 +1231,7 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) { continue; } - let is_positional = variant.fields.raw.first().map_or(false, |field| { + let is_positional = variant.fields.raw.first().is_some_and(|field| { field.name.as_str().starts_with(|c: char| c.is_ascii_digit()) }); let report_on = diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 4949a4316a7..22291c9282d 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -10,9 +10,7 @@ use rustc_session::RemapFileNameExt; use rustc_session::config::{CrateType, EntryFnType, RemapPathScopeComponents, sigpipe}; use rustc_span::{Span, Symbol, sym}; -use crate::errors::{ - AttrOnlyInFunctions, ExternMain, MultipleRustcMain, MultipleStartFunctions, NoMainErr, -}; +use crate::errors::{AttrOnlyInFunctions, ExternMain, MultipleRustcMain, NoMainErr}; struct EntryContext<'tcx> { tcx: TyCtxt<'tcx>, @@ -20,9 +18,6 @@ struct EntryContext<'tcx> { /// The function has the `#[rustc_main]` attribute. rustc_main_fn: Option<(LocalDefId, Span)>, - /// The function that has the attribute `#[start]` on it. - start_fn: Option<(LocalDefId, Span)>, - /// The functions that one might think are `main` but aren't, e.g. /// main functions not defined at the top level. For diagnostics. non_main_fns: Vec<Span>, @@ -40,8 +35,7 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> { return None; } - let mut ctxt = - EntryContext { tcx, rustc_main_fn: None, start_fn: None, non_main_fns: Vec::new() }; + let mut ctxt = EntryContext { tcx, rustc_main_fn: None, non_main_fns: Vec::new() }; for id in tcx.hir().items() { check_and_search_item(id, &mut ctxt); @@ -57,7 +51,7 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) { if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) { - for attr in [sym::start, sym::rustc_main] { + for attr in [sym::rustc_main] { if let Some(span) = attr_span_by_symbol(ctxt, id, attr) { ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr }); } @@ -91,24 +85,11 @@ fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) { }); } } - EntryPointType::Start => { - if ctxt.start_fn.is_none() { - ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id))); - } else { - ctxt.tcx.dcx().emit_err(MultipleStartFunctions { - span: ctxt.tcx.def_span(id.owner_id), - labeled: ctxt.tcx.def_span(id.owner_id.to_def_id()), - previous: ctxt.start_fn.unwrap().1, - }); - } - } } } fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId, EntryFnType)> { - if let Some((def_id, _)) = visitor.start_fn { - Some((def_id.to_def_id(), EntryFnType::Start)) - } else if let Some((local_def_id, _)) = visitor.rustc_main_fn { + if let Some((local_def_id, _)) = visitor.rustc_main_fn { let def_id = local_def_id.to_def_id(); Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) })) } else { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index c3043ac60aa..0aa50ad19ff 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -802,6 +802,8 @@ pub(crate) enum UnusedNote { NoLints { name: Symbol }, #[note(passes_unused_default_method_body_const_note)] DefaultMethodBodyConst, + #[note(passes_unused_linker_warnings_note)] + LinkerWarningsBinaryCrateOnly, } #[derive(LintDiagnostic)] @@ -1314,17 +1316,6 @@ pub(crate) struct MultipleRustcMain { } #[derive(Diagnostic)] -#[diag(passes_multiple_start_functions, code = E0138)] -pub(crate) struct MultipleStartFunctions { - #[primary_span] - pub span: Span, - #[label] - pub labeled: Span, - #[label(passes_previous)] - pub previous: Span, -} - -#[derive(Diagnostic)] #[diag(passes_extern_main)] pub(crate) struct ExternMain { #[primary_span] @@ -1800,7 +1791,7 @@ pub(crate) struct UnusedAssign { pub(crate) struct UnusedAssignSuggestion { pub pre: &'static str, #[suggestion_part(code = "{pre}mut ")] - pub ty_span: Span, + pub ty_span: Option<Span>, #[suggestion_part(code = "")] pub ty_ref_span: Span, #[suggestion_part(code = "*")] diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 6617cf2f723..8b10543f6fd 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -5,8 +5,7 @@ use rustc_ast::visit::BoundKind; use rustc_ast::{self as ast, NodeId, visit as ast_visit}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir as hir; -use rustc_hir::{HirId, intravisit as hir_visit}; +use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit}; use rustc_middle::hir::map::Map; use rustc_middle::ty::TyCtxt; use rustc_middle::util::common::to_readable_str; @@ -363,7 +362,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_expr_field(self, f) } - fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { + fn visit_ty(&mut self, t: &'v hir::Ty<'v, AmbigArg>) { record_variants!((self, t, t.kind, Some(t.hir_id), hir, Ty, TyKind), [ InferDelegation, Slice, @@ -476,7 +475,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir::GenericArg::Lifetime(lt) => self.visit_lifetime(lt), hir::GenericArg::Type(ty) => self.visit_ty(ty), hir::GenericArg::Const(ct) => self.visit_const_arg(ct), - hir::GenericArg::Infer(inf) => self.visit_infer(inf), + hir::GenericArg::Infer(inf) => self.visit_id(inf.hir_id), } } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 426899a4d5c..73da8855e10 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -1620,24 +1620,28 @@ impl<'tcx> Liveness<'_, 'tcx> { && let item = self.ir.tcx.hir_owner_node(item_id) && let Some(fn_decl) = item.fn_decl() && let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind - && let Some((ty_span, pre)) = fn_decl + && let Some((lt, mut_ty)) = fn_decl .inputs .iter() .filter_map(|ty| { if ty.span == *ty_span && let hir::TyKind::Ref(lt, mut_ty) = ty.kind { - // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty` - Some(( - mut_ty.ty.span.shrink_to_lo(), - if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " }, - )) + Some((lt, mut_ty)) } else { None } }) .next() { + let ty_span = if mut_ty.mutbl.is_mut() { + // Leave `&'name mut Ty` and `&mut Ty` as they are (#136028). + None + } else { + // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty` + Some(mut_ty.ty.span.shrink_to_lo()) + }; + let pre = if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " }; Some(errors::UnusedAssignSuggestion { ty_span, pre, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 60734122e63..a52f080038d 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -11,12 +11,11 @@ use rustc_attr_parsing::{ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; use rustc_feature::{ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature}; -use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId}; use rustc_hir::hir_id::CRATE_HIR_ID; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; +use rustc_hir::intravisit::{self, Visitor, VisitorExt}; +use rustc_hir::{self as hir, AmbigArg, FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; use rustc_middle::middle::privacy::EffectiveVisibilities; @@ -802,7 +801,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { )) = stab { let mut c = CheckTraitImplStable { tcx: self.tcx, fully_stable: true }; - c.visit_ty(self_ty); + c.visit_ty_unambig(self_ty); c.visit_trait_ref(t); // do not lint when the trait isn't resolved, since resolution error should @@ -1028,7 +1027,7 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { intravisit::walk_trait_ref(self, t) } - fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) { + fn visit_ty(&mut self, t: &'tcx Ty<'tcx, AmbigArg>) { if let TyKind::Never = t.kind { self.fully_stable = false; } @@ -1042,12 +1041,12 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> { fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) { for ty in fd.inputs { - self.visit_ty(ty) + self.visit_ty_unambig(ty) } if let hir::FnRetTy::Return(output_ty) = fd.output { match output_ty.kind { TyKind::Never => {} // `-> !` is stable - _ => self.visit_ty(output_ty), + _ => self.visit_ty_unambig(output_ty), } } } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index ae991e3ce40..2694cf472f4 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -794,9 +794,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { // fictitious values after `{u,i}size::MAX` (see [`IntRange::split`] for why we do // this). We show this to the user as `usize::MAX..` which is slightly incorrect but // probably clear enough. - let c = ty.numeric_max_val(cx.tcx).unwrap(); - let value = mir::Const::from_ty_const(c, ty.0, cx.tcx); - lo = PatRangeBoundary::Finite(value); + lo = PatRangeBoundary::Finite(ty.numeric_max_val(cx.tcx).unwrap()); } let hi = if let Some(hi) = range.hi.minus_one() { hi diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl index 7785f1a7f81..43c34a109d7 100644 --- a/compiler/rustc_privacy/messages.ftl +++ b/compiler/rustc_privacy/messages.ftl @@ -1,5 +1,19 @@ -privacy_field_is_private = field `{$field_name}` of {$variant_descr} `{$def_path_str}` is private -privacy_field_is_private_is_update_syntax_label = field `{$field_name}` is private +privacy_field_is_private = + {$len -> + [1] field + *[other] fields + } {$field_names} of {$variant_descr} `{$def_path_str}` {$len -> + [1] is + *[other] are + } private + .label = in this type +privacy_field_is_private_is_update_syntax_label = {$rest_len -> + [1] field + *[other] fields + } {$rest_field_names} {$rest_len -> + [1] is + *[other] are + } private privacy_field_is_private_label = private field privacy_from_private_dep_in_public_interface = diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index f5e641eb642..4d1d58c0852 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -1,5 +1,5 @@ -use rustc_errors::DiagArgFromDisplay; use rustc_errors::codes::*; +use rustc_errors::{DiagArgFromDisplay, MultiSpan}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_span::{Span, Symbol}; @@ -7,12 +7,15 @@ use rustc_span::{Span, Symbol}; #[diag(privacy_field_is_private, code = E0451)] pub(crate) struct FieldIsPrivate { #[primary_span] - pub span: Span, - pub field_name: Symbol, + pub span: MultiSpan, + #[label] + pub struct_span: Option<Span>, + pub field_names: String, pub variant_descr: &'static str, pub def_path_str: String, #[subdiagnostic] - pub label: FieldIsPrivateLabel, + pub labels: Vec<FieldIsPrivateLabel>, + pub len: usize, } #[derive(Subdiagnostic)] @@ -21,7 +24,8 @@ pub(crate) enum FieldIsPrivateLabel { IsUpdateSyntax { #[primary_span] span: Span, - field_name: Symbol, + rest_field_names: String, + rest_len: usize, }, #[label(privacy_field_is_private_label)] Other { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index e484cfed06b..d19df08519d 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -24,10 +24,11 @@ use rustc_ast::MacroDef; use rustc_ast::visit::{VisitorResult, try_visit}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::intern::Interned; +use rustc_errors::MultiSpan; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId}; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind}; +use rustc_hir::intravisit::{self, InferKind, Visitor}; +use rustc_hir::{AmbigArg, AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind}; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; use rustc_middle::query::Providers; use rustc_middle::ty::print::PrintTraitRefExt as _; @@ -38,7 +39,7 @@ use rustc_middle::ty::{ use rustc_middle::{bug, span_bug}; use rustc_session::lint; use rustc_span::hygiene::Transparency; -use rustc_span::{Ident, Span, kw, sym}; +use rustc_span::{Ident, Span, Symbol, kw, sym}; use tracing::debug; use {rustc_attr_parsing as attr, rustc_hir as hir}; @@ -921,31 +922,95 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { &mut self, hir_id: hir::HirId, // ID of the field use use_ctxt: Span, // syntax context of the field name at the use site - span: Span, // span of the field pattern, e.g., `x: 0` def: ty::AdtDef<'tcx>, // definition of the struct or enum field: &'tcx ty::FieldDef, - in_update_syntax: bool, - ) { + ) -> bool { if def.is_enum() { - return; + return true; } // definition of the field let ident = Ident::new(kw::Empty, use_ctxt); let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1; - if !field.vis.is_accessible_from(def_id, self.tcx) { - self.tcx.dcx().emit_err(FieldIsPrivate { - span, - field_name: field.name, - variant_descr: def.variant_descr(), - def_path_str: self.tcx.def_path_str(def.did()), - label: if in_update_syntax { - FieldIsPrivateLabel::IsUpdateSyntax { span, field_name: field.name } - } else { - FieldIsPrivateLabel::Other { span } - }, - }); + !field.vis.is_accessible_from(def_id, self.tcx) + } + + // Checks that a field in a struct constructor (expression or pattern) is accessible. + fn emit_unreachable_field_error( + &mut self, + fields: Vec<(Symbol, Span, bool /* field is present */)>, + def: ty::AdtDef<'tcx>, // definition of the struct or enum + update_syntax: Option<Span>, + struct_span: Span, + ) { + if def.is_enum() || fields.is_empty() { + return; } + + // error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private + // --> $DIR/visibility.rs:18:13 + // | + // LL | let _x = Alpha { + // | ----- in this type # from `def` + // LL | beta: 0, + // | ^^^^^^^ private field # `fields.2` is `true` + // LL | .. + // | ^^ field `gamma` is private # `fields.2` is `false` + + // Get the list of all private fields for the main message. + let field_names: Vec<_> = fields.iter().map(|(name, _, _)| name).collect(); + let field_names = match &field_names[..] { + [] => return, + [name] => format!("`{name}`"), + [fields @ .., last] => format!( + "{} and `{last}`", + fields.iter().map(|f| format!("`{f}`")).collect::<Vec<_>>().join(", "), + ), + }; + let span: MultiSpan = fields.iter().map(|(_, span, _)| *span).collect::<Vec<Span>>().into(); + + // Get the list of all private fields when pointing at the `..rest`. + let rest_field_names: Vec<_> = + fields.iter().filter(|(_, _, is_present)| !is_present).map(|(n, _, _)| n).collect(); + let rest_len = rest_field_names.len(); + let rest_field_names = match &rest_field_names[..] { + [] => String::new(), + [name] => format!("`{name}`"), + [fields @ .., last] => format!( + "{} and `{last}`", + fields.iter().map(|f| format!("`{f}`")).collect::<Vec<_>>().join(", "), + ), + }; + // Get all the labels for each field or `..rest` in the primary MultiSpan. + let labels = fields + .iter() + .filter(|(_, _, is_present)| *is_present) + .map(|(_, span, _)| FieldIsPrivateLabel::Other { span: *span }) + .chain(update_syntax.iter().map(|span| FieldIsPrivateLabel::IsUpdateSyntax { + span: *span, + rest_field_names: rest_field_names.clone(), + rest_len, + })) + .collect(); + + self.tcx.dcx().emit_err(FieldIsPrivate { + span, + struct_span: if self + .tcx + .sess + .source_map() + .is_multiline(fields[0].1.between(struct_span)) + { + Some(struct_span) + } else { + None + }, + field_names: field_names.clone(), + variant_descr: def.variant_descr(), + def_path_str: self.tcx.def_path_str(def.did()), + labels, + len: fields.len(), + }); } fn check_expanded_fields( @@ -955,7 +1020,9 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { fields: &[hir::ExprField<'tcx>], hir_id: hir::HirId, span: Span, + struct_span: Span, ) { + let mut failed_fields = vec![]; for (vf_index, variant_field) in variant.fields.iter_enumerated() { let field = fields.iter().find(|f| self.typeck_results().field_index(f.hir_id) == vf_index); @@ -963,8 +1030,15 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { Some(field) => (field.hir_id, field.ident.span, field.span), None => (hir_id, span, span), }; - self.check_field(hir_id, use_ctxt, span, adt, variant_field, true); + if self.check_field(hir_id, use_ctxt, adt, variant_field) { + let name = match field { + Some(field) => field.ident.name, + None => variant_field.name, + }; + failed_fields.push((name, span, field.is_some())); + } } + self.emit_unreachable_field_error(failed_fields, adt, Some(span), struct_span); } } @@ -990,24 +1064,35 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { // If the expression uses FRU we need to make sure all the unmentioned fields // are checked for privacy (RFC 736). Rather than computing the set of // unmentioned fields, just check them all. - self.check_expanded_fields(adt, variant, fields, base.hir_id, base.span); + self.check_expanded_fields( + adt, + variant, + fields, + base.hir_id, + base.span, + qpath.span(), + ); } hir::StructTailExpr::DefaultFields(span) => { - self.check_expanded_fields(adt, variant, fields, expr.hir_id, span); + self.check_expanded_fields( + adt, + variant, + fields, + expr.hir_id, + span, + qpath.span(), + ); } hir::StructTailExpr::None => { + let mut failed_fields = vec![]; for field in fields { - let (hir_id, use_ctxt, span) = (field.hir_id, field.ident.span, field.span); + let (hir_id, use_ctxt) = (field.hir_id, field.ident.span); let index = self.typeck_results().field_index(field.hir_id); - self.check_field( - hir_id, - use_ctxt, - span, - adt, - &variant.fields[index], - false, - ); + if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) { + failed_fields.push((field.ident.name, field.ident.span, true)); + } } + self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span()); } } } @@ -1020,11 +1105,15 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { let res = self.typeck_results().qpath_res(qpath, pat.hir_id); let adt = self.typeck_results().pat_ty(pat).ty_adt_def().unwrap(); let variant = adt.variant_of_res(res); + let mut failed_fields = vec![]; for field in fields { - let (hir_id, use_ctxt, span) = (field.hir_id, field.ident.span, field.span); + let (hir_id, use_ctxt) = (field.hir_id, field.ident.span); let index = self.typeck_results().field_index(field.hir_id); - self.check_field(hir_id, use_ctxt, span, adt, &variant.fields[index], false); + if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) { + failed_fields.push((field.ident.name, field.ident.span, true)); + } } + self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span()); } intravisit::walk_pat(self, pat); @@ -1090,7 +1179,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { self.maybe_typeck_results = old_maybe_typeck_results; } - fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) { self.span = hir_ty.span; if self .visit( @@ -1106,12 +1195,17 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { intravisit::walk_ty(self, hir_ty); } - fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { - self.span = inf.span; + fn visit_infer( + &mut self, + inf_id: rustc_hir::HirId, + inf_span: Span, + _kind: InferKind<'tcx>, + ) -> Self::Result { + self.span = inf_span; if let Some(ty) = self .maybe_typeck_results - .unwrap_or_else(|| span_bug!(inf.span, "`hir::InferArg` outside of a body")) - .node_type_opt(inf.hir_id) + .unwrap_or_else(|| span_bug!(inf_span, "Inference variable outside of a body")) + .node_type_opt(inf_id) { if self.visit(ty).is_break() { return; @@ -1119,7 +1213,8 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { } else { // FIXME: check types of const infers here. } - intravisit::walk_inf(self, inf); + + self.visit_id(inf_id) } // Check types of expressions diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 3e179c61f39..a8c2aa98cd0 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -567,7 +567,7 @@ pub fn print_query_stack<Qcx: QueryContext>( qcx: Qcx, mut current_query: Option<QueryJobId>, dcx: DiagCtxtHandle<'_>, - num_frames: Option<usize>, + limit_frames: Option<usize>, mut file: Option<std::fs::File>, ) -> usize { // Be careful relying on global state here: this code is called from @@ -584,7 +584,7 @@ pub fn print_query_stack<Qcx: QueryContext>( let Some(query_info) = query_map.get(&query) else { break; }; - if Some(count_printed) < num_frames || num_frames.is_none() { + if Some(count_printed) < limit_frames || limit_frames.is_none() { // Only print to stderr as many stack frames as `num_frames` when present. // FIXME: needs translation #[allow(rustc::diagnostic_outside_of_impl)] @@ -615,5 +615,5 @@ pub fn print_query_stack<Qcx: QueryContext>( if let Some(ref mut file) = file { let _ = writeln!(file, "end of query stack"); } - count_printed + count_total } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3fe1eed243f..eec9e9a8515 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -645,10 +645,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let self_spans = items .iter() .filter_map(|(use_tree, _)| { - if let ast::UseTreeKind::Simple(..) = use_tree.kind { - if use_tree.ident().name == kw::SelfLower { - return Some(use_tree.span); - } + if let ast::UseTreeKind::Simple(..) = use_tree.kind + && use_tree.ident().name == kw::SelfLower + { + return Some(use_tree.span); } None @@ -947,19 +947,19 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let imported_binding = self.r.import(binding, import); if parent == self.r.graph_root { let ident = ident.normalize_to_macros_2_0(); - if let Some(entry) = self.r.extern_prelude.get(&ident) { - if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() { - self.r.dcx().emit_err( - errors::MacroExpandedExternCrateCannotShadowExternArguments { - span: item.span, - }, - ); - // `return` is intended to discard this binding because it's an - // unregistered ambiguity error which would result in a panic - // caused by inconsistency `path_res` - // more details: https://github.com/rust-lang/rust/pull/111761 - return; - } + if let Some(entry) = self.r.extern_prelude.get(&ident) + && expansion != LocalExpnId::ROOT + && orig_name.is_some() + && !entry.is_import() + { + self.r.dcx().emit_err( + errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span }, + ); + // `return` is intended to discard this binding because it's an + // unregistered ambiguity error which would result in a panic + // caused by inconsistency `path_res` + // more details: https://github.com/rust-lang/rust/pull/111761 + return; } let entry = self .r @@ -1040,10 +1040,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { span: item.span, }); } - if let ItemKind::ExternCrate(Some(orig_name)) = item.kind { - if orig_name == kw::SelfLower { - self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span }); - } + if let ItemKind::ExternCrate(Some(orig_name)) = item.kind + && orig_name == kw::SelfLower + { + self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span }); } let ill_formed = |span| { self.r.dcx().emit_err(errors::BadMacroImport { span }); @@ -1179,14 +1179,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { return Some((MacroKind::Bang, item.ident, item.span)); } else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) { return Some((MacroKind::Attr, item.ident, item.span)); - } else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive) { - if let Some(meta_item_inner) = + } else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive) + && let Some(meta_item_inner) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) - { - if let Some(ident) = meta_item_inner.ident() { - return Some((MacroKind::Derive, ident, ident.span)); - } - } + && let Some(ident) = meta_item_inner.ident() + { + return Some((MacroKind::Derive, ident, ident.span)); } None } diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 5a605df88c2..1c1e8494ffc 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -397,7 +397,7 @@ impl Resolver<'_, '_> { } ImportKind::ExternCrate { id, .. } => { let def_id = self.local_def_id(id); - if self.extern_crate_map.get(&def_id).map_or(true, |&cnum| { + if self.extern_crate_map.get(&def_id).is_none_or(|&cnum| { !tcx.is_compiler_builtins(cnum) && !tcx.is_panic_runtime(cnum) && !tcx.has_global_allocator(cnum) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index dc26d4de57a..8dc752c2cb3 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -24,13 +24,14 @@ use rustc_session::lint::builtin::{ MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, }; use rustc_session::lint::{AmbiguityErrorDiag, BuiltinLintDiag}; +use rustc_session::utils::was_invoked_from_cargo; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym}; use thin_vec::{ThinVec, thin_vec}; -use tracing::debug; +use tracing::{debug, instrument}; use crate::errors::{ self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive, @@ -225,10 +226,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let (name, span) = (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span)); - if let Some(s) = self.name_already_seen.get(&name) { - if s == &span { - return; - } + if self.name_already_seen.get(&name) == Some(&span) { + return; } let old_kind = match (ns, old_binding.module()) { @@ -322,7 +321,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id(); let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy(); let from_item = - self.extern_prelude.get(&ident).map_or(true, |entry| entry.introduced_by_item); + self.extern_prelude.get(&ident).is_none_or(|entry| entry.introduced_by_item); // Only suggest removing an import if both bindings are to the same def, if both spans // aren't dummy spans. Further, if both bindings are imports, then the ident must have // been introduced by an item. @@ -380,20 +379,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { suggestion = Some(format!("self as {suggested_name}")) } ImportKind::Single { source, .. } => { - if let Some(pos) = - source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize) + if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0) + && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span) + && pos as usize <= snippet.len() { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span) { - if pos <= snippet.len() { - span = binding_span - .with_lo(binding_span.lo() + BytePos(pos as u32)) - .with_hi( - binding_span.hi() - - BytePos(if snippet.ends_with(';') { 1 } else { 0 }), - ); - suggestion = Some(format!(" as {suggested_name}")); - } - } + span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi( + binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }), + ); + suggestion = Some(format!(" as {suggested_name}")); } } ImportKind::ExternCrate { source, target, .. } => { @@ -510,13 +503,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // If the first element of our path was actually resolved to an // `ExternCrate` (also used for `crate::...`) then no need to issue a // warning, this looks all good! - if let Some(binding) = second_binding { - if let NameBindingKind::Import { import, .. } = binding.kind { - // Careful: we still want to rewrite paths from renamed extern crates. - if let ImportKind::ExternCrate { source: None, .. } = import.kind { - return; - } - } + if let Some(binding) = second_binding + && let NameBindingKind::Import { import, .. } = binding.kind + // Careful: we still want to rewrite paths from renamed extern crates. + && let ImportKind::ExternCrate { source: None, .. } = import.kind + { + return; } let diag = BuiltinLintDiag::AbsPathWithModule(root_span); @@ -537,7 +529,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) { module.for_each_child(self, |_this, ident, _ns, binding| { let res = binding.res(); - if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == ident.span.ctxt()) { + if filter_fn(res) && ctxt.is_none_or(|ctxt| ctxt == ident.span.ctxt()) { names.push(TypoSuggestion::typo_from_ident(ident, res)); } }); @@ -685,7 +677,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if could_be_path { let import_suggestions = self.lookup_import_candidates( - Ident::with_dummy_span(name), + name, Namespace::ValueNS, &parent_scope, &|res: Res| { @@ -809,7 +801,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } err.multipart_suggestion(msg, suggestions, applicability); } - if let Some(ModuleOrUniformRoot::Module(module)) = module && let Some(module) = module.opt_def_id() && let Some(segment) = segment @@ -1047,20 +1038,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if filter_fn(res) { for derive in parent_scope.derives { let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; - if let Ok((Some(ext), _)) = this.resolve_macro_path( + let Ok((Some(ext), _)) = this.resolve_macro_path( derive, Some(MacroKind::Derive), parent_scope, false, false, None, - ) { - suggestions.extend( - ext.helper_attrs - .iter() - .map(|name| TypoSuggestion::typo_from_name(*name, res)), - ); - } + ) else { + continue; + }; + suggestions.extend( + ext.helper_attrs + .iter() + .map(|name| TypoSuggestion::typo_from_name(*name, res)), + ); } } } @@ -1215,12 +1207,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } // #90113: Do not count an inaccessible reexported item as a candidate. - if let NameBindingKind::Import { binding, .. } = name_binding.kind { - if this.is_accessible_from(binding.vis, parent_scope.module) - && !this.is_accessible_from(name_binding.vis, parent_scope.module) - { - return; - } + if let NameBindingKind::Import { binding, .. } = name_binding.kind + && this.is_accessible_from(binding.vis, parent_scope.module) + && !this.is_accessible_from(name_binding.vis, parent_scope.module) + { + return; } let res = name_binding.res(); @@ -1229,7 +1220,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => res.opt_def_id(), }; let child_doc_visible = doc_visible - && (did.map_or(true, |did| did.is_local() || !this.tcx.is_doc_hidden(did))); + && did.is_none_or(|did| did.is_local() || !this.tcx.is_doc_hidden(did)); // collect results based on the filter function // avoid suggesting anything from the same module in which we are resolving @@ -1253,14 +1244,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { segms.push(ast::PathSegment::from_ident(ident)); let path = Path { span: name_binding.span, segments: segms, tokens: None }; - if child_accessible { + if child_accessible // Remove invisible match if exists - if let Some(idx) = candidates + && let Some(idx) = candidates .iter() .position(|v: &ImportSuggestion| v.did == did && !v.accessible) - { - candidates.remove(idx); - } + { + candidates.remove(idx); } if candidates.iter().all(|v: &ImportSuggestion| v.did != did) { @@ -1373,48 +1363,50 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // otherwise cause duplicate suggestions. continue; } - let crate_id = self.crate_loader(|c| c.maybe_process_path_extern(ident.name)); - if let Some(crate_id) = crate_id { - let crate_def_id = crate_id.as_def_id(); - let crate_root = self.expect_module(crate_def_id); - - // Check if there's already an item in scope with the same name as the crate. - // If so, we have to disambiguate the potential import suggestions by making - // the paths *global* (i.e., by prefixing them with `::`). - let needs_disambiguation = - self.resolutions(parent_scope.module).borrow().iter().any( - |(key, name_resolution)| { - if key.ns == TypeNS - && key.ident == ident - && let Some(binding) = name_resolution.borrow().binding - { - match binding.res() { - // No disambiguation needed if the identically named item we - // found in scope actually refers to the crate in question. - Res::Def(_, def_id) => def_id != crate_def_id, - Res::PrimTy(_) => true, - _ => false, - } - } else { - false - } - }, - ); - let mut crate_path = ThinVec::new(); - if needs_disambiguation { - crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP)); - } - crate_path.push(ast::PathSegment::from_ident(ident)); + let Some(crate_id) = self.crate_loader(|c| c.maybe_process_path_extern(ident.name)) + else { + continue; + }; - suggestions.extend(self.lookup_import_candidates_from_module( - lookup_ident, - namespace, - parent_scope, - crate_root, - crate_path, - &filter_fn, - )); + let crate_def_id = crate_id.as_def_id(); + let crate_root = self.expect_module(crate_def_id); + + // Check if there's already an item in scope with the same name as the crate. + // If so, we have to disambiguate the potential import suggestions by making + // the paths *global* (i.e., by prefixing them with `::`). + let needs_disambiguation = + self.resolutions(parent_scope.module).borrow().iter().any( + |(key, name_resolution)| { + if key.ns == TypeNS + && key.ident == ident + && let Some(binding) = name_resolution.borrow().binding + { + match binding.res() { + // No disambiguation needed if the identically named item we + // found in scope actually refers to the crate in question. + Res::Def(_, def_id) => def_id != crate_def_id, + Res::PrimTy(_) => true, + _ => false, + } + } else { + false + } + }, + ); + let mut crate_path = ThinVec::new(); + if needs_disambiguation { + crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP)); } + crate_path.push(ast::PathSegment::from_ident(ident)); + + suggestions.extend(self.lookup_import_candidates_from_module( + lookup_ident, + namespace, + parent_scope, + crate_root, + crate_path, + &filter_fn, + )); } } @@ -1511,7 +1503,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }); } for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] { - if let Ok(binding) = self.early_resolve_ident_in_lexical_scope( + let Ok(binding) = self.early_resolve_ident_in_lexical_scope( ident, ScopeSet::All(ns), parent_scope, @@ -1519,53 +1511,53 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { false, None, None, - ) { - let desc = match binding.res() { - Res::Def(DefKind::Macro(MacroKind::Bang), _) => { - "a function-like macro".to_string() - } - Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => { - format!("an attribute: `#[{ident}]`") - } - Res::Def(DefKind::Macro(MacroKind::Derive), _) => { - format!("a derive macro: `#[derive({ident})]`") - } - Res::ToolMod => { - // Don't confuse the user with tool modules. - continue; - } - Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => { - "only a trait, without a derive macro".to_string() - } - res => format!( - "{} {}, not {} {}", - res.article(), - res.descr(), - macro_kind.article(), - macro_kind.descr_expected(), - ), - }; - if let crate::NameBindingKind::Import { import, .. } = binding.kind { - if !import.span.is_dummy() { - let note = errors::IdentImporterHereButItIsDesc { - span: import.span, - imported_ident: ident, - imported_ident_desc: &desc, - }; - err.subdiagnostic(note); - // Silence the 'unused import' warning we might get, - // since this diagnostic already covers that import. - self.record_use(ident, binding, Used::Other); - return; - } + ) else { + continue; + }; + + let desc = match binding.res() { + Res::Def(DefKind::Macro(MacroKind::Bang), _) => "a function-like macro".to_string(), + Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => { + format!("an attribute: `#[{ident}]`") + } + Res::Def(DefKind::Macro(MacroKind::Derive), _) => { + format!("a derive macro: `#[derive({ident})]`") } - let note = errors::IdentInScopeButItIsDesc { + Res::ToolMod => { + // Don't confuse the user with tool modules. + continue; + } + Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => { + "only a trait, without a derive macro".to_string() + } + res => format!( + "{} {}, not {} {}", + res.article(), + res.descr(), + macro_kind.article(), + macro_kind.descr_expected(), + ), + }; + if let crate::NameBindingKind::Import { import, .. } = binding.kind + && !import.span.is_dummy() + { + let note = errors::IdentImporterHereButItIsDesc { + span: import.span, imported_ident: ident, imported_ident_desc: &desc, }; err.subdiagnostic(note); + // Silence the 'unused import' warning we might get, + // since this diagnostic already covers that import. + self.record_use(ident, binding, Used::Other); return; } + let note = errors::IdentInScopeButItIsDesc { + imported_ident: ident, + imported_ident_desc: &desc, + }; + err.subdiagnostic(note); + return; } } @@ -1749,15 +1741,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// If the binding refers to a tuple struct constructor with fields, /// returns the span of its fields. fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> { - if let NameBindingKind::Res(Res::Def( + let NameBindingKind::Res(Res::Def( DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id, )) = binding.kind - { - let def_id = self.tcx.parent(ctor_def_id); - return self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to); // None for `struct Foo()` - } - None + else { + return None; + }; + + let def_id = self.tcx.parent(ctor_def_id); + self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) // None for `struct Foo()` } fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) { @@ -1983,10 +1976,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .collect::<Vec<_>>(); candidates.sort(); candidates.dedup(); - match find_best_match_for_name(&candidates, ident, None) { - Some(sugg) if sugg == ident => None, - sugg => sugg, - } + find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident) } pub(crate) fn report_path_resolution_error( @@ -2044,13 +2034,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { (format!("`_` is not a valid crate or module name"), None) } else if self.tcx.sess.is_rust_2015() { ( - format!("you might be missing crate `{ident}`"), + format!("use of unresolved module or unlinked crate `{ident}`"), Some(( vec![( self.current_crate_outer_attr_insert_span, format!("extern crate {ident};\n"), )], - format!("consider importing the `{ident}` crate"), + if was_invoked_from_cargo() { + format!( + "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \ + to add it to your `Cargo.toml` and import it in your code", + ) + } else { + format!( + "you might be missing a crate named `{ident}`, add it to your \ + project and import it in your code", + ) + }, Applicability::MaybeIncorrect, )), ) @@ -2229,20 +2229,37 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let descr = binding.res().descr(); (format!("{descr} `{ident}` is not a crate or module"), suggestion) } else { - (format!("use of undeclared crate or module `{ident}`"), suggestion) + let suggestion = if suggestion.is_some() { + suggestion + } else if was_invoked_from_cargo() { + Some(( + vec![], + format!( + "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \ + to add it to your `Cargo.toml`", + ), + Applicability::MaybeIncorrect, + )) + } else { + Some(( + vec![], + format!("you might be missing a crate named `{ident}`",), + Applicability::MaybeIncorrect, + )) + }; + (format!("use of unresolved module or unlinked crate `{ident}`"), suggestion) } } } /// Adds suggestions for a path that cannot be resolved. + #[instrument(level = "debug", skip(self, parent_scope))] pub(crate) fn make_path_suggestion( &mut self, span: Span, mut path: Vec<Segment>, parent_scope: &ParentScope<'ra>, ) -> Option<(Vec<Segment>, Option<String>)> { - debug!("make_path_suggestion: span={:?} path={:?}", span, path); - match (path.get(0), path.get(1)) { // `{{root}}::ident::...` on both editions. // On 2015 `{{root}}` is usually added implicitly. @@ -2271,6 +2288,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// LL | use foo::Bar; /// | ^^^ did you mean `self::foo`? /// ``` + #[instrument(level = "debug", skip(self, parent_scope))] fn make_missing_self_suggestion( &mut self, mut path: Vec<Segment>, @@ -2279,7 +2297,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Replace first ident with `self` and check if that is valid. path[0].ident.name = kw::SelfLower; let result = self.maybe_resolve_path(&path, None, parent_scope, None); - debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); + debug!(?path, ?result); if let PathResult::Module(..) = result { Some((path, None)) } else { None } } @@ -2290,6 +2308,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// LL | use foo::Bar; /// | ^^^ did you mean `crate::foo`? /// ``` + #[instrument(level = "debug", skip(self, parent_scope))] fn make_missing_crate_suggestion( &mut self, mut path: Vec<Segment>, @@ -2298,7 +2317,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = kw::Crate; let result = self.maybe_resolve_path(&path, None, parent_scope, None); - debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); + debug!(?path, ?result); if let PathResult::Module(..) = result { Some(( path, @@ -2321,6 +2340,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// LL | use foo::Bar; /// | ^^^ did you mean `super::foo`? /// ``` + #[instrument(level = "debug", skip(self, parent_scope))] fn make_missing_super_suggestion( &mut self, mut path: Vec<Segment>, @@ -2329,7 +2349,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = kw::Super; let result = self.maybe_resolve_path(&path, None, parent_scope, None); - debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); + debug!(?path, ?result); if let PathResult::Module(..) = result { Some((path, None)) } else { None } } @@ -2343,6 +2363,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// /// Used when importing a submodule of an external crate but missing that crate's /// name as the first part of path. + #[instrument(level = "debug", skip(self, parent_scope))] fn make_external_crate_suggestion( &mut self, mut path: Vec<Segment>, @@ -2363,10 +2384,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Replace first ident with a crate name and check if that is valid. path[0].ident.name = name; let result = self.maybe_resolve_path(&path, None, parent_scope, None); - debug!( - "make_external_crate_suggestion: name={:?} path={:?} result={:?}", - name, path, result - ); + debug!(?path, ?name, ?result); if let PathResult::Module(..) = result { return Some((path, None)); } @@ -2410,121 +2428,115 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let binding_key = BindingKey::new(ident, MacroNS); let resolution = resolutions.get(&binding_key)?; let binding = resolution.borrow().binding()?; - if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { - let module_name = crate_module.kind.name().unwrap(); - let import_snippet = match import.kind { - ImportKind::Single { source, target, .. } if source != target => { - format!("{source} as {target}") - } - _ => format!("{ident}"), - }; + let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() else { + return None; + }; + let module_name = crate_module.kind.name().unwrap(); + let import_snippet = match import.kind { + ImportKind::Single { source, target, .. } if source != target => { + format!("{source} as {target}") + } + _ => format!("{ident}"), + }; - let mut corrections: Vec<(Span, String)> = Vec::new(); - if !import.is_nested() { - // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove - // intermediate segments. - corrections.push((import.span, format!("{module_name}::{import_snippet}"))); - } else { - // Find the binding span (and any trailing commas and spaces). - // ie. `use a::b::{c, d, e};` - // ^^^ - let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding( - self.tcx.sess, - import.span, - import.use_span, - ); - debug!( - "check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}", - found_closing_brace, binding_span - ); + let mut corrections: Vec<(Span, String)> = Vec::new(); + if !import.is_nested() { + // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove + // intermediate segments. + corrections.push((import.span, format!("{module_name}::{import_snippet}"))); + } else { + // Find the binding span (and any trailing commas and spaces). + // ie. `use a::b::{c, d, e};` + // ^^^ + let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding( + self.tcx.sess, + import.span, + import.use_span, + ); + debug!(found_closing_brace, ?binding_span); + + let mut removal_span = binding_span; + + // If the binding span ended with a closing brace, as in the below example: + // ie. `use a::b::{c, d};` + // ^ + // Then expand the span of characters to remove to include the previous + // binding's trailing comma. + // ie. `use a::b::{c, d};` + // ^^^ + if found_closing_brace + && let Some(previous_span) = + extend_span_to_previous_binding(self.tcx.sess, binding_span) + { + debug!(?previous_span); + removal_span = removal_span.with_lo(previous_span.lo()); + } + debug!(?removal_span); - let mut removal_span = binding_span; - if found_closing_brace { - // If the binding span ended with a closing brace, as in the below example: - // ie. `use a::b::{c, d};` - // ^ - // Then expand the span of characters to remove to include the previous - // binding's trailing comma. - // ie. `use a::b::{c, d};` - // ^^^ - if let Some(previous_span) = - extend_span_to_previous_binding(self.tcx.sess, binding_span) - { - debug!("check_for_module_export_macro: previous_span={:?}", previous_span); - removal_span = removal_span.with_lo(previous_span.lo()); - } - } - debug!("check_for_module_export_macro: removal_span={:?}", removal_span); - - // Remove the `removal_span`. - corrections.push((removal_span, "".to_string())); - - // Find the span after the crate name and if it has nested imports immediately - // after the crate name already. - // ie. `use a::b::{c, d};` - // ^^^^^^^^^ - // or `use a::{b, c, d}};` - // ^^^^^^^^^^^ - let (has_nested, after_crate_name) = find_span_immediately_after_crate_name( - self.tcx.sess, - module_name, - import.use_span, - ); - debug!( - "check_for_module_export_macro: has_nested={:?} after_crate_name={:?}", - has_nested, after_crate_name - ); + // Remove the `removal_span`. + corrections.push((removal_span, "".to_string())); - let source_map = self.tcx.sess.source_map(); + // Find the span after the crate name and if it has nested imports immediately + // after the crate name already. + // ie. `use a::b::{c, d};` + // ^^^^^^^^^ + // or `use a::{b, c, d}};` + // ^^^^^^^^^^^ + let (has_nested, after_crate_name) = + find_span_immediately_after_crate_name(self.tcx.sess, module_name, import.use_span); + debug!(has_nested, ?after_crate_name); - // Make sure this is actually crate-relative. - let is_definitely_crate = import - .module_path - .first() - .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super); + let source_map = self.tcx.sess.source_map(); - // Add the import to the start, with a `{` if required. - let start_point = source_map.start_point(after_crate_name); - if is_definitely_crate - && let Ok(start_snippet) = source_map.span_to_snippet(start_point) - { - corrections.push(( - start_point, - if has_nested { - // In this case, `start_snippet` must equal '{'. - format!("{start_snippet}{import_snippet}, ") - } else { - // In this case, add a `{`, then the moved import, then whatever - // was there before. - format!("{{{import_snippet}, {start_snippet}") - }, - )); + // Make sure this is actually crate-relative. + let is_definitely_crate = import + .module_path + .first() + .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super); - // Add a `};` to the end if nested, matching the `{` added at the start. - if !has_nested { - corrections - .push((source_map.end_point(after_crate_name), "};".to_string())); - } - } else { - // If the root import is module-relative, add the import separately - corrections.push(( - import.use_span.shrink_to_lo(), - format!("use {module_name}::{import_snippet};\n"), - )); + // Add the import to the start, with a `{` if required. + let start_point = source_map.start_point(after_crate_name); + if is_definitely_crate + && let Ok(start_snippet) = source_map.span_to_snippet(start_point) + { + corrections.push(( + start_point, + if has_nested { + // In this case, `start_snippet` must equal '{'. + format!("{start_snippet}{import_snippet}, ") + } else { + // In this case, add a `{`, then the moved import, then whatever + // was there before. + format!("{{{import_snippet}, {start_snippet}") + }, + )); + + // Add a `};` to the end if nested, matching the `{` added at the start. + if !has_nested { + corrections.push((source_map.end_point(after_crate_name), "};".to_string())); } + } else { + // If the root import is module-relative, add the import separately + corrections.push(( + import.use_span.shrink_to_lo(), + format!("use {module_name}::{import_snippet};\n"), + )); } + } - let suggestion = Some(( - corrections, - String::from("a macro with this name exists at the root of the crate"), - Applicability::MaybeIncorrect, - )); - Some((suggestion, Some("this could be because a macro annotated with `#[macro_export]` will be exported \ + let suggestion = Some(( + corrections, + String::from("a macro with this name exists at the root of the crate"), + Applicability::MaybeIncorrect, + )); + Some(( + suggestion, + Some( + "this could be because a macro annotated with `#[macro_export]` will be exported \ at the root of the crate instead of the module where it is defined" - .to_string()))) - } else { - None - } + .to_string(), + ), + )) } /// Finds a cfg-ed out item inside `module` with the matching name. @@ -2677,15 +2689,12 @@ fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option /// use foo::{a, b::{c, d}}; /// // ^^^^^^^^^^^^^^^ -- true /// ``` +#[instrument(level = "debug", skip(sess))] fn find_span_immediately_after_crate_name( sess: &Session, module_name: Symbol, use_span: Span, ) -> (bool, Span) { - debug!( - "find_span_immediately_after_crate_name: module_name={:?} use_span={:?}", - module_name, use_span - ); let source_map = sess.source_map(); // Using `use issue_59764::foo::{baz, makro};` as an example throughout.. @@ -3051,7 +3060,6 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder { self.first_legal_span = Some(inject); } self.first_use_span = search_for_any_use_in_items(&c.items); - return; } else { visit::walk_crate(self, c); } @@ -3065,7 +3073,6 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder { self.first_legal_span = Some(inject); } self.first_use_span = search_for_any_use_in_items(items); - return; } } else { visit::walk_item(self, item); @@ -3075,16 +3082,16 @@ impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder { fn search_for_any_use_in_items(items: &[P<ast::Item>]) -> Option<Span> { for item in items { - if let ItemKind::Use(..) = item.kind { - if is_span_suitable_for_use_injection(item.span) { - let mut lo = item.span.lo(); - for attr in &item.attrs { - if attr.span.eq_ctxt(item.span) { - lo = std::cmp::min(lo, attr.span.lo()); - } + if let ItemKind::Use(..) = item.kind + && is_span_suitable_for_use_injection(item.span) + { + let mut lo = item.span.lo(); + for attr in &item.attrs { + if attr.span.eq_ctxt(item.span) { + lo = std::cmp::min(lo, attr.span.lo()); } - return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent())); } + return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent())); } } None diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index e279d14704e..6ef4aa40725 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -118,37 +118,38 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { let resolutions = self.r.resolutions(module); for (_, name_resolution) in resolutions.borrow().iter() { - if let Some(mut binding) = name_resolution.borrow().binding() { - // Set the given effective visibility level to `Level::Direct` and - // sets the rest of the `use` chain to `Level::Reexported` until - // we hit the actual exported item. - // - // If the binding is ambiguous, put the root ambiguity binding and all reexports - // leading to it into the table. They are used by the `ambiguous_glob_reexports` - // lint. For all bindings added to the table this way `is_ambiguity` returns true. - let is_ambiguity = - |binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn; - let mut parent_id = ParentId::Def(module_id); - let mut warn_ambiguity = binding.warn_ambiguity; - while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { - self.update_import(binding, parent_id); + let Some(mut binding) = name_resolution.borrow().binding() else { + continue; + }; + // Set the given effective visibility level to `Level::Direct` and + // sets the rest of the `use` chain to `Level::Reexported` until + // we hit the actual exported item. + // + // If the binding is ambiguous, put the root ambiguity binding and all reexports + // leading to it into the table. They are used by the `ambiguous_glob_reexports` + // lint. For all bindings added to the table this way `is_ambiguity` returns true. + let is_ambiguity = + |binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn; + let mut parent_id = ParentId::Def(module_id); + let mut warn_ambiguity = binding.warn_ambiguity; + while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { + self.update_import(binding, parent_id); - if is_ambiguity(binding, warn_ambiguity) { - // Stop at the root ambiguity, further bindings in the chain should not - // be reexported because the root ambiguity blocks any access to them. - // (Those further bindings are most likely not ambiguities themselves.) - break; - } - - parent_id = ParentId::Import(binding); - binding = nested_binding; - warn_ambiguity |= nested_binding.warn_ambiguity; - } - if !is_ambiguity(binding, warn_ambiguity) - && let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) - { - self.update_def(def_id, binding.vis.expect_local(), parent_id); + if is_ambiguity(binding, warn_ambiguity) { + // Stop at the root ambiguity, further bindings in the chain should not + // be reexported because the root ambiguity blocks any access to them. + // (Those further bindings are most likely not ambiguities themselves.) + break; } + + parent_id = ParentId::Import(binding); + binding = nested_binding; + warn_ambiguity |= nested_binding.warn_ambiguity; + } + if !is_ambiguity(binding, warn_ambiguity) + && let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) + { + self.update_def(def_id, binding.vis.expect_local(), parent_id); } } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 3bfe98f7091..7eb795034b0 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -59,7 +59,7 @@ pub(crate) struct NameAlreadyUsedInParameterList { pub(crate) span: Span, #[label(resolve_first_use_of_name)] pub(crate) first_use_span: Span, - pub(crate) name: Symbol, + pub(crate) name: Ident, } #[derive(Diagnostic)] @@ -142,7 +142,7 @@ pub(crate) struct VariableBoundWithDifferentMode { pub(crate) span: Span, #[label(resolve_first_binding_span)] pub(crate) first_binding_span: Span, - pub(crate) variable_name: Symbol, + pub(crate) variable_name: Ident, } #[derive(Diagnostic)] @@ -151,7 +151,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInParameterList { #[primary_span] #[label] pub(crate) span: Span, - pub(crate) identifier: Symbol, + pub(crate) identifier: Ident, } #[derive(Diagnostic)] @@ -160,7 +160,7 @@ pub(crate) struct IdentifierBoundMoreThanOnceInSamePattern { #[primary_span] #[label] pub(crate) span: Span, - pub(crate) identifier: Symbol, + pub(crate) identifier: Ident, } #[derive(Diagnostic)] @@ -478,7 +478,7 @@ pub(crate) struct TraitImplDuplicate { pub(crate) old_span: Span, #[label(resolve_trait_item_span)] pub(crate) trait_item_span: Span, - pub(crate) name: Symbol, + pub(crate) name: Ident, } #[derive(Diagnostic)] @@ -976,7 +976,7 @@ pub(crate) struct AttemptToDefineBuiltinMacroTwice { pub(crate) struct VariableIsNotBoundInAllPatterns { #[primary_span] pub(crate) multispan: MultiSpan, - pub(crate) name: Symbol, + pub(crate) name: Ident, } #[derive(Subdiagnostic, Debug, Clone)] @@ -984,7 +984,7 @@ pub(crate) struct VariableIsNotBoundInAllPatterns { pub(crate) struct PatternDoesntBindName { #[primary_span] pub(crate) span: Span, - pub(crate) name: Symbol, + pub(crate) name: Ident, } #[derive(Subdiagnostic, Debug, Clone)] @@ -1260,7 +1260,7 @@ pub(crate) struct TraitImplMismatch { #[primary_span] #[label] pub(crate) span: Span, - pub(crate) name: Symbol, + pub(crate) name: Ident, pub(crate) kind: &'static str, pub(crate) trait_path: String, #[label(resolve_trait_impl_mismatch_label_item)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 45e87edc53e..a3d3e87ade0 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -246,23 +246,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // ---- end // ``` // So we have to fall back to the module's parent during lexical resolution in this case. - if derive_fallback_lint_id.is_some() { - if let Some(parent) = module.parent { - // Inner module is inside the macro, parent module is outside of the macro. - if module.expansion != parent.expansion - && module.expansion.is_descendant_of(parent.expansion) - { - // The macro is a proc macro derive - if let Some(def_id) = module.expansion.expn_data().macro_def_id { - let ext = &self.get_macro_by_def_id(def_id).ext; - if ext.builtin_name.is_none() - && ext.macro_kind() == MacroKind::Derive - && parent.expansion.outer_expn_is_descendant_of(*ctxt) - { - return Some((parent, derive_fallback_lint_id)); - } - } - } + if derive_fallback_lint_id.is_some() + && let Some(parent) = module.parent + // Inner module is inside the macro + && module.expansion != parent.expansion + // Parent module is outside of the macro + && module.expansion.is_descendant_of(parent.expansion) + // The macro is a proc macro derive + && let Some(def_id) = module.expansion.expn_data().macro_def_id + { + let ext = &self.get_macro_by_def_id(def_id).ext; + if ext.builtin_name.is_none() + && ext.macro_kind() == MacroKind::Derive + && parent.expansion.outer_expn_is_descendant_of(*ctxt) + { + return Some((parent, derive_fallback_lint_id)); } } @@ -593,8 +591,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }, Scope::StdLibPrelude => { let mut result = Err(Determinacy::Determined); - if let Some(prelude) = this.prelude { - if let Ok(binding) = this.resolve_ident_in_module_unadjusted( + if let Some(prelude) = this.prelude + && let Ok(binding) = this.resolve_ident_in_module_unadjusted( ModuleOrUniformRoot::Module(prelude), ident, ns, @@ -603,14 +601,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None, ignore_binding, ignore_import, - ) { - if matches!(use_prelude, UsePrelude::Yes) - || this.is_builtin_macro(binding.res()) - { - result = Ok((binding, Flags::MISC_FROM_PRELUDE)); - } - } + ) + && (matches!(use_prelude, UsePrelude::Yes) + || this.is_builtin_macro(binding.res())) + { + result = Ok((binding, Flags::MISC_FROM_PRELUDE)); } + result } Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) { @@ -939,10 +936,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; // Items and single imports are not shadowable, if we have one, then it's determined. - if let Some(binding) = binding { - if !binding.is_glob_import() { - return check_usable(self, binding); - } + if let Some(binding) = binding + && !binding.is_glob_import() + { + return check_usable(self, binding); } // --- From now on we either have a glob resolution or no resolution. --- @@ -1437,13 +1434,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() { debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id); let record_segment_res = |this: &mut Self, res| { - if finalize.is_some() { - if let Some(id) = id { - if !this.partial_res_map.contains_key(&id) { - assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); - this.record_partial_res(id, PartialRes::new(res)); - } - } + if finalize.is_some() + && let Some(id) = id + && !this.partial_res_map.contains_key(&id) + { + assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id"); + this.record_partial_res(id, PartialRes::new(res)); } }; @@ -1463,13 +1459,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { _ => None, }, }; - if let Some(self_module) = self_module { - if let Some(parent) = self_module.parent { - module = Some(ModuleOrUniformRoot::Module( - self.resolve_self(&mut ctxt, parent), - )); - continue; - } + if let Some(self_module) = self_module + && let Some(parent) = self_module.parent + { + module = + Some(ModuleOrUniformRoot::Module(self.resolve_self(&mut ctxt, parent))); + continue; } return PathResult::failed( ident, @@ -1644,13 +1639,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } Err(Undetermined) => return PathResult::Indeterminate, Err(Determined) => { - if let Some(ModuleOrUniformRoot::Module(module)) = module { - if opt_ns.is_some() && !module.is_normal() { - return PathResult::NonModule(PartialRes::with_unresolved_segments( - module.res().unwrap(), - path.len() - segment_idx, - )); - } + if let Some(ModuleOrUniformRoot::Module(module)) = module + && opt_ns.is_some() + && !module.is_normal() + { + return PathResult::NonModule(PartialRes::with_unresolved_segments( + module.res().unwrap(), + path.len() - segment_idx, + )); } return PathResult::failed( diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index cad45d3c293..d555c938770 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -287,12 +287,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { binding.vis }; - if let ImportKind::Glob { ref max_vis, .. } = import.kind { - if vis == import_vis - || max_vis.get().map_or(true, |max_vis| vis.is_at_least(max_vis, self.tcx)) - { - max_vis.set(Some(vis.expect_local())) - } + if let ImportKind::Glob { ref max_vis, .. } = import.kind + && (vis == import_vis + || max_vis.get().is_none_or(|max_vis| vis.is_at_least(max_vis, self.tcx))) + { + max_vis.set(Some(vis.expect_local())) } self.arenas.alloc_name_binding(NameBindingData { @@ -543,31 +542,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // resolution for it so that later resolve stages won't complain. self.import_dummy_binding(*import, is_indeterminate); - if let Some(err) = unresolved_import_error { - glob_error |= import.is_glob(); + let Some(err) = unresolved_import_error else { continue }; - if let ImportKind::Single { source, ref source_bindings, .. } = import.kind { - if source.name == kw::SelfLower { - // Silence `unresolved import` error if E0429 is already emitted - if let Err(Determined) = source_bindings.value_ns.get() { - continue; - } - } - } + glob_error |= import.is_glob(); - if prev_root_id != NodeId::ZERO - && prev_root_id != import.root_id - && !errors.is_empty() - { - // In the case of a new import line, throw a diagnostic message - // for the previous line. - self.throw_unresolved_import_error(errors, glob_error); - errors = vec![]; - } - if seen_spans.insert(err.span) { - errors.push((*import, err)); - prev_root_id = import.root_id; - } + if let ImportKind::Single { source, ref source_bindings, .. } = import.kind + && source.name == kw::SelfLower + // Silence `unresolved import` error if E0429 is already emitted + && let Err(Determined) = source_bindings.value_ns.get() + { + continue; + } + + if prev_root_id != NodeId::ZERO && prev_root_id != import.root_id && !errors.is_empty() + { + // In the case of a new import line, throw a diagnostic message + // for the previous line. + self.throw_unresolved_import_error(errors, glob_error); + errors = vec![]; + } + if seen_spans.insert(err.span) { + errors.push((*import, err)); + prev_root_id = import.root_id; } } @@ -609,60 +605,60 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { for (key, resolution) in self.resolutions(*module).borrow().iter() { let resolution = resolution.borrow(); - if let Some(binding) = resolution.binding { - if let NameBindingKind::Import { import, .. } = binding.kind - && let Some((amb_binding, _)) = binding.ambiguity - && binding.res() != Res::Err - && exported_ambiguities.contains(&binding) + let Some(binding) = resolution.binding else { continue }; + + if let NameBindingKind::Import { import, .. } = binding.kind + && let Some((amb_binding, _)) = binding.ambiguity + && binding.res() != Res::Err + && exported_ambiguities.contains(&binding) + { + self.lint_buffer.buffer_lint( + AMBIGUOUS_GLOB_REEXPORTS, + import.root_id, + import.root_span, + BuiltinLintDiag::AmbiguousGlobReexports { + name: key.ident.to_string(), + namespace: key.ns.descr().to_string(), + first_reexport_span: import.root_span, + duplicate_reexport_span: amb_binding.span, + }, + ); + } + + if let Some(glob_binding) = resolution.shadowed_glob { + let binding_id = match binding.kind { + NameBindingKind::Res(res) => { + Some(self.def_id_to_node_id[res.def_id().expect_local()]) + } + NameBindingKind::Module(module) => { + Some(self.def_id_to_node_id[module.def_id().expect_local()]) + } + NameBindingKind::Import { import, .. } => import.id(), + }; + + if binding.res() != Res::Err + && glob_binding.res() != Res::Err + && let NameBindingKind::Import { import: glob_import, .. } = + glob_binding.kind + && let Some(binding_id) = binding_id + && let Some(glob_import_id) = glob_import.id() + && let glob_import_def_id = self.local_def_id(glob_import_id) + && self.effective_visibilities.is_exported(glob_import_def_id) + && glob_binding.vis.is_public() + && !binding.vis.is_public() { self.lint_buffer.buffer_lint( - AMBIGUOUS_GLOB_REEXPORTS, - import.root_id, - import.root_span, - BuiltinLintDiag::AmbiguousGlobReexports { - name: key.ident.to_string(), - namespace: key.ns.descr().to_string(), - first_reexport_span: import.root_span, - duplicate_reexport_span: amb_binding.span, + HIDDEN_GLOB_REEXPORTS, + binding_id, + binding.span, + BuiltinLintDiag::HiddenGlobReexports { + name: key.ident.name.to_string(), + namespace: key.ns.descr().to_owned(), + glob_reexport_span: glob_binding.span, + private_item_span: binding.span, }, ); } - - if let Some(glob_binding) = resolution.shadowed_glob { - let binding_id = match binding.kind { - NameBindingKind::Res(res) => { - Some(self.def_id_to_node_id[res.def_id().expect_local()]) - } - NameBindingKind::Module(module) => { - Some(self.def_id_to_node_id[module.def_id().expect_local()]) - } - NameBindingKind::Import { import, .. } => import.id(), - }; - - if binding.res() != Res::Err - && glob_binding.res() != Res::Err - && let NameBindingKind::Import { import: glob_import, .. } = - glob_binding.kind - && let Some(binding_id) = binding_id - && let Some(glob_import_id) = glob_import.id() - && let glob_import_def_id = self.local_def_id(glob_import_id) - && self.effective_visibilities.is_exported(glob_import_def_id) - && glob_binding.vis.is_public() - && !binding.vis.is_public() - { - self.lint_buffer.buffer_lint( - HIDDEN_GLOB_REEXPORTS, - binding_id, - binding.span, - BuiltinLintDiag::HiddenGlobReexports { - name: key.ident.name.to_string(), - namespace: key.ns.descr().to_owned(), - glob_reexport_span: glob_binding.span, - private_item_span: binding.span, - }, - ); - } - } } } } @@ -1006,21 +1002,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.lint_if_path_starts_with_module(Some(finalize), &full_path, None); } - if let ModuleOrUniformRoot::Module(module) = module { - if module == import.parent_scope.module { - // Importing a module into itself is not allowed. - return Some(UnresolvedImportError { - span: import.span, - label: Some(String::from( - "cannot glob-import a module into itself", - )), - note: None, - suggestion: None, - candidates: None, - segment: None, - module: None, - }); - } + if let ModuleOrUniformRoot::Module(module) = module + && module == import.parent_scope.module + { + // Importing a module into itself is not allowed. + return Some(UnresolvedImportError { + span: import.span, + label: Some(String::from("cannot glob-import a module into itself")), + note: None, + suggestion: None, + candidates: None, + segment: None, + module: None, + }); } if !is_prelude && let Some(max_vis) = max_vis.get() @@ -1081,18 +1075,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Consistency checks, analogous to `finalize_macro_resolutions`. let initial_res = source_bindings[ns].get().map(|initial_binding| { all_ns_err = false; - if let Some(target_binding) = target_bindings[ns].get() { - if target.name == kw::Underscore - && initial_binding.is_extern_crate() - && !initial_binding.is_import() - { - let used = if import.module_path.is_empty() { - Used::Scope - } else { - Used::Other - }; - this.record_use(ident, target_binding, used); - } + if let Some(target_binding) = target_bindings[ns].get() + && target.name == kw::Underscore + && initial_binding.is_extern_crate() + && !initial_binding.is_import() + { + let used = if import.module_path.is_empty() { + Used::Scope + } else { + Used::Other + }; + this.record_use(ident, target_binding, used); } initial_binding.res() }); @@ -1247,17 +1240,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut any_successful_reexport = false; let mut crate_private_reexport = false; self.per_ns(|this, ns| { - if let Ok(binding) = source_bindings[ns].get() { - if !binding.vis.is_at_least(import.vis, this.tcx) { - reexport_error = Some((ns, binding)); - if let ty::Visibility::Restricted(binding_def_id) = binding.vis { - if binding_def_id.is_top_level_module() { - crate_private_reexport = true; - } - } - } else { - any_successful_reexport = true; + let Ok(binding) = source_bindings[ns].get() else { + return; + }; + + if !binding.vis.is_at_least(import.vis, this.tcx) { + reexport_error = Some((ns, binding)); + if let ty::Visibility::Restricted(binding_def_id) = binding.vis + && binding_def_id.is_top_level_module() + { + crate_private_reexport = true; } + } else { + any_successful_reexport = true; } }); @@ -1474,28 +1469,28 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Since import resolution is finished, globs will not define any more names. *module.globs.borrow_mut() = Vec::new(); - if let Some(def_id) = module.opt_def_id() { - let mut children = Vec::new(); - - module.for_each_child(self, |this, ident, _, binding| { - let res = binding.res().expect_non_local(); - let error_ambiguity = binding.is_ambiguity_recursive() && !binding.warn_ambiguity; - if res != def::Res::Err && !error_ambiguity { - let mut reexport_chain = SmallVec::new(); - let mut next_binding = binding; - while let NameBindingKind::Import { binding, import, .. } = next_binding.kind { - reexport_chain.push(import.simplify(this)); - next_binding = binding; - } + let Some(def_id) = module.opt_def_id() else { return }; + + let mut children = Vec::new(); - children.push(ModChild { ident, res, vis: binding.vis, reexport_chain }); + module.for_each_child(self, |this, ident, _, binding| { + let res = binding.res().expect_non_local(); + let error_ambiguity = binding.is_ambiguity_recursive() && !binding.warn_ambiguity; + if res != def::Res::Err && !error_ambiguity { + let mut reexport_chain = SmallVec::new(); + let mut next_binding = binding; + while let NameBindingKind::Import { binding, import, .. } = next_binding.kind { + reexport_chain.push(import.simplify(this)); + next_binding = binding; } - }); - if !children.is_empty() { - // Should be fine because this code is only called for local modules. - self.module_children.insert(def_id.expect_local(), children); + children.push(ModChild { ident, res, vis: binding.vis, reexport_chain }); } + }); + + if !children.is_empty() { + // Should be fine because this code is only called for local modules. + self.module_children.insert(def_id.expect_local(), children); } } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1a0292ebbde..68d3351f174 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -468,16 +468,12 @@ impl<'a> PathSource<'a> { { "external crate" } - ExprKind::Path(_, path) => { - let mut msg = "function"; - if let Some(segment) = path.segments.iter().last() { - if let Some(c) = segment.ident.to_string().chars().next() { - if c.is_uppercase() { - msg = "function, tuple struct or tuple variant"; - } - } - } - msg + ExprKind::Path(_, path) + if let Some(segment) = path.segments.last() + && let Some(c) = segment.ident.to_string().chars().next() + && c.is_uppercase() => + { + "function, tuple struct or tuple variant" } _ => "function", }, @@ -612,7 +608,7 @@ impl MaybeExported<'_> { return vis.kind.is_pub(); } }; - def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id)) + def_id.is_none_or(|def_id| r.effective_visibilities.is_exported(def_id)) } } @@ -1182,32 +1178,27 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r // namespace first, and if that fails we try again in the value namespace. If // resolution in the value namespace succeeds, we have an generic const argument on // our hands. - if let TyKind::Path(None, ref path) = ty.kind { + if let TyKind::Path(None, ref path) = ty.kind // We cannot disambiguate multi-segment paths right now as that requires type // checking. - if path.is_potential_trivial_const_arg() { - let mut check_ns = |ns| { - self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns) - .is_some() - }; - if !check_ns(TypeNS) && check_ns(ValueNS) { - self.resolve_anon_const_manual( - true, - AnonConstKind::ConstArg(IsRepeatExpr::No), - |this| { - this.smart_resolve_path( - ty.id, - &None, - path, - PathSource::Expr(None), - ); - this.visit_path(path, ty.id); - }, - ); + && path.is_potential_trivial_const_arg() + { + let mut check_ns = |ns| { + self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns) + .is_some() + }; + if !check_ns(TypeNS) && check_ns(ValueNS) { + self.resolve_anon_const_manual( + true, + AnonConstKind::ConstArg(IsRepeatExpr::No), + |this| { + this.smart_resolve_path(ty.id, &None, path, PathSource::Expr(None)); + this.visit_path(path, ty.id); + }, + ); - self.diag_metadata.currently_processing_generic_args = prev; - return; - } + self.diag_metadata.currently_processing_generic_args = prev; + return; } } @@ -1243,54 +1234,56 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r } fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) { - if let Some(ref args) = path_segment.args { - match &**args { - GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, args), - GenericArgs::Parenthesized(p_args) => { - // Probe the lifetime ribs to know how to behave. - for rib in self.lifetime_ribs.iter().rev() { - match rib.kind { - // We are inside a `PolyTraitRef`. The lifetimes are - // to be introduced in that (maybe implicit) `for<>` binder. - LifetimeRibKind::Generics { - binder, - kind: LifetimeBinderKind::PolyTrait, - .. - } => { - self.with_lifetime_rib( - LifetimeRibKind::AnonymousCreateParameter { + let Some(ref args) = path_segment.args else { + return; + }; + + match &**args { + GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, args), + GenericArgs::Parenthesized(p_args) => { + // Probe the lifetime ribs to know how to behave. + for rib in self.lifetime_ribs.iter().rev() { + match rib.kind { + // We are inside a `PolyTraitRef`. The lifetimes are + // to be introduced in that (maybe implicit) `for<>` binder. + LifetimeRibKind::Generics { + binder, + kind: LifetimeBinderKind::PolyTrait, + .. + } => { + self.with_lifetime_rib( + LifetimeRibKind::AnonymousCreateParameter { + binder, + report_in_path: false, + }, + |this| { + this.resolve_fn_signature( binder, - report_in_path: false, - }, - |this| { - this.resolve_fn_signature( - binder, - false, - p_args.inputs.iter().map(|ty| (None, &**ty)), - &p_args.output, - ) - }, - ); - break; - } - // We have nowhere to introduce generics. Code is malformed, - // so use regular lifetime resolution to avoid spurious errors. - LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => { - visit::walk_generic_args(self, args); - break; - } - LifetimeRibKind::AnonymousCreateParameter { .. } - | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } - | LifetimeRibKind::Elided(_) - | LifetimeRibKind::ElisionFailure - | LifetimeRibKind::ConcreteAnonConst(_) - | LifetimeRibKind::ConstParamTy => {} + false, + p_args.inputs.iter().map(|ty| (None, &**ty)), + &p_args.output, + ) + }, + ); + break; + } + // We have nowhere to introduce generics. Code is malformed, + // so use regular lifetime resolution to avoid spurious errors. + LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => { + visit::walk_generic_args(self, args); + break; } + LifetimeRibKind::AnonymousCreateParameter { .. } + | LifetimeRibKind::AnonymousReportError + | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } + | LifetimeRibKind::Elided(_) + | LifetimeRibKind::ElisionFailure + | LifetimeRibKind::ConcreteAnonConst(_) + | LifetimeRibKind::ConstParamTy => {} } } - GenericArgs::ParenthesizedElided(_) => {} } + GenericArgs::ParenthesizedElided(_) => {} } } @@ -1735,13 +1728,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } let normalized_ident = ident.normalize_to_macros_2_0(); - let mut outer_res = None; - for rib in lifetime_rib_iter { - if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) { - outer_res = Some(outer); - break; - } - } + let outer_res = lifetime_rib_iter + .find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer)); self.emit_undeclared_lifetime_error(lifetime, outer_res); self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named); @@ -1808,23 +1796,21 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } LifetimeRibKind::AnonymousReportError => { if elided { - let mut suggestion = None; - for rib in self.lifetime_ribs[i..].iter().rev() { + let suggestion = self.lifetime_ribs[i..].iter().rev().find_map(|rib| { if let LifetimeRibKind::Generics { span, kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound, .. - } = &rib.kind + } = rib.kind { - suggestion = - Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion { - lo: span.shrink_to_lo(), - hi: lifetime.ident.span.shrink_to_hi(), - }); - break; + Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion { + lo: span.shrink_to_lo(), + hi: lifetime.ident.span.shrink_to_hi(), + }) + } else { + None } - } - + }); // are we trying to use an anonymous lifetime // on a non GAT associated trait type? if !self.in_func_body @@ -2460,12 +2446,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { for i in (0..self.label_ribs.len()).rev() { let rib = &self.label_ribs[i]; - if let RibKind::MacroDefinition(def) = rib.kind { + if let RibKind::MacroDefinition(def) = rib.kind // If an invocation of this macro created `ident`, give up on `ident` // and switch to `ident`'s source from the macro definition. - if def == self.r.macro_def(label.span.ctxt()) { - label.span.remove_mark(); - } + && def == self.r.macro_def(label.span.ctxt()) + { + label.span.remove_mark(); } let ident = label.normalize_to_macro_rules(); @@ -2493,14 +2479,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// Determine whether or not a label from the `rib_index`th label rib is reachable. fn is_label_valid_from_rib(&self, rib_index: usize) -> bool { let ribs = &self.label_ribs[rib_index + 1..]; - - for rib in ribs { - if rib.kind.is_label_barrier() { - return false; - } - } - - true + ribs.iter().all(|rib| !rib.kind.is_label_barrier()) } fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) { @@ -2856,7 +2835,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { match seen_bindings.entry(ident) { Entry::Occupied(entry) => { let span = *entry.get(); - let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span); + let err = ResolutionError::NameAlreadyUsedInParameterList(ident, span); self.report_error(param.ident.span, err); let rib = match param.kind { GenericParamKind::Lifetime => { @@ -3443,7 +3422,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { match seen_trait_items.entry(id_in_trait) { Entry::Occupied(entry) => { self.report_error(span, ResolutionError::TraitImplDuplicate { - name: ident.name, + name: ident, old_span: *entry.get(), trait_item_span: binding.span, }); @@ -3478,7 +3457,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }; let trait_path = path_names_to_string(path); self.report_error(span, ResolutionError::TraitImplMismatch { - name: ident.name, + name: ident, kind, code, trait_path, @@ -3505,21 +3484,20 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.visit_ty(&qself.ty); } self.visit_path(&delegation.path, delegation.id); - if let Some(body) = &delegation.body { - self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| { - // `PatBoundCtx` is not necessary in this context - let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; - - let span = delegation.path.segments.last().unwrap().ident.span; - this.fresh_binding( - Ident::new(kw::SelfLower, span), - delegation.id, - PatternSource::FnParam, - &mut bindings, - ); - this.visit_block(body); - }); - } + let Some(body) = &delegation.body else { return }; + self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| { + // `PatBoundCtx` is not necessary in this context + let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())]; + + let span = delegation.path.segments.last().unwrap().ident.span; + this.fresh_binding( + Ident::new(kw::SelfLower, span), + delegation.id, + PatternSource::FnParam, + &mut bindings, + ); + this.visit_block(body); + }); } fn resolve_params(&mut self, params: &'ast [Param]) { @@ -3662,9 +3640,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .filter(|(_, pat)| pat.id != pat_outer.id) .flat_map(|(map, _)| map); - for (key, binding_inner) in inners { - let name = key.name; - match map_outer.get(key) { + for (&name, binding_inner) in inners { + match map_outer.get(&name) { None => { // The inner binding is missing in the outer. let binding_error = @@ -3902,7 +3879,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // `Variant(a, a)`: _ => IdentifierBoundMoreThanOnceInSamePattern, }; - self.report_error(ident.span, error(ident.name)); + self.report_error(ident.span, error(ident)); } // Record as bound if it's valid: @@ -5104,7 +5081,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str]) -> bool { let mut path = expected_path.iter().rev(); while let (Some(parent), Some(next_step)) = (tcx.opt_parent(def_id), path.next()) { - if !tcx.opt_item_name(def_id).map_or(false, |n| n.as_str() == *next_step) { + if !tcx.opt_item_name(def_id).is_some_and(|n| n.as_str() == *next_step) { return false; } def_id = parent; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 2936d722aa7..2db8087fd83 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1636,13 +1636,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .enumerate() .map(|(idx, new)| (new, old_fields.get(idx))) .map(|(new, old)| { - let new = new.name.to_ident_string(); if let Some(Some(old)) = old - && new != *old + && new.as_str() != old { format!("{new}: {old}") } else { - new + new.to_string() } }) .collect::<Vec<String>>() @@ -1696,7 +1695,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ) => { // Don't suggest macro if it's unstable. let suggestable = def_id.is_local() - || self.r.tcx.lookup_stability(def_id).map_or(true, |s| s.is_stable()); + || self.r.tcx.lookup_stability(def_id).is_none_or(|s| s.is_stable()); err.span_label(span, fallback_label.to_string()); @@ -2135,7 +2134,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .r .delegation_fn_sigs .get(&self.r.local_def_id(assoc_item.id)) - .map_or(false, |sig| sig.has_self) => + .is_some_and(|sig| sig.has_self) => { AssocSuggestion::MethodWithSelf { called } } @@ -2166,7 +2165,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .r .delegation_fn_sigs .get(&def_id) - .map_or(false, |sig| sig.has_self), + .is_some_and(|sig| sig.has_self), None => self .r .tcx diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 8e457e68eec..04144eb616f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -214,7 +214,7 @@ enum Used { #[derive(Debug)] struct BindingError { - name: Symbol, + name: Ident, origin: BTreeSet<Span>, target: BTreeSet<Span>, could_be_path: bool, @@ -226,7 +226,7 @@ enum ResolutionError<'ra> { GenericParamsFromOuterItem(Res, HasGenericParams, DefKind), /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. - NameAlreadyUsedInParameterList(Symbol, Span), + NameAlreadyUsedInParameterList(Ident, Span), /// Error E0407: method is not a member of trait. MethodNotMemberOfTrait(Ident, String, Option<Symbol>), /// Error E0437: type is not a member of trait. @@ -236,11 +236,11 @@ enum ResolutionError<'ra> { /// Error E0408: variable `{}` is not bound in all patterns. VariableNotBoundInPattern(BindingError, ParentScope<'ra>), /// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm. - VariableBoundWithDifferentMode(Symbol, Span), + VariableBoundWithDifferentMode(Ident, Span), /// Error E0415: identifier is bound more than once in this parameter list. - IdentifierBoundMoreThanOnceInParameterList(Symbol), + IdentifierBoundMoreThanOnceInParameterList(Ident), /// Error E0416: identifier is bound more than once in the same pattern. - IdentifierBoundMoreThanOnceInSamePattern(Symbol), + IdentifierBoundMoreThanOnceInSamePattern(Ident), /// Error E0426: use of undeclared label. UndeclaredLabel { name: Symbol, suggestion: Option<LabelSuggestion> }, /// Error E0429: `self` imports are only allowed within a `{ }` list. @@ -292,14 +292,14 @@ enum ResolutionError<'ra> { UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option<LabelSuggestion> }, /// Error E0323, E0324, E0325: mismatch between trait item and impl item. TraitImplMismatch { - name: Symbol, + name: Ident, kind: &'static str, trait_path: String, trait_item_span: Span, code: ErrCode, }, /// Error E0201: multiple impl items for the same trait item. - TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span }, + TraitImplDuplicate { name: Ident, trait_item_span: Span, old_span: Span }, /// Inline asm `sym` operand must refer to a `fn` or `static`. InvalidAsmSym, /// `self` used instead of `Self` in a generic parameter @@ -1242,7 +1242,7 @@ impl<'ra> ResolverArenas<'ra> { no_implicit_prelude, )))); let def_id = module.opt_def_id(); - if def_id.map_or(true, |def_id| def_id.is_local()) { + if def_id.is_none_or(|def_id| def_id.is_local()) { self.local_modules.borrow_mut().push(module); } if let Some(def_id) = def_id { diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index b6b2971263a..4ff54f47435 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1022,7 +1022,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, ) { if let Some(Res::NonMacroAttr(kind)) = res { - if kind != NonMacroAttrKind::Tool && binding.map_or(true, |b| b.is_import()) { + if kind != NonMacroAttrKind::Tool && binding.is_none_or(|b| b.is_import()) { let binding_span = binding.map(|binding| binding.span); self.dcx().emit_err(errors::CannotUseThroughAnImport { span, diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 7998596c59e..fecb9735019 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -350,10 +350,7 @@ pub fn strip_generics_from_path(path_str: &str) -> Result<Box<str>, MalformedGen /// If there are no doc-comments, return true. /// FIXME(#78591): Support both inner and outer attributes on the same item. pub fn inner_docs(attrs: &[impl AttributeExt]) -> bool { - attrs - .iter() - .find(|a| a.doc_str().is_some()) - .map_or(true, |a| a.style() == ast::AttrStyle::Inner) + attrs.iter().find(|a| a.doc_str().is_some()).is_none_or(|a| a.style() == ast::AttrStyle::Inner) } /// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]`. diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index e9983699609..b9c535df4bd 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -31,7 +31,7 @@ libc = "0.2" # tidy-alphabetical-end [target.'cfg(windows)'.dependencies.windows] -version = "0.57.0" +version = "0.59.0" features = [ "Win32_Foundation", "Win32_System_LibraryLoader", diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 21afb7df7cb..97bd2670aa6 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -675,7 +675,7 @@ impl OutputTypes { /// Returns `true` if user specified a name and not just produced type pub fn contains_explicit_name(&self, key: &OutputType) -> bool { - self.0.get(key).map_or(false, |f| f.is_some()) + matches!(self.0.get(key), Some(Some(..))) } pub fn iter(&self) -> BTreeMapIter<'_, OutputType, Option<OutFileName>> { @@ -888,7 +888,7 @@ impl Input { Input::File(file) => Some(file), Input::Str { name, .. } => match name { FileName::Real(real) => real.local_path(), - FileName::QuoteExpansion(_) => None, + FileName::CfgSpec(_) => None, FileName::Anon(_) => None, FileName::MacroExpansion(_) => None, FileName::ProcMacroSourceCode(_) => None, @@ -1268,7 +1268,6 @@ pub enum EntryFnType { /// and an `include!()`. sigpipe: u8, }, - Start, } #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)] @@ -1346,8 +1345,12 @@ pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg { user_cfg } -pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: &Path) -> Target { - match Target::search(&opts.target_triple, sysroot) { +pub fn build_target_config( + early_dcx: &EarlyDiagCtxt, + target: &TargetTuple, + sysroot: &Path, +) -> Target { + match Target::search(target, sysroot) { Ok((target, warnings)) => { for warning in warnings.warning_messages() { early_dcx.early_warn(warning) @@ -1951,7 +1954,7 @@ fn collect_print_requests( matches: &getopts::Matches, ) -> Vec<PrintRequest> { let mut prints = Vec::<PrintRequest>::new(); - if cg.target_cpu.as_ref().is_some_and(|s| s == "help") { + if cg.target_cpu.as_deref() == Some("help") { prints.push(PrintRequest { kind: PrintKind::TargetCPUs, out: OutFileName::Stdout }); cg.target_cpu = None; }; diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 4be013fd6fd..ec83761da4a 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -145,7 +145,7 @@ fn current_dll_path() -> Result<PathBuf, String> { .map_err(|e| e.to_string())?; let mut filename = vec![0; 1024]; - let n = unsafe { GetModuleFileNameW(module, &mut filename) } as usize; + let n = unsafe { GetModuleFileNameW(Some(module), &mut filename) } as usize; if n == 0 { return Err(format!("GetModuleFileNameW failed: {}", io::Error::last_os_error())); } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 60f1154dc6d..1f03de3f53d 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -189,7 +189,7 @@ pub struct Session { /// enabled. Makes it so that "please report a bug" is hidden, as ICEs with /// internal features are wontfix, and they are usually the cause of the ICEs. /// None signifies that this is not tracked. - pub using_internal_features: Arc<AtomicBool>, + pub using_internal_features: &'static AtomicBool, /// All commandline args used to invoke the compiler, with @file args fully expanded. /// This will only be used within debug info, e.g. in the pdb file on windows @@ -895,13 +895,16 @@ fn default_emitter( } t => t, }; + + let source_map = if sopts.unstable_opts.link_only { None } else { Some(source_map) }; + match sopts.error_format { config::ErrorOutputType::HumanReadable(kind, color_config) => { let short = kind.short(); if let HumanReadableErrorType::AnnotateSnippet = kind { let emitter = AnnotateSnippetEmitter::new( - Some(source_map), + source_map, bundle, fallback_bundle, short, @@ -911,7 +914,7 @@ fn default_emitter( } else { let emitter = HumanEmitter::new(stderr_destination(color_config), fallback_bundle) .fluent_bundle(bundle) - .sm(Some(source_map)) + .sm(source_map) .short_message(short) .teach(sopts.unstable_opts.teach) .diagnostic_width(sopts.diagnostic_width) @@ -966,7 +969,7 @@ pub fn build_session( sysroot: PathBuf, cfg_version: &'static str, ice_file: Option<PathBuf>, - using_internal_features: Arc<AtomicBool>, + using_internal_features: &'static AtomicBool, expanded_args: Vec<String>, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override @@ -1442,7 +1445,7 @@ fn mk_emitter(output: ErrorOutputType) -> Box<DynEmitter> { config::ErrorOutputType::Json { pretty, json_rendered, color_config } => { Box::new(JsonEmitter::new( Box::new(io::BufWriter::new(io::stderr())), - Lrc::new(SourceMap::new(FilePathMapping::empty())), + Some(Lrc::new(SourceMap::new(FilePathMapping::empty()))), fallback_bundle, pretty, json_rendered, diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index dc63ea1999e..ad38ea228bf 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -316,7 +316,7 @@ macro_rules! optional { #[doc(hidden)] macro_rules! run_driver { ($args:expr, $callback:expr $(, $with_tcx:ident)?) => {{ - use rustc_driver::{Callbacks, Compilation, RunCompiler}; + use rustc_driver::{Callbacks, Compilation, run_compiler}; use rustc_middle::ty::TyCtxt; use rustc_interface::interface; use stable_mir::CompilerError; @@ -347,7 +347,7 @@ macro_rules! run_driver { /// Runs the compiler against given target and tests it with `test_function` pub fn run(&mut self) -> Result<C, CompilerError<B>> { let compiler_result = rustc_driver::catch_fatal_errors(|| -> interface::Result::<()> { - RunCompiler::new(&self.args.clone(), self).run(); + run_compiler(&self.args.clone(), self); Ok(()) }); match (compiler_result, self.result.take()) { diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 9793a4d4162..31c7e6c3eb4 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -451,16 +451,13 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let ty = ty::Ty::new_static_str(tcx); let bytes = value.as_bytes(); let val_tree = ty::ValTree::from_raw_bytes(tcx, bytes); - - let ct = ty::Const::new_value(tcx, val_tree, ty); - super::convert::mir_const_from_ty_const(&mut *tables, ct, ty) + let val = tcx.valtree_to_const_val((ty, val_tree)); + mir::Const::from_value(val, ty).stable(&mut tables) } fn new_const_bool(&self, value: bool) -> MirConst { let mut tables = self.0.borrow_mut(); - let ct = ty::Const::from_bool(tables.tcx, value); - let ty = tables.tcx.types.bool; - super::convert::mir_const_from_ty_const(&mut *tables, ct, ty) + mir::Const::from_bool(tables.tcx, value).stable(&mut tables) } fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> { @@ -472,13 +469,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> { .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) .unwrap() .size; - - // We don't use Const::from_bits since it doesn't have any error checking. let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`.")) })?; - let ct = ty::Const::new_value(tables.tcx, ValTree::from_scalar_int(scalar), ty); - Ok(super::convert::mir_const_from_ty_const(&mut *tables, ct, ty)) + Ok(mir::Const::from_scalar(tcx, mir::interpret::Scalar::Int(scalar), ty) + .stable(&mut tables)) } fn try_new_ty_const_uint( &self, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs index 4f8da08eff9..a3da563af50 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs @@ -9,8 +9,6 @@ mod error; mod mir; mod ty; -pub(crate) use ty::mir_const_from_ty_const; - impl<'tcx> Stable<'tcx> for rustc_hir::Safety { type T = stable_mir::mir::Safety; fn stable(&self, _: &mut Tables<'_>) -> Self::T { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index a7e122639ea..ff452eea23d 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -414,48 +414,6 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { } } -pub(crate) fn mir_const_from_ty_const<'tcx>( - tables: &mut Tables<'tcx>, - ty_const: ty::Const<'tcx>, - ty: Ty<'tcx>, -) -> stable_mir::ty::MirConst { - let kind = match ty_const.kind() { - ty::ConstKind::Value(ty, val) => { - let val = match val { - ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar), - ty::ValTree::Branch(branch) => { - ty::ValTree::Branch(tables.tcx.lift(branch).unwrap()) - } - }; - let ty = tables.tcx.lift(ty).unwrap(); - let const_val = tables.tcx.valtree_to_const_val((ty, val)); - if matches!(const_val, mir::ConstValue::ZeroSized) { - stable_mir::ty::ConstantKind::ZeroSized - } else { - stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( - ty, const_val, tables, - )) - } - } - ty::ConstKind::Param(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)), - ty::ConstKind::Error(_) => unreachable!(), - ty::ConstKind::Infer(_) => unreachable!(), - ty::ConstKind::Bound(_, _) => unimplemented!(), - ty::ConstKind::Placeholder(_) => unimplemented!(), - ty::ConstKind::Unevaluated(uv) => { - stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { - def: tables.const_def(uv.def), - args: uv.args.stable(tables), - promoted: None, - }) - } - ty::ConstKind::Expr(_) => unimplemented!(), - }; - let stable_ty = tables.intern_ty(ty); - let id = tables.intern_mir_const(mir::Const::Ty(ty, ty_const)); - stable_mir::ty::MirConst::new(kind, stable_ty, id) -} - impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { type T = stable_mir::ty::TyConst; diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 51cfbf59471..51d809bd65d 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -25,6 +25,7 @@ #![feature(hash_set_entry)] #![feature(if_let_guard)] #![feature(let_chains)] +#![feature(map_try_insert)] #![feature(negative_impls)] #![feature(read_buf)] #![feature(round_char_boundary)] @@ -85,9 +86,9 @@ use std::str::FromStr; use std::{fmt, iter}; use md5::{Digest, Md5}; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{Hash64, Hash128, HashStable, StableHasher}; use rustc_data_structures::sync::{FreezeLock, FreezeWriteGuard, Lock, Lrc}; +use rustc_data_structures::unord::UnordMap; use sha1::Sha1; use sha2::Sha256; @@ -103,7 +104,7 @@ pub struct SessionGlobals { span_interner: Lock<span_encoding::SpanInterner>, /// Maps a macro argument token into use of the corresponding metavariable in the macro body. /// Collisions are possible and processed in `maybe_use_metavar_location` on best effort basis. - metavar_spans: Lock<FxHashMap<Span, Span>>, + metavar_spans: MetavarSpansMap, hygiene_data: Lock<hygiene::HygieneData>, /// The session's source map, if there is one. This field should only be @@ -177,9 +178,42 @@ pub fn create_default_session_globals_then<R>(f: impl FnOnce() -> R) -> R { // deserialization. scoped_tls::scoped_thread_local!(static SESSION_GLOBALS: SessionGlobals); +#[derive(Default)] +pub struct MetavarSpansMap(FreezeLock<UnordMap<Span, (Span, bool)>>); + +impl MetavarSpansMap { + pub fn insert(&self, span: Span, var_span: Span) -> bool { + match self.0.write().try_insert(span, (var_span, false)) { + Ok(_) => true, + Err(entry) => entry.entry.get().0 == var_span, + } + } + + /// Read a span and record that it was read. + pub fn get(&self, span: Span) -> Option<Span> { + if let Some(mut mspans) = self.0.try_write() { + if let Some((var_span, read)) = mspans.get_mut(&span) { + *read = true; + Some(*var_span) + } else { + None + } + } else { + if let Some((span, true)) = self.0.read().get(&span) { Some(*span) } else { None } + } + } + + /// Freeze the set, and return the spans which have been read. + /// + /// After this is frozen, no spans that have not been read can be read. + pub fn freeze_and_get_read_spans(&self) -> UnordMap<Span, Span> { + self.0.freeze().items().filter(|(_, (_, b))| *b).map(|(s1, (s2, _))| (*s1, *s2)).collect() + } +} + #[inline] -pub fn with_metavar_spans<R>(f: impl FnOnce(&mut FxHashMap<Span, Span>) -> R) -> R { - with_session_globals(|session_globals| f(&mut session_globals.metavar_spans.lock())) +pub fn with_metavar_spans<R>(f: impl FnOnce(&MetavarSpansMap) -> R) -> R { + with_session_globals(|session_globals| f(&session_globals.metavar_spans)) } // FIXME: We should use this enum or something like it to get rid of the @@ -305,8 +339,8 @@ impl RealFileName { #[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, Decodable, Encodable)] pub enum FileName { Real(RealFileName), - /// Call to `quote!`. - QuoteExpansion(Hash64), + /// Strings provided as `--cfg [cfgspec]`. + CfgSpec(Hash64), /// Command line. Anon(Hash64), /// Hack in `src/librustc_ast/parse.rs`. @@ -353,7 +387,7 @@ impl fmt::Display for FileNameDisplay<'_> { Real(ref name) => { write!(fmt, "{}", name.to_string_lossy(self.display_pref)) } - QuoteExpansion(_) => write!(fmt, "<quote expansion>"), + CfgSpec(_) => write!(fmt, "<cfgspec>"), MacroExpansion(_) => write!(fmt, "<macro expansion>"), Anon(_) => write!(fmt, "<anon>"), ProcMacroSourceCode(_) => write!(fmt, "<proc-macro source code>"), @@ -384,7 +418,7 @@ impl FileName { | ProcMacroSourceCode(_) | CliCrateAttr(_) | Custom(_) - | QuoteExpansion(_) + | CfgSpec(_) | DocTest(_, _) | InlineAsm(_) => false, } @@ -425,7 +459,7 @@ impl FileName { pub fn cfg_spec_source_code(src: &str) -> FileName { let mut hasher = StableHasher::new(); src.hash(&mut hasher); - FileName::QuoteExpansion(hasher.finish()) + FileName::CfgSpec(hasher.finish()) } pub fn cli_crate_attr_source_code(src: &str) -> FileName { @@ -872,8 +906,7 @@ impl Span { /// Check if you can select metavar spans for the given spans to get matching contexts. fn try_metavars(a: SpanData, b: SpanData, a_orig: Span, b_orig: Span) -> (SpanData, SpanData) { - let get = |mspans: &FxHashMap<_, _>, s| mspans.get(&s).copied(); - match with_metavar_spans(|mspans| (get(mspans, a_orig), get(mspans, b_orig))) { + match with_metavar_spans(|mspans| (mspans.get(a_orig), mspans.get(b_orig))) { (None, None) => {} (Some(meta_a), None) => { let meta_a = meta_a.data(); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index f5ce5dbc9d6..1fb15fe9800 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -707,7 +707,6 @@ symbols! { coverage, coverage_attribute, cr, - crate_id, crate_in_paths, crate_local, crate_name, @@ -1189,6 +1188,7 @@ symbols! { link_section, linkage, linker, + linker_messages, lint_reasons, literal, load, @@ -1389,7 +1389,6 @@ symbols! { no_mangle, no_sanitize, no_stack_check, - no_start, no_std, nomem, non_ascii_idents, diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs index 3a71592cbe0..92c1f6e7148 100644 --- a/compiler/rustc_target/src/callconv/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs @@ -58,8 +58,10 @@ where // The AIX ABI expect byval for aggregates // See https://github.com/llvm/llvm-project/blob/main/clang/lib/CodeGen/Targets/PPC.cpp. + // The incoming parameter is represented as a pointer in the IR, + // the alignment is associated with the size of the register. (align 8 for 64bit) if !is_ret && abi == AIX { - arg.pass_by_stack_offset(None); + arg.pass_by_stack_offset(Some(Align::from_bytes(8).unwrap())); return; } diff --git a/compiler/rustc_target/src/callconv/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs index c99eb9226ef..a73c1a0f46c 100644 --- a/compiler/rustc_target/src/callconv/s390x.rs +++ b/compiler/rustc_target/src/callconv/s390x.rs @@ -38,9 +38,17 @@ where } let size = arg.layout.size; - if size.bits() <= 128 && arg.layout.is_single_vector_element(cx, size) { - arg.cast_to(Reg { kind: RegKind::Vector, size }); - return; + if size.bits() <= 128 { + if let BackendRepr::Vector { .. } = arg.layout.backend_repr { + // pass non-wrapped vector types using `PassMode::Direct` + return; + } + + if arg.layout.is_single_vector_element(cx, size) { + // pass non-transparant wrappers around a vector as `PassMode::Cast` + arg.cast_to(Reg { kind: RegKind::Vector, size }); + return; + } } if !arg.layout.is_aggregate() && size.bits() <= 64 { arg.extend_integer_width_to(64); diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs index 0944bda2687..816564d2fed 100644 --- a/compiler/rustc_target/src/callconv/x86_win64.rs +++ b/compiler/rustc_target/src/callconv/x86_win64.rs @@ -1,4 +1,4 @@ -use rustc_abi::{BackendRepr, Float, Primitive}; +use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind, Size}; use crate::abi::call::{ArgAbi, FnAbi, Reg}; use crate::spec::HasTargetSpec; @@ -6,7 +6,7 @@ use crate::spec::HasTargetSpec; // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { - let fixup = |a: &mut ArgAbi<'_, Ty>| { + let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| { match a.layout.backend_repr { BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {} BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => { @@ -23,11 +23,16 @@ pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi< // (probably what clang calls "illegal vectors"). } BackendRepr::Scalar(scalar) => { - // Match what LLVM does for `f128` so that `compiler-builtins` builtins match up - // with what LLVM expects. - if a.layout.size.bytes() > 8 + if is_ret && matches!(scalar.primitive(), Primitive::Int(Integer::I128, _)) { + // `i128` is returned in xmm0 by Clang and GCC + // FIXME(#134288): This may change for the `-msvc` targets in the future. + let reg = Reg { kind: RegKind::Vector, size: Size::from_bits(128) }; + a.cast_to(reg); + } else if a.layout.size.bytes() > 8 && !matches!(scalar.primitive(), Primitive::Float(Float::F128)) { + // Match what LLVM does for `f128` so that `compiler-builtins` builtins match up + // with what LLVM expects. a.make_indirect(); } else { a.extend_integer_width_to(32); @@ -37,8 +42,9 @@ pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi< }; if !fn_abi.ret.is_ignore() { - fixup(&mut fn_abi.ret); + fixup(&mut fn_abi.ret, true); } + for arg in fn_abi.args.iter_mut() { if arg.is_ignore() && arg.layout.is_zst() { // Windows ABIs do not talk about ZST since such types do not exist in MSVC. @@ -49,7 +55,7 @@ pub(crate) fn compute_abi_info<Ty>(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi< arg.make_indirect_from_ignore(); continue; } - fixup(arg); + fixup(arg, false); } // FIXME: We should likely also do something about ZST return types, similar to above. // However, that's non-trivial due to `()`. diff --git a/compiler/rustc_target/src/spec/base/nto_qnx.rs b/compiler/rustc_target/src/spec/base/nto_qnx.rs index 65475d068d7..819e68a0500 100644 --- a/compiler/rustc_target/src/spec/base/nto_qnx.rs +++ b/compiler/rustc_target/src/spec/base/nto_qnx.rs @@ -1,4 +1,6 @@ -use crate::spec::{RelroLevel, TargetOptions, cvs}; +use crate::spec::{ + Cc, LinkArgs, LinkerFlavor, Lld, RelroLevel, Target, TargetMetadata, TargetOptions, cvs, +}; pub(crate) fn opts() -> TargetOptions { TargetOptions { @@ -16,3 +18,96 @@ pub(crate) fn opts() -> TargetOptions { ..Default::default() } } + +pub(crate) fn meta() -> TargetMetadata { + TargetMetadata { description: None, tier: Some(3), host_tools: Some(false), std: Some(true) } +} + +pub(crate) fn aarch64() -> Target { + Target { + llvm_target: "aarch64-unknown-unknown".into(), + metadata: meta(), + pointer_width: 64, + // from: https://llvm.org/docs/LangRef.html#data-layout + // e = little endian + // m:e = ELF mangling: Private symbols get a .L prefix + // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 + // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 + // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 + // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 + // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. + // S128 = 128 bits are the natural alignment of the stack in bits. + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: TargetOptions { + features: "+v8a".into(), + max_atomic_width: Some(128), + ..opts() + } + } +} + +pub(crate) fn x86_64() -> Target { + Target { + llvm_target: "x86_64-pc-unknown".into(), + metadata: meta(), + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: "x86_64".into(), + options: TargetOptions { + cpu: "x86-64".into(), + plt_by_default: false, + max_atomic_width: Some(64), + vendor: "pc".into(), + ..opts() + }, + } +} + +pub(crate) fn pre_link_args(api_var: ApiVariant, arch: Arch) -> LinkArgs { + let (qcc_arg, arch_lib_dir) = match arch { + Arch::Aarch64 => ("-Vgcc_ntoaarch64le_cxx", "aarch64le"), + Arch::I586 => { + ("-Vgcc_ntox86_cxx", "notSupportedByQnx_compiler/rustc_target/src/spec/base/nto_qnx.rs") + } + Arch::X86_64 => ("-Vgcc_ntox86_64_cxx", "x86_64"), + }; + match api_var { + ApiVariant::Default => { + TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[qcc_arg]) + } + ApiVariant::IoSock => TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[ + qcc_arg, + get_iosock_param(arch_lib_dir), + ]), + } +} + +pub(crate) enum ApiVariant { + Default, + IoSock, +} + +pub(crate) enum Arch { + Aarch64, + I586, + X86_64, +} + +// When using `io-sock` on QNX, we must add a search path for the linker so +// that it prefers the io-sock version. +// The path depends on the host, i.e. we cannot hard-code it here, but have +// to determine it when the compiler runs. +// When using the QNX toolchain, the environment variable QNX_TARGET is always set. +// More information: +// https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.io_sock/topic/migrate_app.html +fn get_iosock_param(arch_lib_dir: &str) -> &'static str { + let target_dir = std::env::var("QNX_TARGET") + .unwrap_or_else(|_| "QNX_TARGET_not_set_please_source_qnxsdp-env.sh".into()); + let linker_param = format!("-L{target_dir}/{arch_lib_dir}/io-sock/lib"); + + // FIXME: leaking this is kind of weird: we're feeding these into something that expects an + // `AsRef<OsStr>`, but often converts to `OsString` anyways, so shouldn't we just demand an `OsString`? + linker_param.leak() +} diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs index e975102e238..d8b6ae8cf32 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnu.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs @@ -97,9 +97,9 @@ pub(crate) fn opts() -> TargetOptions { emit_debug_gdb_scripts: false, requires_uwtable: true, eh_frame_header: false, + debuginfo_kind: DebuginfoKind::Dwarf, // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. - debuginfo_kind: DebuginfoKind::Pdb, supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..Default::default() } diff --git a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs index 4f370ec8bd0..86e52117dbf 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnullvm.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnullvm.rs @@ -44,9 +44,9 @@ pub(crate) fn opts() -> TargetOptions { has_thread_local: true, crt_static_allows_dylibs: true, crt_static_respected: true, + debuginfo_kind: DebuginfoKind::Dwarf, // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. - debuginfo_kind: DebuginfoKind::Pdb, supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), ..Default::default() } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1f2df7f0168..bcd2aff54bb 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1853,6 +1853,8 @@ supported_targets! { ("armv7a-none-eabi", armv7a_none_eabi), ("armv7a-none-eabihf", armv7a_none_eabihf), + ("armv7a-nuttx-eabi", armv7a_nuttx_eabi), + ("armv7a-nuttx-eabihf", armv7a_nuttx_eabihf), ("msp430-none-elf", msp430_none_elf), @@ -1896,6 +1898,7 @@ supported_targets! { ("aarch64-unknown-none", aarch64_unknown_none), ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat), + ("aarch64-unknown-nuttx", aarch64_unknown_nuttx), ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx), @@ -1960,7 +1963,11 @@ supported_targets! { ("aarch64-unknown-nto-qnx700", aarch64_unknown_nto_qnx700), ("aarch64-unknown-nto-qnx710", aarch64_unknown_nto_qnx710), + ("aarch64-unknown-nto-qnx710_iosock", aarch64_unknown_nto_qnx710_iosock), + ("aarch64-unknown-nto-qnx800", aarch64_unknown_nto_qnx800), ("x86_64-pc-nto-qnx710", x86_64_pc_nto_qnx710), + ("x86_64-pc-nto-qnx710_iosock", x86_64_pc_nto_qnx710_iosock), + ("x86_64-pc-nto-qnx800", x86_64_pc_nto_qnx800), ("i586-pc-nto-qnx700", i586_pc_nto_qnx700), ("aarch64-unknown-linux-ohos", aarch64_unknown_linux_ohos), @@ -1971,6 +1978,8 @@ supported_targets! { ("x86_64-unknown-linux-none", x86_64_unknown_linux_none), ("thumbv6m-nuttx-eabi", thumbv6m_nuttx_eabi), + ("thumbv7a-nuttx-eabi", thumbv7a_nuttx_eabi), + ("thumbv7a-nuttx-eabihf", thumbv7a_nuttx_eabihf), ("thumbv7m-nuttx-eabi", thumbv7m_nuttx_eabi), ("thumbv7em-nuttx-eabi", thumbv7em_nuttx_eabi), ("thumbv7em-nuttx-eabihf", thumbv7em_nuttx_eabihf), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs index d6b77ffd091..3b719ebaf07 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs @@ -7,7 +7,8 @@ // For example, `-C target-cpu=cortex-a53`. use crate::spec::{ - Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, StackProbeType, Target, TargetOptions, + Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType, Target, + TargetOptions, }; pub(crate) fn target() -> Target { @@ -19,6 +20,7 @@ pub(crate) fn target() -> Target { relocation_model: RelocModel::Static, disable_redzone: true, max_atomic_width: Some(128), + supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, stack_probes: StackProbeType::Inline, panic_strategy: PanicStrategy::Abort, ..Default::default() diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs index 441ed7cf153..b26e6f19e1a 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx700.rs @@ -1,37 +1,11 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions, base}; +use crate::spec::Target; +use crate::spec::base::nto_qnx; pub(crate) fn target() -> Target { - // In QNX, libc does not provide a compatible ABI between versions. - // To distinguish between QNX versions, we needed a stable conditional compilation switch, - // which is why we needed to implement different targets in the compiler. - Target { - llvm_target: "aarch64-unknown-unknown".into(), - metadata: crate::spec::TargetMetadata { - description: Some("ARM64 QNX Neutrino 7.0 RTOS".into()), - tier: Some(3), - host_tools: Some(false), - std: Some(true), - }, - pointer_width: 64, - // from: https://llvm.org/docs/LangRef.html#data-layout - // e = little endian - // m:e = ELF mangling: Private symbols get a .L prefix - // i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32 - // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32 - // i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64 - // i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128 - // n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently. - // S128 = 128 bits are the natural alignment of the stack in bits. - data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), - arch: "aarch64".into(), - options: TargetOptions { - features: "+v8a".into(), - max_atomic_width: Some(128), - pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[ - "-Vgcc_ntoaarch64le_cxx", - ]), - env: "nto70".into(), - ..base::nto_qnx::opts() - }, - } + let mut target = nto_qnx::aarch64(); + target.metadata.description = Some("ARM64 QNX Neutrino 7.0 RTOS".into()); + target.options.pre_link_args = + nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::Aarch64); + target.options.env = "nto70".into(); + target } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs index 5b5a21fca95..3a78952c36c 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs @@ -1,8 +1,12 @@ use crate::spec::Target; +use crate::spec::base::nto_qnx; pub(crate) fn target() -> Target { - let mut base = super::aarch64_unknown_nto_qnx700::target(); - base.metadata.description = Some("ARM64 QNX Neutrino 7.1 RTOS".into()); - base.options.env = "nto71".into(); - base + let mut target = nto_qnx::aarch64(); + target.metadata.description = + Some("ARM64 QNX Neutrino 7.1 RTOS with io-pkt network stack".into()); + target.options.pre_link_args = + nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::Aarch64); + target.options.env = "nto71".into(); + target } diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710_iosock.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710_iosock.rs new file mode 100644 index 00000000000..4964f4078f5 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710_iosock.rs @@ -0,0 +1,12 @@ +use crate::spec::Target; +use crate::spec::base::nto_qnx; + +pub(crate) fn target() -> Target { + let mut target = nto_qnx::aarch64(); + target.metadata.description = + Some("ARM64 QNX Neutrino 7.1 RTOS with io-sock network stack".into()); + target.options.pre_link_args = + nto_qnx::pre_link_args(nto_qnx::ApiVariant::IoSock, nto_qnx::Arch::Aarch64); + target.options.env = "nto71_iosock".into(); + target +} diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx800.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx800.rs new file mode 100644 index 00000000000..5b820681efe --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx800.rs @@ -0,0 +1,11 @@ +use crate::spec::Target; +use crate::spec::base::nto_qnx; + +pub(crate) fn target() -> Target { + let mut target = nto_qnx::aarch64(); + target.metadata.description = Some("ARM64 QNX Neutrino 8.0 RTOS".into()); + target.options.pre_link_args = + nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::Aarch64); + target.options.env = "nto80".into(); + target +} diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs new file mode 100644 index 00000000000..582211b02b6 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nuttx.rs @@ -0,0 +1,46 @@ +// Generic AArch64 target for NuttX OS +// +// Can be used in conjunction with the `target-feature` and +// `target-cpu` compiler flags to opt-in more hardware-specific +// features. +// +// For example, `-C target-cpu=cortex-a53`. + +use crate::spec::{ + Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, StackProbeType, Target, + TargetOptions, cvs, +}; + +pub(crate) fn target() -> Target { + let opts = TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + // Enable the Cortex-A53 errata 843419 mitigation by default + pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), &[ + "--fix-cortex-a53-843419", + ]), + features: "+v8a,+strict-align,+neon,+fp-armv8".into(), + supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + relocation_model: RelocModel::Static, + disable_redzone: true, + max_atomic_width: Some(128), + stack_probes: StackProbeType::Inline, + panic_strategy: PanicStrategy::Abort, + families: cvs!["unix"], + os: "nuttx".into(), + ..Default::default() + }; + Target { + llvm_target: "aarch64-unknown-none".into(), + metadata: crate::spec::TargetMetadata { + description: Some("AArch64 NuttX".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 64, + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: "aarch64".into(), + options: opts, + } +} diff --git a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs new file mode 100644 index 00000000000..08cbfc74396 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabi.rs @@ -0,0 +1,41 @@ +// Targets Cortex-A7/A8/A9 processors (ARMv7-A) running NuttX +// +// This target assumes that the device does NOT have a FPU (Floating Point Unit) +// and will use software floating point operations. This matches the NuttX EABI +// configuration without hardware floating point support. + +use crate::spec::{ + Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs, +}; + +pub(crate) fn target() -> Target { + let opts = TargetOptions { + abi: "eabi".into(), + llvm_floatabi: Some(FloatAbi::Soft), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + features: "+v7,+thumb2,+soft-float,-neon,+strict-align".into(), + relocation_model: RelocModel::Static, + disable_redzone: true, + max_atomic_width: Some(64), + panic_strategy: PanicStrategy::Abort, + emit_debug_gdb_scripts: false, + c_enum_min_bits: Some(8), + families: cvs!["unix"], + os: "nuttx".into(), + ..Default::default() + }; + Target { + llvm_target: "armv7a-none-eabi".into(), + metadata: crate::spec::TargetMetadata { + description: Some("ARMv7-A Cortex-A with NuttX".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + options: opts, + } +} diff --git a/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs new file mode 100644 index 00000000000..f68c11a9c68 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/armv7a_nuttx_eabihf.rs @@ -0,0 +1,41 @@ +// Targets Cortex-A7/A8/A9 processors (ARMv7-A) running NuttX with hardware floating point +// +// This target assumes that the device has a FPU (Floating Point Unit) +// and will use hardware floating point operations. This matches the NuttX EABI +// configuration with hardware floating point support. + +use crate::spec::{ + Cc, FloatAbi, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions, cvs, +}; + +pub(crate) fn target() -> Target { + let opts = TargetOptions { + abi: "eabihf".into(), + llvm_floatabi: Some(FloatAbi::Hard), + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + features: "+v7,+thumb2,+vfp3,+neon,+strict-align".into(), + relocation_model: RelocModel::Static, + disable_redzone: true, + max_atomic_width: Some(64), + panic_strategy: PanicStrategy::Abort, + emit_debug_gdb_scripts: false, + c_enum_min_bits: Some(8), + families: cvs!["unix"], + os: "nuttx".into(), + ..Default::default() + }; + Target { + llvm_target: "armv7a-none-eabihf".into(), + metadata: crate::spec::TargetMetadata { + description: Some("ARMv7-A Cortex-A with NuttX (hard float)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + options: opts, + } +} diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs index 7648f81fd4d..fa21cfbab8a 100644 --- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs +++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs @@ -1,14 +1,13 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base}; +use crate::spec::base::nto_qnx; +use crate::spec::{StackProbeType, Target, TargetOptions, base}; pub(crate) fn target() -> Target { + let mut meta = nto_qnx::meta(); + meta.description = Some("32-bit x86 QNX Neutrino 7.0 RTOS".into()); + meta.std = Some(false); Target { llvm_target: "i586-pc-unknown".into(), - metadata: crate::spec::TargetMetadata { - description: Some("32-bit x86 QNX Neutrino 7.0 RTOS".into()), - tier: Some(3), - host_tools: Some(false), - std: Some(false), - }, + metadata: meta, pointer_width: 32, data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\ i128:128-f64:32:64-f80:32-n8:16:32-S128" @@ -17,9 +16,10 @@ pub(crate) fn target() -> Target { options: TargetOptions { cpu: "pentium4".into(), max_atomic_width: Some(64), - pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[ - "-Vgcc_ntox86_cxx", - ]), + pre_link_args: nto_qnx::pre_link_args( + nto_qnx::ApiVariant::Default, + nto_qnx::Arch::I586, + ), env: "nto70".into(), vendor: "pc".into(), stack_probes: StackProbeType::Inline, diff --git a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs index b1f52973c10..771ffac7d80 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32e_unknown_none_elf.rs @@ -1,6 +1,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub(crate) fn target() -> Target { + let abi = "ilp32e"; Target { // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also // `options.llvm_abiname`. @@ -16,11 +17,12 @@ pub(crate) fn target() -> Target { arch: "riscv32".into(), options: TargetOptions { + abi: abi.into(), linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), cpu: "generic-rv32".into(), // The ilp32e ABI specifies the `data_layout` - llvm_abiname: "ilp32e".into(), + llvm_abiname: abi.into(), max_atomic_width: Some(32), atomic_cas: false, features: "+e,+forced-atomics".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs index feeaa48778d..3b81c278d3a 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32em_unknown_none_elf.rs @@ -1,6 +1,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub(crate) fn target() -> Target { + let abi = "ilp32e"; Target { // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also // `options.llvm_abiname`. @@ -16,11 +17,12 @@ pub(crate) fn target() -> Target { arch: "riscv32".into(), options: TargetOptions { + abi: abi.into(), linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), cpu: "generic-rv32".into(), // The ilp32e ABI specifies the `data_layout` - llvm_abiname: "ilp32e".into(), + llvm_abiname: abi.into(), max_atomic_width: Some(32), atomic_cas: false, features: "+e,+m,+forced-atomics".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs index 45d73c13233..c18b51ad46e 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32emc_unknown_none_elf.rs @@ -1,6 +1,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; pub(crate) fn target() -> Target { + let abi = "ilp32e"; Target { // The below `data_layout` is explicitly specified by the ilp32e ABI in LLVM. See also // `options.llvm_abiname`. @@ -16,11 +17,12 @@ pub(crate) fn target() -> Target { arch: "riscv32".into(), options: TargetOptions { + abi: abi.into(), linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), linker: Some("rust-lld".into()), cpu: "generic-rv32".into(), // The ilp32e ABI specifies the `data_layout` - llvm_abiname: "ilp32e".into(), + llvm_abiname: abi.into(), max_atomic_width: Some(32), atomic_cas: false, features: "+e,+m,+c,+forced-atomics".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs index 31c9180c509..3eb3d18faf4 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_nuttx_elf.rs @@ -6,9 +6,9 @@ pub(crate) fn target() -> Target { llvm_target: "riscv32".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, arch: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs index 08dd3cc2a09..7864f7f8f9a 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_nuttx_elf.rs @@ -6,9 +6,9 @@ pub(crate) fn target() -> Target { llvm_target: "riscv32".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, arch: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs index e86549806dd..60d8ec576af 100644 --- a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_nuttx_elf.rs @@ -6,9 +6,9 @@ pub(crate) fn target() -> Target { llvm_target: "riscv32".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, arch: "riscv32".into(), diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs index c389759aecd..2cbb8c19b84 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_nuttx_elf.rs @@ -8,9 +8,9 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, llvm_target: "riscv64".into(), pointer_width: 64, diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs index 9c181665581..306b23d2787 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_nuttx_elf.rs @@ -8,9 +8,9 @@ pub(crate) fn target() -> Target { data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, llvm_target: "riscv64".into(), pointer_width: 64, diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs index 5799bbf551f..dcf98acc41f 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv6m_nuttx_eabi.rs @@ -7,9 +7,9 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv6m-none-eabi".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), @@ -22,12 +22,9 @@ pub(crate) fn target() -> Target { llvm_floatabi: Some(FloatAbi::Soft), // The ARMv6-M architecture doesn't support unaligned loads/stores so we disable them // with +strict-align. - // Also force-enable 32-bit atomics, which allows the use of atomic load/store only. - // The resulting atomics are ABI incompatible with atomics backed by libatomic. - features: "+strict-align,+atomics-32".into(), - // There are no atomic CAS instructions available in the instruction set of the ARMv6-M - // architecture - atomic_cas: false, + // The ARMv6-M doesn't support hardware atomic operations, use atomic builtins instead. + features: "+strict-align".into(), + max_atomic_width: Some(32), ..base::thumb::opts() }, } diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs new file mode 100644 index 00000000000..b5cb393f4b0 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabi.rs @@ -0,0 +1,33 @@ +// Targets Cortex-A7/A8/A9 processors (ARMv7-A) +// +// This target assumes that the device does NOT have a FPU (Floating Point Unit) +// and will use software floating point operations. This matches the NuttX EABI +// configuration without hardware floating point support. + +use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "thumbv7a-none-eabi".into(), + metadata: crate::spec::TargetMetadata { + description: None, + tier: Some(3), + host_tools: None, + std: Some(true), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + + options: TargetOptions { + families: cvs!["unix"], + os: "nuttx".into(), + abi: "eabi".into(), + llvm_floatabi: Some(FloatAbi::Soft), + // Cortex-A7/A8/A9 with software floating point + features: "+soft-float,-neon".into(), + max_atomic_width: Some(64), + ..base::thumb::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs new file mode 100644 index 00000000000..1aa44a8cc93 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_nuttx_eabihf.rs @@ -0,0 +1,37 @@ +// Targets Cortex-A7/A8/A9 processors (ARMv7-A) +// +// This target assumes that the device has a FPU (Floating Point Unit) and lowers all (single +// precision) floating point operations to hardware instructions. Cortex-A7/A8/A9 processors +// support VFPv3-D32 or VFPv4-D32 floating point units with optional double-precision support. +// +// This target uses the "hard" floating convention (ABI) where floating point values +// are passed to/from subroutines via FPU registers (S0, S1, D0, D1, etc.). + +use crate::spec::{FloatAbi, Target, TargetOptions, base, cvs}; + +pub(crate) fn target() -> Target { + Target { + llvm_target: "thumbv7a-none-eabihf".into(), + metadata: crate::spec::TargetMetadata { + description: None, + tier: Some(3), + host_tools: None, + std: Some(true), + }, + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + + options: TargetOptions { + families: cvs!["unix"], + os: "nuttx".into(), + abi: "eabihf".into(), + llvm_floatabi: Some(FloatAbi::Hard), + // Cortex-A7/A8/A9 support VFPv3-D32/VFPv4-D32 with optional double-precision + // and NEON SIMD instructions + features: "+vfp3,+neon".into(), + max_atomic_width: Some(64), + ..base::thumb::opts() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs index 536d128590f..a3bc4013e53 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabi.rs @@ -16,9 +16,9 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv7em-none-eabi".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs index 35e92b81d87..14bbe38257d 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7em_nuttx_eabihf.rs @@ -15,9 +15,9 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv7em-none-eabihf".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs index 320867444ad..2a77f48a9cd 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7m_nuttx_eabi.rs @@ -7,9 +7,9 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv7m-none-eabi".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs index 1af01b97666..25a100e9c7e 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_nuttx_eabi.rs @@ -7,9 +7,9 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv8m.base-none-eabi".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs index 661d74217ad..0bfe2b32ad4 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabi.rs @@ -8,9 +8,9 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv8m.main-none-eabi".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs index 484d35bfc20..9f75f23aa93 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_nuttx_eabihf.rs @@ -8,9 +8,9 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv8m.main-none-eabihf".into(), metadata: crate::spec::TargetMetadata { description: None, - tier: None, + tier: Some(3), host_tools: None, - std: None, + std: Some(true), }, pointer_width: 32, data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs index 245a5f06765..248aa91862c 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs @@ -1,28 +1,12 @@ -use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions, base}; +use crate::spec::Target; +use crate::spec::base::nto_qnx; pub(crate) fn target() -> Target { - Target { - llvm_target: "x86_64-pc-unknown".into(), - metadata: crate::spec::TargetMetadata { - description: Some("x86 64-bit QNX Neutrino 7.1 RTOS".into()), - tier: Some(3), - host_tools: Some(false), - std: Some(true), - }, - pointer_width: 64, - data_layout: - "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), - arch: "x86_64".into(), - options: TargetOptions { - cpu: "x86-64".into(), - plt_by_default: false, - max_atomic_width: Some(64), - pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[ - "-Vgcc_ntox86_64_cxx", - ]), - env: "nto71".into(), - vendor: "pc".into(), - ..base::nto_qnx::opts() - }, - } + let mut target = nto_qnx::x86_64(); + target.metadata.description = + Some("x86 64-bit QNX Neutrino 7.1 RTOS with io-pkt network stack".into()); + target.options.pre_link_args = + nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::X86_64); + target.options.env = "nto71".into(); + target } diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710_iosock.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710_iosock.rs new file mode 100644 index 00000000000..8f4c4924a29 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710_iosock.rs @@ -0,0 +1,12 @@ +use crate::spec::Target; +use crate::spec::base::nto_qnx; + +pub(crate) fn target() -> Target { + let mut target = nto_qnx::x86_64(); + target.metadata.description = + Some("x86 64-bit QNX Neutrino 7.1 RTOS with io-sock network stack".into()); + target.options.pre_link_args = + nto_qnx::pre_link_args(nto_qnx::ApiVariant::IoSock, nto_qnx::Arch::X86_64); + target.options.env = "nto71_iosock".into(); + target +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx800.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx800.rs new file mode 100644 index 00000000000..d91a94a2ba5 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx800.rs @@ -0,0 +1,11 @@ +use crate::spec::Target; +use crate::spec::base::nto_qnx; + +pub(crate) fn target() -> Target { + let mut target = nto_qnx::x86_64(); + target.metadata.description = Some("x86 64-bit QNX Neutrino 8.0 RTOS".into()); + target.options.pre_link_args = + nto_qnx::pre_link_args(nto_qnx::ApiVariant::Default, nto_qnx::Arch::X86_64); + target.options.env = "nto80".into(); + target +} diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl index b82bb27eb79..750d2756b4a 100644 --- a/compiler/rustc_trait_selection/messages.ftl +++ b/compiler/rustc_trait_selection/messages.ftl @@ -261,7 +261,6 @@ trait_selection_oc_fn_lang_correct_type = {$lang_item_name -> *[lang_item_name] lang item `{$lang_item_name}` } function has wrong type trait_selection_oc_fn_main_correct_type = `main` function has wrong type -trait_selection_oc_fn_start_correct_type = `#[start]` function has wrong type trait_selection_oc_generic = mismatched types trait_selection_oc_if_else_different = `if` and `else` have incompatible types @@ -396,7 +395,6 @@ trait_selection_subtype = ...so that the {$requirement -> [if_else_different] `if` and `else` have incompatible types [no_else] `if` missing an `else` returns `()` [fn_main_correct_type] `main` function has the correct type - [fn_start_correct_type] `#[start]` function has the correct type [fn_lang_correct_type] lang item function has the correct type [intrinsic_correct_type] intrinsic has the correct type [method_correct_type] method receiver has the correct type @@ -410,7 +408,6 @@ trait_selection_subtype_2 = ...so that {$requirement -> [if_else_different] `if` and `else` have incompatible types [no_else] `if` missing an `else` returns `()` [fn_main_correct_type] `main` function has the correct type - [fn_start_correct_type] `#[start]` function has the correct type [fn_lang_correct_type] lang item function has the correct type [intrinsic_correct_type] intrinsic has the correct type [method_correct_type] method receiver has the correct type diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 9778299eb19..bcb6ac13b8f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -435,6 +435,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>, terr: TypeError<'tcx>, param_env: Option<ParamEnv<'tcx>>, + path: &mut Option<PathBuf>, ) { match *cause.code() { ObligationCauseCode::Pattern { @@ -457,6 +458,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { format!("this is an iterator with items of type `{}`", args.type_at(0)), ); } else { + let expected_ty = self.tcx.short_ty_string(expected_ty, path); err.span_label(span, format!("this expression has type `{expected_ty}`")); } } @@ -717,53 +719,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { value: &mut DiagStyledString, other_value: &mut DiagStyledString, name: String, - sub: ty::GenericArgsRef<'tcx>, + args: &[ty::GenericArg<'tcx>], pos: usize, other_ty: Ty<'tcx>, ) { // `value` and `other_value` hold two incomplete type representation for display. // `name` is the path of both types being compared. `sub` value.push_highlighted(name); - let len = sub.len(); - if len > 0 { - value.push_highlighted("<"); - } - // Output the lifetimes for the first type - let lifetimes = sub - .regions() - .map(|lifetime| { - let s = lifetime.to_string(); - if s.is_empty() { "'_".to_string() } else { s } - }) - .collect::<Vec<_>>() - .join(", "); - if !lifetimes.is_empty() { - if sub.regions().count() < len { - value.push_normal(lifetimes + ", "); - } else { - value.push_normal(lifetimes); - } + if args.is_empty() { + return; } + value.push_highlighted("<"); - // Highlight all the type arguments that aren't at `pos` and compare the type argument at - // `pos` and `other_ty`. - for (i, type_arg) in sub.types().enumerate() { - if i == pos { - let values = self.cmp(type_arg, other_ty); - value.0.extend((values.0).0); - other_value.0.extend((values.1).0); - } else { - value.push_highlighted(type_arg.to_string()); + for (i, arg) in args.iter().enumerate() { + if i > 0 { + value.push_normal(", "); } - if len > 0 && i != len - 1 { - value.push_normal(", "); + match arg.unpack() { + ty::GenericArgKind::Lifetime(lt) => { + let s = lt.to_string(); + value.push_normal(if s.is_empty() { "'_" } else { &s }); + } + ty::GenericArgKind::Const(ct) => { + value.push_normal(ct.to_string()); + } + // Highlight all the type arguments that aren't at `pos` and compare + // the type argument at `pos` and `other_ty`. + ty::GenericArgKind::Type(type_arg) => { + if i == pos { + let values = self.cmp(type_arg, other_ty); + value.0.extend((values.0).0); + other_value.0.extend((values.1).0); + } else { + value.push_highlighted(type_arg.to_string()); + } + } } } - if len > 0 { - value.push_highlighted(">"); - } + + value.push_highlighted(">"); } /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`, @@ -791,27 +787,26 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { t1_out: &mut DiagStyledString, t2_out: &mut DiagStyledString, path: String, - sub: &'tcx [ty::GenericArg<'tcx>], + args: &'tcx [ty::GenericArg<'tcx>], other_path: String, other_ty: Ty<'tcx>, - ) -> Option<()> { - // FIXME/HACK: Go back to `GenericArgsRef` to use its inherent methods, - // ideally that shouldn't be necessary. - let sub = self.tcx.mk_args(sub); - for (i, ta) in sub.types().enumerate() { - if ta == other_ty { - self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty); - return Some(()); - } - if let ty::Adt(def, _) = ta.kind() { - let path_ = self.tcx.def_path_str(def.did()); - if path_ == other_path { - self.highlight_outer(t1_out, t2_out, path, sub, i, other_ty); - return Some(()); + ) -> bool { + for (i, arg) in args.iter().enumerate() { + if let Some(ta) = arg.as_type() { + if ta == other_ty { + self.highlight_outer(t1_out, t2_out, path, args, i, other_ty); + return true; + } + if let ty::Adt(def, _) = ta.kind() { + let path_ = self.tcx.def_path_str(def.did()); + if path_ == other_path { + self.highlight_outer(t1_out, t2_out, path, args, i, other_ty); + return true; + } } } } - None + false } /// Adds a `,` to the type representation only if it is appropriate. @@ -819,10 +814,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &self, value: &mut DiagStyledString, other_value: &mut DiagStyledString, - len: usize, pos: usize, ) { - if len > 0 && pos != len - 1 { + if pos > 0 { value.push_normal(", "); other_value.push_normal(", "); } @@ -899,10 +893,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let len2 = sig2.inputs().len(); if len1 == len2 { for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() { + self.push_comma(&mut values.0, &mut values.1, i); let (x1, x2) = self.cmp(*l, *r); (values.0).0.extend(x1.0); (values.1).0.extend(x2.0); - self.push_comma(&mut values.0, &mut values.1, len1, i); } } else { for (i, l) in sig1.inputs().iter().enumerate() { @@ -1150,14 +1144,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let len1 = sub_no_defaults_1.len(); let len2 = sub_no_defaults_2.len(); let common_len = cmp::min(len1, len2); - let remainder1: Vec<_> = sub1.types().skip(common_len).collect(); - let remainder2: Vec<_> = sub2.types().skip(common_len).collect(); + let remainder1 = &sub1[common_len..]; + let remainder2 = &sub2[common_len..]; let common_default_params = iter::zip(remainder1.iter().rev(), remainder2.iter().rev()) .filter(|(a, b)| a == b) .count(); let len = sub1.len() - common_default_params; - let consts_offset = len - sub1.consts().count(); // Only draw `<...>` if there are lifetime/type arguments. if len > 0 { @@ -1169,70 +1162,68 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let s = lifetime.to_string(); if s.is_empty() { "'_".to_string() } else { s } } - // At one point we'd like to elide all lifetimes here, they are irrelevant for - // all diagnostics that use this output - // - // Foo<'x, '_, Bar> - // Foo<'y, '_, Qux> - // ^^ ^^ --- type arguments are not elided - // | | - // | elided as they were the same - // not elided, they were different, but irrelevant - // - // For bound lifetimes, keep the names of the lifetimes, - // even if they are the same so that it's clear what's happening - // if we have something like - // - // for<'r, 's> fn(Inv<'r>, Inv<'s>) - // for<'r> fn(Inv<'r>, Inv<'r>) - let lifetimes = sub1.regions().zip(sub2.regions()); - for (i, lifetimes) in lifetimes.enumerate() { - let l1 = lifetime_display(lifetimes.0); - let l2 = lifetime_display(lifetimes.1); - if lifetimes.0 != lifetimes.1 { - values.0.push_highlighted(l1); - values.1.push_highlighted(l2); - } else if lifetimes.0.is_bound() || self.tcx.sess.opts.verbose { - values.0.push_normal(l1); - values.1.push_normal(l2); - } else { - values.0.push_normal("'_"); - values.1.push_normal("'_"); - } - self.push_comma(&mut values.0, &mut values.1, len, i); - } - // We're comparing two types with the same path, so we compare the type - // arguments for both. If they are the same, do not highlight and elide from the - // output. - // Foo<_, Bar> - // Foo<_, Qux> - // ^ elided type as this type argument was the same in both sides - let type_arguments = sub1.types().zip(sub2.types()); - let regions_len = sub1.regions().count(); - let num_display_types = consts_offset - regions_len; - for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() { - let i = i + regions_len; - if ta1 == ta2 && !self.tcx.sess.opts.verbose { - values.0.push_normal("_"); - values.1.push_normal("_"); - } else { - recurse(ta1, ta2, &mut values); + for (i, (arg1, arg2)) in sub1.iter().zip(sub2).enumerate().take(len) { + self.push_comma(&mut values.0, &mut values.1, i); + match arg1.unpack() { + // At one point we'd like to elide all lifetimes here, they are + // irrelevant for all diagnostics that use this output. + // + // Foo<'x, '_, Bar> + // Foo<'y, '_, Qux> + // ^^ ^^ --- type arguments are not elided + // | | + // | elided as they were the same + // not elided, they were different, but irrelevant + // + // For bound lifetimes, keep the names of the lifetimes, + // even if they are the same so that it's clear what's happening + // if we have something like + // + // for<'r, 's> fn(Inv<'r>, Inv<'s>) + // for<'r> fn(Inv<'r>, Inv<'r>) + ty::GenericArgKind::Lifetime(l1) => { + let l1_str = lifetime_display(l1); + let l2 = arg2.expect_region(); + let l2_str = lifetime_display(l2); + if l1 != l2 { + values.0.push_highlighted(l1_str); + values.1.push_highlighted(l2_str); + } else if l1.is_bound() || self.tcx.sess.opts.verbose { + values.0.push_normal(l1_str); + values.1.push_normal(l2_str); + } else { + values.0.push_normal("'_"); + values.1.push_normal("'_"); + } + } + ty::GenericArgKind::Type(ta1) => { + let ta2 = arg2.expect_ty(); + if ta1 == ta2 && !self.tcx.sess.opts.verbose { + values.0.push_normal("_"); + values.1.push_normal("_"); + } else { + recurse(ta1, ta2, &mut values); + } + } + // We're comparing two types with the same path, so we compare the type + // arguments for both. If they are the same, do not highlight and elide + // from the output. + // Foo<_, Bar> + // Foo<_, Qux> + // ^ elided type as this type argument was the same in both sides + + // Do the same for const arguments, if they are equal, do not highlight and + // elide them from the output. + ty::GenericArgKind::Const(ca1) => { + let ca2 = arg2.expect_const(); + maybe_highlight(ca1, ca2, &mut values, self.tcx); + } } - self.push_comma(&mut values.0, &mut values.1, len, i); - } - - // Do the same for const arguments, if they are equal, do not highlight and - // elide them from the output. - let const_arguments = sub1.consts().zip(sub2.consts()); - for (i, (ca1, ca2)) in const_arguments.enumerate() { - let i = i + consts_offset; - maybe_highlight(ca1, ca2, &mut values, self.tcx); - self.push_comma(&mut values.0, &mut values.1, len, i); } // Close the type argument bracket. - // Only draw `<...>` if there are lifetime/type arguments. + // Only draw `<...>` if there are arguments. if len > 0 { values.0.push_normal(">"); values.1.push_normal(">"); @@ -1244,17 +1235,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Foo<Bar<Qux> // ------- this type argument is exactly the same as the other type // Bar<Qux> - if self - .cmp_type_arg( - &mut values.0, - &mut values.1, - path1.clone(), - sub_no_defaults_1, - path2.clone(), - t2, - ) - .is_some() - { + if self.cmp_type_arg( + &mut values.0, + &mut values.1, + path1.clone(), + sub_no_defaults_1, + path2.clone(), + t2, + ) { return values; } // Check for case: @@ -1262,17 +1250,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Bar<Qux> // Foo<Bar<Qux>> // ------- this type argument is exactly the same as the other type - if self - .cmp_type_arg( - &mut values.1, - &mut values.0, - path2, - sub_no_defaults_2, - path1, - t1, - ) - .is_some() - { + if self.cmp_type_arg( + &mut values.1, + &mut values.0, + path2, + sub_no_defaults_2, + path1, + t1, + ) { return values; } @@ -1343,8 +1328,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut values = (DiagStyledString::normal("("), DiagStyledString::normal("(")); let len = args1.len(); for (i, (left, right)) in args1.iter().zip(args2).enumerate() { + self.push_comma(&mut values.0, &mut values.1, i); recurse(left, right, &mut values); - self.push_comma(&mut values.0, &mut values.1, len, i); } if len == 1 { // Keep the output for single element tuples as `(ty,)`. @@ -1611,7 +1596,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return; } - if let Some((expected, found, path)) = expected_found { + let mut path = None; + if let Some((expected, found, p)) = expected_found { + path = p; let (expected_label, found_label, exp_found) = match exp_found { Mismatch::Variable(ef) => ( ef.expected.prefix_string(self.tcx), @@ -1792,13 +1779,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &sort_string(values.expected), &sort_string(values.found), ); - if let Some(path) = path { - diag.note(format!( - "the full type name has been written to '{}'", - path.display(), - )); - diag.note("consider using `--verbose` to print the full type name to the console"); - } } } } @@ -1894,7 +1874,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // It reads better to have the error origin as the final // thing. - self.note_error_origin(diag, cause, exp_found, terr, param_env); + self.note_error_origin(diag, cause, exp_found, terr, param_env, &mut path); + if let Some(path) = path { + diag.note(format!("the full type name has been written to '{}'", path.display())); + diag.note("consider using `--verbose` to print the full type name to the console"); + } debug!(?diag); } @@ -2318,7 +2302,6 @@ impl<'tcx> ObligationCause<'tcx> { | ObligationCauseCode::MatchExpressionArm(_) | ObligationCauseCode::IfExpression { .. } | ObligationCauseCode::LetElse - | ObligationCauseCode::StartFunctionType | ObligationCauseCode::LangFunctionType(_) | ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver => FailureCode::Error0308, @@ -2376,9 +2359,6 @@ impl<'tcx> ObligationCause<'tcx> { ObligationCauseCode::MainFunctionType => { ObligationCauseFailureCode::FnMainCorrectType { span } } - ObligationCauseCode::StartFunctionType => { - ObligationCauseFailureCode::FnStartCorrectType { span, subdiags } - } &ObligationCauseCode::LangFunctionType(lang_item_name) => { ObligationCauseFailureCode::FnLangCorrectType { span, subdiags, lang_item_name } } @@ -2421,7 +2401,6 @@ impl<'tcx> ObligationCause<'tcx> { "const is compatible with trait" } ObligationCauseCode::MainFunctionType => "`main` function has the correct type", - ObligationCauseCode::StartFunctionType => "`#[start]` function has the correct type", ObligationCauseCode::LangFunctionType(_) => "lang item function has the correct type", ObligationCauseCode::IntrinsicType => "intrinsic has the correct type", ObligationCauseCode::MethodReceiver => "method receiver has the correct type", @@ -2442,7 +2421,6 @@ impl IntoDiagArg for ObligationCauseAsDiagArg<'_> { "const_compat" } ObligationCauseCode::MainFunctionType => "fn_main_correct_type", - ObligationCauseCode::StartFunctionType => "fn_start_correct_type", ObligationCauseCode::LangFunctionType(_) => "fn_lang_correct_type", ObligationCauseCode::IntrinsicType => "intrinsic_correct_type", ObligationCauseCode::MethodReceiver => "method_correct_type", diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index 2a487a48a8e..b9f3abc2534 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -1,8 +1,8 @@ use core::ops::ControlFlow; -use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::intravisit::{self, Visitor, VisitorExt}; +use rustc_hir::{self as hir, AmbigArg}; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars as rbv; @@ -48,7 +48,7 @@ fn find_component_for_bound_region<'tcx>( region_def_id: DefId, ) -> Option<&'tcx hir::Ty<'tcx>> { FindNestedTypeVisitor { tcx, region_def_id, current_index: ty::INNERMOST } - .visit_ty(arg) + .visit_ty_unambig(arg) .break_value() } @@ -74,7 +74,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { self.tcx.hir() } - fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result { + fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { match arg.kind { hir::TyKind::BareFn(_) => { self.current_index.shift_in(1); @@ -101,7 +101,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { Some(rbv::ResolvedArg::EarlyBound(id)) => { debug!("EarlyBound id={:?}", id); if id.to_def_id() == self.region_def_id { - return ControlFlow::Break(arg); + return ControlFlow::Break(arg.as_unambig_ty()); } } @@ -117,7 +117,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { if debruijn_index == self.current_index && id.to_def_id() == self.region_def_id { - return ControlFlow::Break(arg); + return ControlFlow::Break(arg.as_unambig_ty()); } } @@ -147,7 +147,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { ) .is_break() { - ControlFlow::Break(arg) + ControlFlow::Break(arg.as_unambig_ty()) } else { ControlFlow::Continue(()) }; @@ -210,7 +210,7 @@ impl<'tcx> Visitor<'tcx> for TyPathVisitor<'tcx> { ControlFlow::Continue(()) } - fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) -> Self::Result { + fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { // ignore nested types // // If you have a type like `Foo<'a, &Ty>` we diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs index 54d8a9e25ca..886581bc35f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mismatched_static_lifetime.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::VisitorExt; use rustc_middle::bug; use rustc_middle::ty::TypeVisitor; use tracing::debug; @@ -87,7 +87,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { for matching_def_id in v.0 { let mut hir_v = super::static_impl_trait::HirTraitObjectVisitor(&mut traits, matching_def_id); - hir_v.visit_ty(impl_self_ty); + hir_v.visit_ty_unambig(impl_self_ty); } if traits.is_empty() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 3416a17624e..dfbef39e9e1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -3,9 +3,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, Subdiagnostic}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{Visitor, walk_ty}; +use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty}; use rustc_hir::{ - self as hir, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime, + self as hir, AmbigArg, GenericBound, GenericParam, GenericParamKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, MissingLifetimeKind, Node, TyKind, }; use rustc_middle::ty::{ @@ -153,7 +153,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut add_label = true; if let hir::FnRetTy::Return(ty) = fn_decl.output { let mut v = StaticLifetimeVisitor(vec![], tcx.hir()); - v.visit_ty(ty); + v.visit_ty_unambig(ty); if !v.0.is_empty() { span = v.0.clone().into(); spans = v.0; @@ -374,7 +374,7 @@ pub fn suggest_new_region_bound( } } } - TyKind::TraitObject(_, lt, _) => { + TyKind::TraitObject(_, lt) => { if let LifetimeName::ImplicitObjectLifetimeDefault = lt.res { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), @@ -420,8 +420,8 @@ fn make_elided_region_spans_suggs<'a>( let mut process_consecutive_brackets = |span: Option<Span>, spans_suggs: &mut Vec<(Span, String)>| { - if span - .is_some_and(|span| bracket_span.map_or(true, |bracket_span| span == bracket_span)) + if let Some(span) = span + && bracket_span.is_none_or(|bracket_span| span == bracket_span) { consecutive_brackets += 1; } else if let Some(bracket_span) = bracket_span.take() { @@ -500,7 +500,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // In that case, only the first one will get suggestions. let mut traits = vec![]; let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); - hir_v.visit_ty(self_ty); + hir_v.visit_ty_unambig(self_ty); !traits.is_empty() }) { @@ -560,7 +560,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { for found_did in found_dids { let mut traits = vec![]; let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); - hir_v.visit_ty(self_ty); + hir_v.visit_ty_unambig(self_ty); for &span in &traits { let subdiag = DynTraitConstraintSuggestion { span, ident }; subdiag.add_to_diag(err); @@ -591,12 +591,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for TraitObjectVisitor { pub struct HirTraitObjectVisitor<'a>(pub &'a mut Vec<Span>, pub DefId); impl<'a, 'tcx> Visitor<'tcx> for HirTraitObjectVisitor<'a> { - fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { - if let TyKind::TraitObject( - poly_trait_refs, - Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. }, - _, - ) = t.kind + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx, AmbigArg>) { + if let TyKind::TraitObject(poly_trait_refs, lifetime_ptr) = t.kind + && let Lifetime { res: LifetimeName::ImplicitObjectLifetimeDefault, .. } = + lifetime_ptr.pointer() { for ptr in poly_trait_refs { if Some(self.1) == ptr.trait_ref.trait_def_id() { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 95dd1b28a39..bbcd28c0835 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -1,10 +1,10 @@ //! Error Reporting for `impl` items that do not match the obligations from their `trait`. use rustc_errors::ErrorGuaranteed; -use rustc_hir as hir; use rustc_hir::def::{Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{Visitor, walk_ty}; +use rustc_hir::{self as hir, AmbigArg}; use rustc_middle::hir::nested_filter; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::ExpectedFound; @@ -137,11 +137,13 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { self.tcx.hir() } - fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) { match arg.kind { hir::TyKind::Ref(_, ref mut_ty) => { // We don't want to suggest looking into borrowing `&T` or `&Self`. - hir::intravisit::walk_ty(self, mut_ty.ty); + if let Some(ambig_ty) = mut_ty.ty.try_as_ambig_ty() { + walk_ty(self, ambig_ty); + } return; } hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 36270e0da78..af7e56961b7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -167,6 +167,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { exp_span, exp_found.expected, exp_found.found, ); + match self.tcx.coroutine_kind(cause.body_id) { + Some(hir::CoroutineKind::Desugared( + hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen, + _, + )) => (), + None + | Some( + hir::CoroutineKind::Coroutine(_) + | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _), + ) => return, + } + if let ObligationCauseCode::CompareImplItem { .. } = cause.code() { return; } @@ -643,7 +655,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { && let ty::Ref(found_region, _, _) = found.kind() && expected_region.is_bound() && !found_region.is_bound() - && let hir::TyKind::Infer = arg_hir.kind + && let hir::TyKind::Infer(()) = arg_hir.kind { // If the expected region is late bound, the found region is not, and users are asking compiler // to infer the type, we can suggest adding `: &_`. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index c40ba330845..5021fd8bf83 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -462,6 +462,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.note( "`#[target_feature]` functions do not implement the `Fn` traits", ); + err.note( + "try casting the function to a `fn` pointer or wrapping it in a closure", + ); } self.try_to_add_help_message( @@ -580,8 +583,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.tcx.hir_node_by_def_id(obligation.cause.body_id) && let hir::ItemKind::Impl(impl_) = item.kind && let None = impl_.of_trait - && let hir::TyKind::TraitObject(_, _, syntax) = impl_.self_ty.kind - && let TraitObjectSyntax::None = syntax + && let hir::TyKind::TraitObject(_, tagged_ptr) = impl_.self_ty.kind + && let TraitObjectSyntax::None = tagged_ptr.tag() && impl_.self_ty.span.edition().at_least_rust_2021() { // Silence the dyn-compatibility error in favor of the missing dyn on @@ -1338,20 +1341,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let derive_better_type_error = |alias_term: ty::AliasTerm<'tcx>, expected_term: ty::Term<'tcx>| { let ocx = ObligationCtxt::new(self); - let normalized_term = match expected_term.unpack() { - ty::TermKind::Ty(_) => self.next_ty_var(DUMMY_SP).into(), - ty::TermKind::Const(_) => self.next_const_var(DUMMY_SP).into(), - }; - ocx.register_obligation(Obligation::new( - self.tcx, - ObligationCause::dummy(), + + let Ok(normalized_term) = ocx.structurally_normalize_term( + &ObligationCause::dummy(), obligation.param_env, - ty::PredicateKind::NormalizesTo(ty::NormalizesTo { - alias: alias_term, - term: normalized_term, - }), - )); - let _ = ocx.select_where_possible(); + alias_term.to_term(self.tcx), + ) else { + return None; + }; + if let Err(terr) = ocx.eq( &ObligationCause::dummy(), obligation.param_env, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index cd4f77bb4cf..8111983c539 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, LangItem}; +use rustc_hir::{self as hir, AmbigArg, LangItem}; use rustc_infer::traits::{ DynCompatibilityViolation, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, @@ -87,9 +87,9 @@ impl<'v> Visitor<'v> for FindExprBySpan<'v> { } } - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { if self.span == ty.span { - self.ty_result = Some(ty); + self.ty_result = Some(ty.as_unambig_ty()); } else { hir::intravisit::walk_ty(self, ty); } @@ -433,33 +433,19 @@ pub fn report_dyn_incompatibility<'tcx>( hir::Node::Item(item) => Some(item.ident.span), _ => None, }); + let mut err = struct_span_code_err!( tcx.dcx(), span, E0038, - "the trait `{}` cannot be made into an object", + "the {} `{}` is not dyn compatible", + tcx.def_descr(trait_def_id), trait_str ); - err.span_label(span, format!("`{trait_str}` cannot be made into an object")); - - if let Some(hir_id) = hir_id - && let hir::Node::Ty(ty) = tcx.hir_node(hir_id) - && let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind - { - let mut hir_id = hir_id; - while let hir::Node::Ty(ty) = tcx.parent_hir_node(hir_id) { - hir_id = ty.hir_id; - } - if tcx.parent_hir_node(hir_id).fn_sig().is_some() { - // Do not suggest `impl Trait` when dealing with things like super-traits. - err.span_suggestion_verbose( - ty.span.until(trait_ref.span), - "consider using an opaque type instead", - "impl ", - Applicability::MaybeIncorrect, - ); - } - } + err.span_label(span, format!("`{trait_str}` is not dyn compatible")); + + attempt_dyn_to_impl_suggestion(tcx, hir_id, &mut err); + let mut reported_violations = FxIndexSet::default(); let mut multi_span = vec![]; let mut messages = vec![]; @@ -474,7 +460,7 @@ pub fn report_dyn_incompatibility<'tcx>( if reported_violations.insert(violation.clone()) { let spans = violation.spans(); let msg = if trait_span.is_none() || spans.is_empty() { - format!("the trait cannot be made into an object because {}", violation.error_msg()) + format!("the trait is not dyn compatible because {}", violation.error_msg()) } else { format!("...because {}", violation.error_msg()) }; @@ -491,7 +477,7 @@ pub fn report_dyn_incompatibility<'tcx>( let has_multi_span = !multi_span.is_empty(); let mut note_span = MultiSpan::from_spans(multi_span.clone()); if let (Some(trait_span), true) = (trait_span, has_multi_span) { - note_span.push_span_label(trait_span, "this trait cannot be made into an object..."); + note_span.push_span_label(trait_span, "this trait is not dyn compatible..."); } for (span, msg) in iter::zip(multi_span, messages) { note_span.push_span_label(span, msg); @@ -499,16 +485,12 @@ pub fn report_dyn_incompatibility<'tcx>( // FIXME(dyn_compat_renaming): Update the URL. err.span_note( note_span, - "for a trait to be \"dyn-compatible\" it needs to allow building a vtable to allow the call \ - to be resolvable dynamically; for more information visit \ - <https://doc.rust-lang.org/reference/items/traits.html#object-safety>", + "for a trait to be dyn compatible it needs to allow building a vtable\n\ + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>", ); // Only provide the help if its a local trait, otherwise it's not actionable. if trait_span.is_some() { - let mut reported_violations: Vec<_> = reported_violations.into_iter().collect(); - reported_violations.sort(); - let mut potential_solutions: Vec<_> = reported_violations.into_iter().map(|violation| violation.solution()).collect(); potential_solutions.sort(); @@ -519,68 +501,116 @@ pub fn report_dyn_incompatibility<'tcx>( } } + attempt_dyn_to_enum_suggestion(tcx, trait_def_id, &*trait_str, &mut err); + + err +} + +/// Attempt to suggest converting the `dyn Trait` argument to an enumeration +/// over the types that implement `Trait`. +fn attempt_dyn_to_enum_suggestion( + tcx: TyCtxt<'_>, + trait_def_id: DefId, + trait_str: &str, + err: &mut Diag<'_>, +) { let impls_of = tcx.trait_impls_of(trait_def_id); - let impls = if impls_of.blanket_impls().is_empty() { - impls_of - .non_blanket_impls() - .values() - .flatten() - .filter(|def_id| { - !matches!(tcx.type_of(*def_id).instantiate_identity().kind(), ty::Dynamic(..)) - }) - .collect::<Vec<_>>() - } else { - vec![] - }; - let externally_visible = if !impls.is_empty() - && let Some(def_id) = trait_def_id.as_local() + + if !impls_of.blanket_impls().is_empty() { + return; + } + + let concrete_impls: Option<Vec<Ty<'_>>> = impls_of + .non_blanket_impls() + .values() + .flatten() + .map(|impl_id| { + // Don't suggest conversion to enum if the impl types have type parameters. + // It's unlikely the user wants to define a generic enum. + let Some(impl_type) = tcx.type_of(*impl_id).no_bound_vars() else { return None }; + + // Obviously unsized impl types won't be usable in an enum. + // Note: this doesn't use `Ty::is_trivially_sized` because that function + // defaults to assuming that things are *not* sized, whereas we want to + // fall back to assuming that things may be sized. + match impl_type.kind() { + ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::DynKind::Dyn) => { + return None; + } + _ => {} + } + Some(impl_type) + }) + .collect(); + let Some(concrete_impls) = concrete_impls else { return }; + + const MAX_IMPLS_TO_SUGGEST_CONVERTING_TO_ENUM: usize = 9; + if concrete_impls.is_empty() || concrete_impls.len() > MAX_IMPLS_TO_SUGGEST_CONVERTING_TO_ENUM { + return; + } + + let externally_visible = if let Some(def_id) = trait_def_id.as_local() { // We may be executing this during typeck, which would result in cycle // if we used effective_visibilities query, which looks into opaque types // (and therefore calls typeck). - && tcx.resolutions(()).effective_visibilities.is_exported(def_id) - { - true + tcx.resolutions(()).effective_visibilities.is_exported(def_id) } else { false }; - match &impls[..] { - [] => {} - _ if impls.len() > 9 => {} - [only] if externally_visible => { - err.help(with_no_trimmed_paths!(format!( - "only type `{}` is seen to implement the trait in this crate, consider using it \ - directly instead", - tcx.type_of(*only).instantiate_identity(), - ))); - } - [only] => { - err.help(with_no_trimmed_paths!(format!( - "only type `{}` implements the trait, consider using it directly instead", - tcx.type_of(*only).instantiate_identity(), - ))); - } - impls => { - let types = impls - .iter() - .map(|t| { - with_no_trimmed_paths!(format!(" {}", tcx.type_of(*t).instantiate_identity(),)) - }) - .collect::<Vec<_>>(); - err.help(format!( - "the following types implement the trait, consider defining an enum where each \ - variant holds one of these types, implementing `{}` for this new enum and using \ - it instead:\n{}", - trait_str, - types.join("\n"), - )); - } + + if let [only_impl] = &concrete_impls[..] { + let within = if externally_visible { " within this crate" } else { "" }; + err.help(with_no_trimmed_paths!(format!( + "only type `{only_impl}` implements `{trait_str}`{within}; \ + consider using it directly instead." + ))); + } else { + let types = concrete_impls + .iter() + .map(|t| with_no_trimmed_paths!(format!(" {}", t))) + .collect::<Vec<String>>() + .join("\n"); + + err.help(format!( + "the following types implement `{trait_str}`:\n\ + {types}\n\ + consider defining an enum where each variant holds one of these types,\n\ + implementing `{trait_str}` for this new enum and using it instead", + )); } + if externally_visible { err.note(format!( - "`{trait_str}` can be implemented in other crates; if you want to support your users \ + "`{trait_str}` may be implemented in other crates; if you want to support your users \ passing their own types here, you can't refer to a specific type", )); } +} - err +/// Attempt to suggest that a `dyn Trait` argument or return type be converted +/// to use `impl Trait`. +fn attempt_dyn_to_impl_suggestion(tcx: TyCtxt<'_>, hir_id: Option<hir::HirId>, err: &mut Diag<'_>) { + let Some(hir_id) = hir_id else { return }; + let hir::Node::Ty(ty) = tcx.hir_node(hir_id) else { return }; + let hir::TyKind::TraitObject([trait_ref, ..], ..) = ty.kind else { return }; + + // Only suggest converting `dyn` to `impl` if we're in a function signature. + // This ensures that we don't suggest converting e.g. + // `type Alias = Box<dyn DynIncompatibleTrait>;` to + // `type Alias = Box<impl DynIncompatibleTrait>;` + let Some((_id, first_non_type_parent_node)) = + tcx.hir().parent_iter(hir_id).find(|(_id, node)| !matches!(node, hir::Node::Ty(_))) + else { + return; + }; + if first_non_type_parent_node.fn_sig().is_none() { + return; + } + + err.span_suggestion_verbose( + ty.span.until(trait_ref.span), + "consider using an opaque type instead", + "impl ", + Applicability::MaybeIncorrect, + ); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 2d932e36470..4e0b097db4c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt}; use rustc_parse_format::{ParseMode, Parser, Piece, Position}; use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES; -use rustc_span::{Span, Symbol, kw, sym}; +use rustc_span::{Ident, Span, Symbol, kw, sym}; use tracing::{debug, info}; use {rustc_attr_parsing as attr, rustc_hir as hir}; @@ -375,7 +375,7 @@ impl IgnoredDiagnosticOption { #[help] pub struct UnknownFormatParameterForOnUnimplementedAttr { argument_name: Symbol, - trait_name: Symbol, + trait_name: Ident, } #[derive(LintDiagnostic)] @@ -792,7 +792,7 @@ impl<'tcx> OnUnimplementedFormatString { tcx.trait_id_of_impl(item_def_id) .expect("expected `on_unimplemented` to correspond to a trait") }; - let trait_name = tcx.item_name(trait_def_id); + let trait_name = tcx.item_ident(trait_def_id); let generics = tcx.generics_of(item_def_id); let s = self.symbol.as_str(); let mut parser = Parser::new(s, None, None, false, ParseMode::Format); @@ -821,7 +821,11 @@ impl<'tcx> OnUnimplementedFormatString { Position::ArgumentNamed(s) => { match Symbol::intern(s) { // `{ThisTraitsName}` is allowed - s if s == trait_name && !self.is_diagnostic_namespace_variant => (), + s if s == trait_name.name + && !self.is_diagnostic_namespace_variant => + { + () + } s if ALLOWED_FORMAT_SYMBOLS.contains(&s) && !self.is_diagnostic_namespace_variant => { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index c2e73b732d3..471105773e2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -14,14 +14,13 @@ use rustc_errors::{ Applicability, Diag, EmissionGuarantee, MultiSpan, Style, SuggestionStyle, pluralize, struct_span_code_err, }; -use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::Visitor; +use rustc_hir::intravisit::{Visitor, VisitorExt}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ - CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, expr_needs_parens, - is_range_literal, + self as hir, AmbigArg, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, HirId, Node, + expr_needs_parens, is_range_literal, }; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_middle::hir::map; @@ -179,7 +178,7 @@ pub fn suggest_restriction<'tcx, G: EmissionGuarantee>( let mut ty_spans = vec![]; for input in fn_sig.decl.inputs { ReplaceImplTraitVisitor { ty_spans: &mut ty_spans, param_did: param.def_id } - .visit_ty(input); + .visit_ty_unambig(input); } // The type param `T: Trait` we will suggest to introduce. let type_param = format!("{type_param_name}: {bound_str}"); @@ -2740,7 +2739,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ObligationCauseCode::IfExpression { .. } | ObligationCauseCode::IfExpressionWithNoElse | ObligationCauseCode::MainFunctionType - | ObligationCauseCode::StartFunctionType | ObligationCauseCode::LangFunctionType(_) | ObligationCauseCode::IntrinsicType | ObligationCauseCode::MethodReceiver @@ -3075,7 +3073,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } if let Some(ty) = ty { match ty.kind { - hir::TyKind::TraitObject(traits, _, _) => { + hir::TyKind::TraitObject(traits, _) => { let (span, kw) = match traits { [first, ..] if first.span.lo() == ty.span.lo() => { // Missing `dyn` in front of trait object. @@ -5066,7 +5064,7 @@ pub struct SelfVisitor<'v> { } impl<'v> Visitor<'v> for SelfVisitor<'v> { - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { if let hir::TyKind::Path(path) = ty.kind && let hir::QPath::TypeRelative(inner_ty, segment) = path && (Some(segment.ident.name) == self.name || self.name.is_none()) @@ -5074,7 +5072,7 @@ impl<'v> Visitor<'v> for SelfVisitor<'v> { && let hir::QPath::Resolved(None, inner_path) = inner_path && let Res::SelfTyAlias { .. } = inner_path.res { - self.paths.push(ty); + self.paths.push(ty.as_unambig_ty()); } hir::intravisit::walk_ty(self, ty); } @@ -5188,7 +5186,7 @@ struct ReplaceImplTraitVisitor<'a> { } impl<'a, 'hir> hir::intravisit::Visitor<'hir> for ReplaceImplTraitVisitor<'a> { - fn visit_ty(&mut self, t: &'hir hir::Ty<'hir>) { + fn visit_ty(&mut self, t: &'hir hir::Ty<'hir, AmbigArg>) { if let hir::TyKind::Path(hir::QPath::Resolved( None, hir::Path { res: Res::Def(_, segment_did), .. }, @@ -5481,7 +5479,7 @@ impl<'v> Visitor<'v> for FindTypeParam { // Skip where-clauses, to avoid suggesting indirection for type parameters found there. } - fn visit_ty(&mut self, ty: &hir::Ty<'_>) { + fn visit_ty(&mut self, ty: &hir::Ty<'_, AmbigArg>) { // We collect the spans of all uses of the "bare" type param, like in `field: T` or // `field: (T, T)` where we could make `T: ?Sized` while skipping cases that are known to be // valid like `field: &'a T` or `field: *mut T` and cases that *might* have further `Sized` diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 53a4e5031c6..2dfa72972ba 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -6,11 +6,10 @@ use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, MultiSpan, SubdiagMessageOp, Subdiagnostic, }; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{Visitor, walk_ty}; -use rustc_hir::{FnRetTy, GenericParamKind, Node}; +use rustc_hir::intravisit::{Visitor, VisitorExt, walk_ty}; +use rustc_hir::{self as hir, AmbigArg, FnRetTy, GenericParamKind, Node}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::print::{PrintTraitRefExt as _, TraitRefPrintOnlyTraitPath}; use rustc_middle::ty::{self, Binder, ClosureKind, FnSig, PolyTraitRef, Region, Ty, TyCtxt}; @@ -579,7 +578,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { } impl<'v> Visitor<'v> for ImplicitLifetimeFinder { - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v, AmbigArg>) { let make_suggestion = |ident: Ident| { if ident.name == kw::Empty && ident.span.is_empty() { format!("{}, ", self.suggestion_param_name) @@ -642,16 +641,16 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { if let Some(fn_decl) = node.fn_decl() && let hir::FnRetTy::Return(ty) = fn_decl.output { - visitor.visit_ty(ty); + visitor.visit_ty_unambig(ty); } if visitor.suggestions.is_empty() { // Do not suggest constraining the `&self` param, but rather the return type. // If that is wrong (because it is not sufficient), a follow up error will tell the // user to fix it. This way we lower the chances of *over* constraining, but still // get the cake of "correctly" contrained in two steps. - visitor.visit_ty(self.ty_sup); + visitor.visit_ty_unambig(self.ty_sup); } - visitor.visit_ty(self.ty_sub); + visitor.visit_ty_unambig(self.ty_sub); if visitor.suggestions.is_empty() { return false; } @@ -1695,13 +1694,6 @@ pub enum ObligationCauseFailureCode { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_fn_start_correct_type, code = E0308)] - FnStartCorrectType { - #[primary_span] - span: Span, - #[subdiagnostic] - subdiags: Vec<TypeErrorAdditionalDiags>, - }, #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)] FnLangCorrectType { #[primary_span] diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 4498beff4ea..2b7da4bc5ff 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -513,8 +513,27 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { _ => ChildMode::PassThrough, }; + let nested_goals = candidate.instantiate_nested_goals(self.span()); + + // If the candidate requires some `T: FnPtr` bound which does not hold should not be treated as + // an actual candidate, instead we should treat them as if the impl was never considered to + // have potentially applied. As if `impl<A, R> Trait for for<..> fn(..A) -> R` was written + // instead of `impl<T: FnPtr> Trait for T`. + // + // We do this as a separate loop so that we do not choose to tell the user about some nested + // goal before we encounter a `T: FnPtr` nested goal. + for nested_goal in &nested_goals { + if let Some(fn_ptr_trait) = tcx.lang_items().fn_ptr_trait() + && let Some(poly_trait_pred) = nested_goal.goal().predicate.as_trait_clause() + && poly_trait_pred.def_id() == fn_ptr_trait + && let Err(NoSolution) = nested_goal.result() + { + return ControlFlow::Break(self.obligation.clone()); + } + } + let mut impl_where_bound_count = 0; - for nested_goal in candidate.instantiate_nested_goals(self.span()) { + for nested_goal in nested_goals { trace!(nested_goal = ?(nested_goal.goal(), nested_goal.source(), nested_goal.result())); let make_obligation = |cause| Obligation { @@ -605,7 +624,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } } -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] enum ChildMode<'tcx> { // Try to derive an `ObligationCause::{ImplDerived,BuiltinDerived}`, // and skip all `GoalSource::Misc`, which represent useless obligations diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index e27143f1396..50d47d20e1a 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -709,7 +709,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { if matches!(ty.kind(), ty::Alias(..)) { let ocx = ObligationCtxt::new(infcx); ty = ocx - .structurally_normalize(&ObligationCause::dummy(), param_env, ty) + .structurally_normalize_ty(&ObligationCause::dummy(), param_env, ty) .map_err(|_| ())?; if !ocx.select_where_possible().is_empty() { return Err(()); diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index d2abd881c45..66491d9abe1 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -19,6 +19,7 @@ use rustc_middle::ty::{ TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_span::Span; +use rustc_type_ir::elaborate; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -39,7 +40,7 @@ pub fn hir_ty_lowering_dyn_compatibility_violations( trait_def_id: DefId, ) -> Vec<DynCompatibilityViolation> { debug_assert!(tcx.generics_of(trait_def_id).has_self); - tcx.supertrait_def_ids(trait_def_id) + elaborate::supertrait_def_ids(tcx, trait_def_id) .map(|def_id| predicates_reference_self(tcx, def_id, true)) .filter(|spans| !spans.is_empty()) .map(DynCompatibilityViolation::SupertraitSelf) @@ -52,9 +53,8 @@ fn dyn_compatibility_violations( ) -> &'_ [DynCompatibilityViolation] { debug_assert!(tcx.generics_of(trait_def_id).has_self); debug!("dyn_compatibility_violations: {:?}", trait_def_id); - tcx.arena.alloc_from_iter( - tcx.supertrait_def_ids(trait_def_id) + elaborate::supertrait_def_ids(tcx, trait_def_id) .flat_map(|def_id| dyn_compatibility_violations_for_trait(tcx, def_id)), ) } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 5e270b62b00..4a3983fca31 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -319,7 +319,7 @@ where self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut()) } - pub fn structurally_normalize( + pub fn structurally_normalize_ty( &self, cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -327,7 +327,7 @@ where ) -> Result<Ty<'tcx>, Vec<E>> { self.infcx .at(cause, param_env) - .structurally_normalize(value, &mut **self.engine.borrow_mut()) + .structurally_normalize_ty(value, &mut **self.engine.borrow_mut()) } pub fn structurally_normalize_const( @@ -340,4 +340,15 @@ where .at(cause, param_env) .structurally_normalize_const(value, &mut **self.engine.borrow_mut()) } + + pub fn structurally_normalize_term( + &self, + cause: &ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: ty::Term<'tcx>, + ) -> Result<ty::Term<'tcx>, Vec<E>> { + self.infcx + .at(cause, param_env) + .structurally_normalize_term(value, &mut **self.engine.borrow_mut()) + } } diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index da16a742099..fe5ad003a7e 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -66,9 +66,9 @@ pub use self::specialize::{ }; pub use self::structural_normalize::StructurallyNormalizeExt; pub use self::util::{ - BoundVarReplacer, PlaceholderReplacer, TraitAliasExpander, TraitAliasExpansionInfo, elaborate, - expand_trait_aliases, impl_item_is_final, supertraits, - transitive_bounds_that_define_assoc_item, upcast_choices, with_replaced_escaping_bound_vars, + BoundVarReplacer, PlaceholderReplacer, elaborate, expand_trait_aliases, impl_item_is_final, + supertrait_def_ids, supertraits, transitive_bounds_that_define_assoc_item, upcast_choices, + with_replaced_escaping_bound_vars, }; use crate::error_reporting::InferCtxtErrorExt; use crate::infer::outlives::env::OutlivesEnvironment; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index d59cf88875e..537b042bde5 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -18,6 +18,7 @@ use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast}; use rustc_middle::{bug, span_bug}; use rustc_span::sym; +use rustc_type_ir::elaborate; use thin_vec::thin_vec; use tracing::{debug, instrument}; @@ -836,8 +837,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>( if tcx.is_impl_trait_in_trait(obligation.predicate.def_id) && let Some(out_trait_def_id) = data.principal_def_id() && let rpitit_trait_def_id = tcx.parent(obligation.predicate.def_id) - && tcx - .supertrait_def_ids(out_trait_def_id) + && elaborate::supertrait_def_ids(tcx, out_trait_def_id) .any(|trait_def_id| trait_def_id == rpitit_trait_def_id) { candidate_set.push_candidate(ProjectionCandidate::ObjectRpitit); diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 4004e354dc1..26ba1511b54 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -6,8 +6,7 @@ use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument}; use crate::traits::query::NoSolution; -use crate::traits::query::normalize::QueryNormalizeExt; -use crate::traits::{Normalized, ObligationCause, ObligationCtxt}; +use crate::traits::{ObligationCause, ObligationCtxt}; /// This returns true if the type `ty` is "trivial" for /// dropck-outlives -- that is, if it doesn't require any types to @@ -172,13 +171,18 @@ pub fn compute_dropck_outlives_inner<'tcx>( // do not themselves define a destructor", more or less. We have // to push them onto the stack to be expanded. for ty in constraints.dtorck_types.drain(..) { - let Normalized { value: ty, obligations } = - ocx.infcx.at(&cause, param_env).query_normalize(ty)?; - ocx.register_obligations(obligations); + let normalized_ty = ocx.normalize(&cause, param_env, ty); - debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); + let errors = ocx.select_where_possible(); + if !errors.is_empty() { + debug!("failed to normalize dtorck type: {ty} ~> {errors:#?}"); + return Err(NoSolution); + } + + let normalized_ty = ocx.infcx.resolve_vars_if_possible(normalized_ty); + debug!("dropck_outlives: ty from dtorck_types = {:?}", normalized_ty); - match ty.kind() { + match normalized_ty.kind() { // All parameters live for the duration of the // function. ty::Param(..) => {} @@ -186,12 +190,12 @@ pub fn compute_dropck_outlives_inner<'tcx>( // A projection that we couldn't resolve - it // might have a destructor. ty::Alias(..) => { - result.kinds.push(ty.into()); + result.kinds.push(normalized_ty.into()); } _ => { - if ty_set.insert(ty) { - ty_stack.push((ty, depth + 1)); + if ty_set.insert(normalized_ty) { + ty_stack.push((normalized_ty, depth + 1)); } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index b370f802052..13a6744c2e9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -18,7 +18,7 @@ use rustc_infer::traits::{ use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode}; use rustc_middle::{bug, span_bug}; -use rustc_type_ir::Interner; +use rustc_type_ir::{Interner, elaborate}; use tracing::{debug, instrument, trace}; use super::SelectionCandidate::*; @@ -1003,8 +1003,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let a_auto_traits: FxIndexSet<DefId> = a_data .auto_traits() .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| { - self.tcx() - .supertrait_def_ids(principal_def_id) + elaborate::supertrait_def_ids(self.tcx(), principal_def_id) .filter(|def_id| self.tcx().trait_is_auto(*def_id)) })) .collect(); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5581ea46882..0cc0d7f786b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -32,6 +32,7 @@ use rustc_middle::ty::{ TypingMode, Upcast, }; use rustc_span::{Symbol, sym}; +use rustc_type_ir::elaborate; use tracing::{debug, instrument, trace}; use self::EvaluationResult::*; @@ -2531,7 +2532,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let a_auto_traits: FxIndexSet<DefId> = a_data .auto_traits() .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { - tcx.supertrait_def_ids(principal_def_id).filter(|def_id| tcx.trait_is_auto(*def_id)) + elaborate::supertrait_def_ids(tcx, principal_def_id) + .filter(|def_id| tcx.trait_is_auto(*def_id)) })) .collect(); diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index f8e8f2176c1..e6d5d336b8d 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -7,44 +7,12 @@ use crate::traits::{NormalizeExt, Obligation}; #[extension(pub trait StructurallyNormalizeExt<'tcx>)] impl<'tcx> At<'_, 'tcx> { - fn structurally_normalize<E: 'tcx>( + fn structurally_normalize_ty<E: 'tcx>( &self, ty: Ty<'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx, E>, ) -> Result<Ty<'tcx>, Vec<E>> { - assert!(!ty.is_ty_var(), "should have resolved vars before calling"); - - if self.infcx.next_trait_solver() { - let ty::Alias(..) = *ty.kind() else { - return Ok(ty); - }; - - let new_infer_ty = self.infcx.next_ty_var(self.cause.span); - - // We simply emit an `alias-eq` goal here, since that will take care of - // normalizing the LHS of the projection until it is a rigid projection - // (or a not-yet-defined opaque in scope). - let obligation = Obligation::new( - self.infcx.tcx, - self.cause.clone(), - self.param_env, - ty::PredicateKind::AliasRelate( - ty.into(), - new_infer_ty.into(), - ty::AliasRelationDirection::Equate, - ), - ); - - fulfill_cx.register_predicate_obligation(self.infcx, obligation); - let errors = fulfill_cx.select_where_possible(self.infcx); - if !errors.is_empty() { - return Err(errors); - } - - Ok(self.infcx.resolve_vars_if_possible(new_infer_ty)) - } else { - Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx)) - } + self.structurally_normalize_term(ty.into(), fulfill_cx).map(|term| term.expect_type()) } fn structurally_normalize_const<E: 'tcx>( @@ -52,14 +20,29 @@ impl<'tcx> At<'_, 'tcx> { ct: ty::Const<'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx, E>, ) -> Result<ty::Const<'tcx>, Vec<E>> { - assert!(!ct.is_ct_infer(), "should have resolved vars before calling"); + if self.infcx.tcx.features().generic_const_exprs() { + return Ok(super::evaluate_const(&self.infcx, ct, self.param_env)); + } + + self.structurally_normalize_term(ct.into(), fulfill_cx).map(|term| term.expect_const()) + } + + fn structurally_normalize_term<E: 'tcx>( + &self, + term: ty::Term<'tcx>, + fulfill_cx: &mut dyn TraitEngine<'tcx, E>, + ) -> Result<ty::Term<'tcx>, Vec<E>> { + assert!(!term.is_infer(), "should have resolved vars before calling"); if self.infcx.next_trait_solver() { - let ty::ConstKind::Unevaluated(..) = ct.kind() else { - return Ok(ct); - }; + if let None = term.to_alias_term() { + return Ok(term); + } - let new_infer_ct = self.infcx.next_const_var(self.cause.span); + let new_infer = match term.unpack() { + ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(), + ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(), + }; // We simply emit an `alias-eq` goal here, since that will take care of // normalizing the LHS of the projection until it is a rigid projection @@ -68,11 +51,7 @@ impl<'tcx> At<'_, 'tcx> { self.infcx.tcx, self.cause.clone(), self.param_env, - ty::PredicateKind::AliasRelate( - ct.into(), - new_infer_ct.into(), - ty::AliasRelationDirection::Equate, - ), + ty::PredicateKind::AliasRelate(term, new_infer, ty::AliasRelationDirection::Equate), ); fulfill_cx.register_predicate_obligation(self.infcx, obligation); @@ -81,11 +60,9 @@ impl<'tcx> At<'_, 'tcx> { return Err(errors); } - Ok(self.infcx.resolve_vars_if_possible(new_infer_ct)) - } else if self.infcx.tcx.features().generic_const_exprs() { - Ok(super::evaluate_const(&self.infcx, ct, self.param_env)) + Ok(self.infcx.resolve_vars_if_possible(new_infer)) } else { - Ok(self.normalize(ct).into_value_registering_obligations(self.infcx, fulfill_cx)) + Ok(self.normalize(term).into_value_registering_obligations(self.infcx, fulfill_cx)) } } } diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index da1045b664a..c9fb2a757e1 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,162 +1,85 @@ -use std::collections::BTreeMap; +use std::collections::{BTreeMap, VecDeque}; -use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::Diag; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; pub use rustc_infer::traits::util::*; use rustc_middle::bug; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use rustc_span::Span; use smallvec::{SmallVec, smallvec}; use tracing::debug; -/////////////////////////////////////////////////////////////////////////// -// `TraitAliasExpander` iterator -/////////////////////////////////////////////////////////////////////////// - -/// "Trait alias expansion" is the process of expanding a sequence of trait -/// references into another sequence by transitively following all trait -/// aliases. e.g. If you have bounds like `Foo + Send`, a trait alias -/// `trait Foo = Bar + Sync;`, and another trait alias -/// `trait Bar = Read + Write`, then the bounds would expand to -/// `Read + Write + Sync + Send`. -/// Expansion is done via a DFS (depth-first search), and the `visited` field -/// is used to avoid cycles. -pub struct TraitAliasExpander<'tcx> { - tcx: TyCtxt<'tcx>, - stack: Vec<TraitAliasExpansionInfo<'tcx>>, -} - -/// Stores information about the expansion of a trait via a path of zero or more trait aliases. -#[derive(Debug, Clone)] -pub struct TraitAliasExpansionInfo<'tcx> { - pub path: SmallVec<[(ty::PolyTraitRef<'tcx>, Span); 4]>, -} - -impl<'tcx> TraitAliasExpansionInfo<'tcx> { - fn new(trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - Self { path: smallvec![(trait_ref, span)] } - } - - /// Adds diagnostic labels to `diag` for the expansion path of a trait through all intermediate - /// trait aliases. - pub fn label_with_exp_info( - &self, - diag: &mut Diag<'_>, - top_label: &'static str, - use_desc: &str, - ) { - diag.span_label(self.top().1, top_label); - if self.path.len() > 1 { - for (_, sp) in self.path.iter().rev().skip(1).take(self.path.len() - 2) { - diag.span_label(*sp, format!("referenced here ({use_desc})")); - } - } - if self.top().1 != self.bottom().1 { - // When the trait object is in a return type these two spans match, we don't want - // redundant labels. - diag.span_label( - self.bottom().1, - format!("trait alias used in trait object type ({use_desc})"), - ); - } - } - - pub fn trait_ref(&self) -> ty::PolyTraitRef<'tcx> { - self.top().0 - } - - pub fn top(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.path.last().unwrap() - } - - pub fn bottom(&self) -> &(ty::PolyTraitRef<'tcx>, Span) { - self.path.first().unwrap() - } - - fn clone_and_push(&self, trait_ref: ty::PolyTraitRef<'tcx>, span: Span) -> Self { - let mut path = self.path.clone(); - path.push((trait_ref, span)); - - Self { path } - } -} - +/// Return the trait and projection predicates that come from eagerly expanding the +/// trait aliases in the list of clauses. For each trait predicate, record a stack +/// of spans that trace from the user-written trait alias bound. For projection predicates, +/// just record the span of the projection itself. +/// +/// For trait aliases, we don't deduplicte the predicates, since we currently do not +/// consider duplicated traits as a single trait for the purposes of our "one trait principal" +/// restriction; however, for projections we do deduplicate them. +/// +/// ```rust,ignore (fails) +/// trait Bar {} +/// trait Foo = Bar + Bar; +/// +/// let not_object_safe: dyn Foo; // bad, two `Bar` principals. +/// ``` pub fn expand_trait_aliases<'tcx>( tcx: TyCtxt<'tcx>, - trait_refs: impl Iterator<Item = (ty::PolyTraitRef<'tcx>, Span)>, -) -> TraitAliasExpander<'tcx> { - let items: Vec<_> = - trait_refs.map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)).collect(); - TraitAliasExpander { tcx, stack: items } -} - -impl<'tcx> TraitAliasExpander<'tcx> { - /// If `item` is a trait alias and its predicate has not yet been visited, then expands `item` - /// to the definition, pushes the resulting expansion onto `self.stack`, and returns `false`. - /// Otherwise, immediately returns `true` if `item` is a regular trait, or `false` if it is a - /// trait alias. - /// The return value indicates whether `item` should be yielded to the user. - fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { - let tcx = self.tcx; - let trait_ref = item.trait_ref(); - let pred = trait_ref.upcast(tcx); - - debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); - - // Don't recurse if this bound is not a trait alias. - let is_alias = tcx.is_trait_alias(trait_ref.def_id()); - if !is_alias { - return true; - } - - // Don't recurse if this trait alias is already on the stack for the DFS search. - let anon_pred = anonymize_predicate(tcx, pred); - if item - .path - .iter() - .rev() - .skip(1) - .any(|&(tr, _)| anonymize_predicate(tcx, tr.upcast(tcx)) == anon_pred) - { - return false; - } - - // Get components of trait alias. - let predicates = tcx.explicit_super_predicates_of(trait_ref.def_id()); - debug!(?predicates); - - let items = predicates.skip_binder().iter().rev().filter_map(|(pred, span)| { - pred.instantiate_supertrait(tcx, trait_ref) - .as_trait_clause() - .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) - }); - debug!("expand_trait_aliases: items={:?}", items.clone().collect::<Vec<_>>()); - - self.stack.extend(items); - - false - } -} - -impl<'tcx> Iterator for TraitAliasExpander<'tcx> { - type Item = TraitAliasExpansionInfo<'tcx>; - - fn size_hint(&self) -> (usize, Option<usize>) { - (self.stack.len(), None) - } - - fn next(&mut self) -> Option<TraitAliasExpansionInfo<'tcx>> { - while let Some(item) = self.stack.pop() { - if self.expand(&item) { - return Some(item); + clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>, +) -> ( + Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>, + Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, +) { + let mut trait_preds = vec![]; + let mut projection_preds = vec![]; + let mut seen_projection_preds = FxHashSet::default(); + + let mut queue: VecDeque<_> = clauses.into_iter().map(|(p, s)| (p, smallvec![s])).collect(); + + while let Some((clause, spans)) = queue.pop_front() { + match clause.kind().skip_binder() { + ty::ClauseKind::Trait(trait_pred) => { + if tcx.is_trait_alias(trait_pred.def_id()) { + queue.extend( + tcx.explicit_super_predicates_of(trait_pred.def_id()) + .iter_identity_copied() + .map(|(clause, span)| { + let mut spans = spans.clone(); + spans.push(span); + ( + clause.instantiate_supertrait( + tcx, + clause.kind().rebind(trait_pred.trait_ref), + ), + spans, + ) + }), + ); + } else { + trait_preds.push((clause.kind().rebind(trait_pred), spans)); + } } + ty::ClauseKind::Projection(projection_pred) => { + let projection_pred = clause.kind().rebind(projection_pred); + if !seen_projection_preds.insert(tcx.anonymize_bound_vars(projection_pred)) { + continue; + } + projection_preds.push((projection_pred, *spans.last().unwrap())); + } + ty::ClauseKind::RegionOutlives(..) + | ty::ClauseKind::TypeOutlives(..) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) + | ty::ClauseKind::HostEffect(..) => {} } - None } + + (trait_preds, projection_preds) } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 71088a598bb..5d041c2623a 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -6,13 +6,12 @@ use rustc_middle::query::Providers; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::{Clause, FnSig, ParamEnvAnd, PolyFnSig, Ty, TyCtxt, TypeFoldable}; use rustc_trait_selection::infer::InferCtxtBuilderExt; -use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{ AscribeUserType, type_op_ascribe_user_type_with_span, }; use rustc_trait_selection::traits::query::type_op::normalize::Normalize; use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate; -use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt}; +use rustc_trait_selection::traits::{Obligation, ObligationCause, ObligationCtxt}; pub(crate) fn provide(p: &mut Providers) { *p = Providers { @@ -43,10 +42,7 @@ where T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>>, { let (param_env, Normalize { value }) = key.into_parts(); - let Normalized { value, obligations } = - ocx.infcx.at(&ObligationCause::dummy(), param_env).query_normalize(value)?; - ocx.register_obligations(obligations); - Ok(value) + Ok(ocx.normalize(&ObligationCause::dummy(), param_env, value)) } fn type_op_normalize_ty<'tcx>( diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs index 6ce9969aefe..b00585d2922 100644 --- a/compiler/rustc_transmute/src/layout/tree.rs +++ b/compiler/rustc_transmute/src/layout/tree.rs @@ -197,6 +197,7 @@ pub(crate) mod rustc { match err { LayoutError::Unknown(..) | LayoutError::ReferencesError(..) + | LayoutError::TooGeneric(..) | LayoutError::NormalizationFailure(..) => Self::UnknownLayout, LayoutError::SizeOverflow(..) => Self::SizeOverflow, LayoutError::Cycle(err) => Self::TypeError(*err), diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 8f9f66db1bd..f71b924b177 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -1,8 +1,8 @@ use rustc_data_structures::fx::FxIndexSet; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::{self as hir, AmbigArg}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt}; use rustc_middle::{bug, span_bug}; @@ -187,7 +187,7 @@ fn associated_types_for_impl_traits_in_associated_fn( } impl<'tcx> Visitor<'tcx> for RPITVisitor { - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { if let hir::TyKind::OpaqueDef(opaq) = ty.kind && self.rpits.insert(opaq.def_id) { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 17be0bd0ab9..a04c7536118 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -104,14 +104,12 @@ fn map_error<'tcx>( // This is sometimes not a compile error if there are trivially false where clauses. // See `tests/ui/layout/trivial-bounds-sized.rs` for an example. assert!(field.layout.is_unsized(), "invalid layout error {err:#?}"); - if !field.ty.is_sized(cx.tcx(), cx.typing_env) { - let guar = cx.tcx().dcx().delayed_bug(format!( + if cx.typing_env.param_env.caller_bounds().is_empty() { + cx.tcx().dcx().delayed_bug(format!( "encountered unexpected unsized field in layout of {ty:?}: {field:#?}" )); - LayoutError::ReferencesError(guar) - } else { - LayoutError::Unknown(ty) } + LayoutError::Unknown(ty) } LayoutCalculatorError::EmptyUnion => { // This is always a compile error. @@ -146,6 +144,35 @@ fn univariant_uninterned<'tcx>( cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err)) } +fn validate_const_with_value<'tcx>( + const_: ty::Const<'tcx>, + ty: Ty<'tcx>, + cx: &LayoutCx<'tcx>, +) -> Result<ty::Const<'tcx>, &'tcx LayoutError<'tcx>> { + match const_.kind() { + ty::ConstKind::Value(..) => Ok(const_), + ty::ConstKind::Error(guar) => { + return Err(error(cx, LayoutError::ReferencesError(guar))); + } + ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => { + if !const_.has_param() { + bug!("no generic type found in the type: {ty:?}"); + } + return Err(error(cx, LayoutError::TooGeneric(ty))); + } + ty::ConstKind::Unevaluated(_) => { + if !const_.has_param() { + return Err(error(cx, LayoutError::Unknown(ty))); + } else { + return Err(error(cx, LayoutError::TooGeneric(ty))); + } + } + ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { + bug!("unexpected type: {ty:?}"); + } + } +} + fn layout_of_uncached<'tcx>( cx: &LayoutCx<'tcx>, ty: Ty<'tcx>, @@ -182,12 +209,13 @@ fn layout_of_uncached<'tcx>( &mut layout.backend_repr { if let Some(start) = start { - scalar.valid_range_mut().start = start - .try_to_bits(tcx, cx.typing_env) - .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; + scalar.valid_range_mut().start = + validate_const_with_value(start, ty, cx)? + .try_to_bits(tcx, cx.typing_env) + .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; } if let Some(end) = end { - let mut end = end + let mut end = validate_const_with_value(end, ty, cx)? .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; if !include_end { @@ -319,17 +347,13 @@ fn layout_of_uncached<'tcx>( } // Arrays and slices. - ty::Array(element, mut count) => { - if count.has_aliases() { - count = tcx.normalize_erasing_regions(cx.typing_env, count); - if count.has_aliases() { - return Err(error(cx, LayoutError::Unknown(ty))); - } - } - - let count = count + ty::Array(element, count) => { + let count = validate_const_with_value(count, ty, cx)? + .to_valtree() + .0 .try_to_target_usize(tcx) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; + let element = cx.layout_of(element)?; let size = element .size @@ -687,6 +711,9 @@ fn layout_of_uncached<'tcx>( // Types with no meaningful known layout. ty::Alias(..) => { + if ty.has_param() { + return Err(error(cx, LayoutError::TooGeneric(ty))); + } // NOTE(eddyb) `layout_of` query should've normalized these away, // if that was possible, so there's no reason to try again here. return Err(error(cx, LayoutError::Unknown(ty))); @@ -696,7 +723,11 @@ fn layout_of_uncached<'tcx>( bug!("Layout::compute: unexpected type `{}`", ty) } - ty::Placeholder(..) | ty::Param(_) => { + ty::Param(_) => { + return Err(error(cx, LayoutError::TooGeneric(ty))); + } + + ty::Placeholder(..) => { return Err(error(cx, LayoutError::Unknown(ty))); } }) diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index 10b164eae02..74e4e035c87 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -3,9 +3,10 @@ use std::ops::ControlFlow; use derive_where::derive_where; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; +use crate::data_structures::DelayedMap; use crate::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region}; use crate::inherent::*; -use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::{self as ty, Interner}; /// A closure can be modeled as a struct that looks like: @@ -471,6 +472,7 @@ impl<I: Interner> CoroutineClosureSignature<I> { interner: cx, region: env_region, debruijn: ty::INNERMOST, + cache: Default::default(), }); Ty::new_tup_from_iter( cx, @@ -498,6 +500,10 @@ struct FoldEscapingRegions<I: Interner> { interner: I, debruijn: ty::DebruijnIndex, region: I::Region, + + // Depends on `debruijn` because we may have types with regions of different + // debruijn depths depending on the binders we've entered. + cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>, } impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> { @@ -505,6 +511,18 @@ impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> { self.interner } + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + if !t.has_vars_bound_at_or_above(self.debruijn) { + t + } else if let Some(&t) = self.cache.get(&(self.debruijn, t)) { + t + } else { + let res = t.super_fold_with(self); + assert!(self.cache.insert((self.debruijn, t), res)); + res + } + } + fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> where T: TypeFoldable<I>, diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 71c3646498b..3213638afb2 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -47,6 +47,7 @@ use std::ops::ControlFlow; use rustc_ast_ir::visit::VisitorResult; use rustc_ast_ir::{try_visit, walk_visitable_list}; use rustc_index::{Idx, IndexVec}; +use smallvec::SmallVec; use thin_vec::ThinVec; use crate::data_structures::Lrc; @@ -192,6 +193,13 @@ impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for ThinVec<T> { } } +impl<I: Interner, T: TypeVisitable<I>, const N: usize> TypeVisitable<I> for SmallVec<[T; N]> { + fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result { + walk_visitable_list!(visitor, self.iter()); + V::Result::output() + } +} + // `TypeFoldable` isn't impl'd for `&[T]`. It doesn't make sense in the general // case, because we can't return a new slice. But note that there are a couple // of trivial impls of `TypeFoldable` for specific slice types elsewhere. diff --git a/library/Cargo.lock b/library/Cargo.lock index 7b9081d46a0..30875482dc0 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -72,6 +72,10 @@ dependencies = [ [[package]] name = "core" version = "0.0.0" + +[[package]] +name = "coretests" +version = "0.0.0" dependencies = [ "rand", "rand_xorshift", diff --git a/library/Cargo.toml b/library/Cargo.toml index e59aa518804..1205f7c9ed6 100644 --- a/library/Cargo.toml +++ b/library/Cargo.toml @@ -3,6 +3,7 @@ resolver = "1" members = [ "std", "sysroot", + "coretests", ] exclude = [ diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs index b8119c9f0eb..5b15aaeddbc 100644 --- a/library/alloc/benches/btree/map.rs +++ b/library/alloc/benches/btree/map.rs @@ -353,6 +353,7 @@ pub fn iter_10k(b: &mut Bencher) { } #[bench] +#[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM pub fn iter_1m(b: &mut Bencher) { bench_iter(b, 1_000, 1_000_000); } diff --git a/library/alloc/benches/slice.rs b/library/alloc/benches/slice.rs index 48c74c4491d..c45c3722712 100644 --- a/library/alloc/benches/slice.rs +++ b/library/alloc/benches/slice.rs @@ -366,14 +366,25 @@ rotate!(rotate_medium_half, gen_random, 9158, 9158 / 2); rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158 / 2 + 1); // Intended to use more RAM than the machine has cache +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by1, gen_random, 5 * 1024 * 1024, 1); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by9199_u64, gen_random, 5 * 1024 * 1024, 9199); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5 * 1024 * 1024, 9199); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by9199_strings, gen_strings, 5 * 1024 * 1024, 9199); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by9199_big, gen_big_random, 5 * 1024 * 1024, 9199); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by1234577_u64, gen_random, 5 * 1024 * 1024, 1234577); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5 * 1024 * 1024, 1234577); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by1234577_strings, gen_strings, 5 * 1024 * 1024, 1234577); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_by1234577_big, gen_big_random, 5 * 1024 * 1024, 1234577); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_half, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2); +#[cfg(not(target_os = "emscripten"))] // hits an OOM rotate!(rotate_huge_half_plus_one, gen_random, 5 * 1024 * 1024, 5 * 1024 * 1024 / 2 + 1); diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index d29ffae9d70..a725ad6894b 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -547,6 +547,11 @@ fn bench_in_place_collect_droppable(b: &mut Bencher) { }) } +// node.js gives out of memory error to use with length 1_100_000 +#[cfg(target_os = "emscripten")] +const LEN: usize = 4096; + +#[cfg(not(target_os = "emscripten"))] const LEN: usize = 16384; #[bench] diff --git a/library/alloc/src/bstr.rs b/library/alloc/src/bstr.rs new file mode 100644 index 00000000000..61e61019b50 --- /dev/null +++ b/library/alloc/src/bstr.rs @@ -0,0 +1,702 @@ +//! The `ByteStr` and `ByteString` types and trait implementations. + +// This could be more fine-grained. +#![cfg(not(no_global_oom_handling))] + +use core::borrow::{Borrow, BorrowMut}; +#[unstable(feature = "bstr", issue = "134915")] +pub use core::bstr::ByteStr; +use core::bstr::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord}; +use core::cmp::Ordering; +use core::ops::{ + Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, + RangeTo, RangeToInclusive, +}; +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +use core::str::FromStr; +use core::{fmt, hash}; + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +use crate::borrow::{Cow, ToOwned}; +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +use crate::boxed::Box; +#[cfg(not(no_rc))] +use crate::rc::Rc; +use crate::string::String; +#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))] +use crate::sync::Arc; +use crate::vec::Vec; + +/// A wrapper for `Vec<u8>` representing a human-readable string that's conventionally, but not +/// always, UTF-8. +/// +/// Unlike `String`, this type permits non-UTF-8 contents, making it suitable for user input, +/// non-native filenames (as `Path` only supports native filenames), and other applications that +/// need to round-trip whatever data the user provides. +/// +/// A `ByteString` owns its contents and can grow and shrink, like a `Vec` or `String`. For a +/// borrowed byte string, see [`ByteStr`](../../std/bstr/struct.ByteStr.html). +/// +/// `ByteString` implements `Deref` to `&Vec<u8>`, so all methods available on `&Vec<u8>` are +/// available on `ByteString`. Similarly, `ByteString` implements `DerefMut` to `&mut Vec<u8>`, +/// so you can modify a `ByteString` using any method available on `&mut Vec<u8>`. +/// +/// The `Debug` and `Display` implementations for `ByteString` are the same as those for `ByteStr`, +/// showing invalid UTF-8 as hex escapes or the Unicode replacement character, respectively. +#[unstable(feature = "bstr", issue = "134915")] +#[repr(transparent)] +#[derive(Clone)] +#[doc(alias = "BString")] +pub struct ByteString(pub Vec<u8>); + +impl ByteString { + #[inline] + pub(crate) fn as_bytes(&self) -> &[u8] { + &self.0 + } + + #[inline] + pub(crate) fn as_bytestr(&self) -> &ByteStr { + ByteStr::new(&self.0) + } + + #[inline] + pub(crate) fn as_mut_bytestr(&mut self) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Deref for ByteString { + type Target = Vec<u8>; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl DerefMut for ByteString { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for ByteString {} + +#[unstable(feature = "bstr", issue = "134915")] +impl fmt::Debug for ByteString { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.as_bytestr(), f) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl fmt::Display for ByteString { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.as_bytestr(), f) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl AsRef<[u8]> for ByteString { + #[inline] + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl AsRef<ByteStr> for ByteString { + #[inline] + fn as_ref(&self) -> &ByteStr { + self.as_bytestr() + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl AsMut<[u8]> for ByteString { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl AsMut<ByteStr> for ByteString { + #[inline] + fn as_mut(&mut self) -> &mut ByteStr { + self.as_mut_bytestr() + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Borrow<[u8]> for ByteString { + #[inline] + fn borrow(&self) -> &[u8] { + &self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Borrow<ByteStr> for ByteString { + #[inline] + fn borrow(&self) -> &ByteStr { + self.as_bytestr() + } +} + +// `impl Borrow<ByteStr> for Vec<u8>` omitted to avoid inference failures +// `impl Borrow<ByteStr> for String` omitted to avoid inference failures + +#[unstable(feature = "bstr", issue = "134915")] +impl BorrowMut<[u8]> for ByteString { + #[inline] + fn borrow_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl BorrowMut<ByteStr> for ByteString { + #[inline] + fn borrow_mut(&mut self) -> &mut ByteStr { + self.as_mut_bytestr() + } +} + +// `impl BorrowMut<ByteStr> for Vec<u8>` omitted to avoid inference failures + +#[unstable(feature = "bstr", issue = "134915")] +impl Default for ByteString { + fn default() -> Self { + ByteString(Vec::new()) + } +} + +// Omitted due to inference failures +// +// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +// #[unstable(feature = "bstr", issue = "134915")] +// impl<'a, const N: usize> From<&'a [u8; N]> for ByteString { +// #[inline] +// fn from(s: &'a [u8; N]) -> Self { +// ByteString(s.as_slice().to_vec()) +// } +// } +// +// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +// #[unstable(feature = "bstr", issue = "134915")] +// impl<const N: usize> From<[u8; N]> for ByteString { +// #[inline] +// fn from(s: [u8; N]) -> Self { +// ByteString(s.as_slice().to_vec()) +// } +// } +// +// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +// #[unstable(feature = "bstr", issue = "134915")] +// impl<'a> From<&'a [u8]> for ByteString { +// #[inline] +// fn from(s: &'a [u8]) -> Self { +// ByteString(s.to_vec()) +// } +// } +// +// #[unstable(feature = "bstr", issue = "134915")] +// impl From<Vec<u8>> for ByteString { +// #[inline] +// fn from(s: Vec<u8>) -> Self { +// ByteString(s) +// } +// } + +#[unstable(feature = "bstr", issue = "134915")] +impl From<ByteString> for Vec<u8> { + #[inline] + fn from(s: ByteString) -> Self { + s.0 + } +} + +// Omitted due to inference failures +// +// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +// #[unstable(feature = "bstr", issue = "134915")] +// impl<'a> From<&'a str> for ByteString { +// #[inline] +// fn from(s: &'a str) -> Self { +// ByteString(s.as_bytes().to_vec()) +// } +// } +// +// #[unstable(feature = "bstr", issue = "134915")] +// impl From<String> for ByteString { +// #[inline] +// fn from(s: String) -> Self { +// ByteString(s.into_bytes()) +// } +// } + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> From<&'a ByteStr> for ByteString { + #[inline] + fn from(s: &'a ByteStr) -> Self { + ByteString(s.0.to_vec()) + } +} + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> From<ByteString> for Cow<'a, ByteStr> { + #[inline] + fn from(s: ByteString) -> Self { + Cow::Owned(s) + } +} + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> From<&'a ByteString> for Cow<'a, ByteStr> { + #[inline] + fn from(s: &'a ByteString) -> Self { + Cow::Borrowed(s.as_bytestr()) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl FromIterator<char> for ByteString { + #[inline] + fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self { + ByteString(iter.into_iter().collect::<String>().into_bytes()) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl FromIterator<u8> for ByteString { + #[inline] + fn from_iter<T: IntoIterator<Item = u8>>(iter: T) -> Self { + ByteString(iter.into_iter().collect()) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> FromIterator<&'a str> for ByteString { + #[inline] + fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self { + ByteString(iter.into_iter().collect::<String>().into_bytes()) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> FromIterator<&'a [u8]> for ByteString { + #[inline] + fn from_iter<T: IntoIterator<Item = &'a [u8]>>(iter: T) -> Self { + let mut buf = Vec::new(); + for b in iter { + buf.extend_from_slice(b); + } + ByteString(buf) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> FromIterator<&'a ByteStr> for ByteString { + #[inline] + fn from_iter<T: IntoIterator<Item = &'a ByteStr>>(iter: T) -> Self { + let mut buf = Vec::new(); + for b in iter { + buf.extend_from_slice(&b.0); + } + ByteString(buf) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl FromIterator<ByteString> for ByteString { + #[inline] + fn from_iter<T: IntoIterator<Item = ByteString>>(iter: T) -> Self { + let mut buf = Vec::new(); + for mut b in iter { + buf.append(&mut b.0); + } + ByteString(buf) + } +} + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl FromStr for ByteString { + type Err = core::convert::Infallible; + + #[inline] + fn from_str(s: &str) -> Result<Self, Self::Err> { + Ok(ByteString(s.as_bytes().to_vec())) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<usize> for ByteString { + type Output = u8; + + #[inline] + fn index(&self, idx: usize) -> &u8 { + &self.0[idx] + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeFull> for ByteString { + type Output = ByteStr; + + #[inline] + fn index(&self, _: RangeFull) -> &ByteStr { + self.as_bytestr() + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<Range<usize>> for ByteString { + type Output = ByteStr; + + #[inline] + fn index(&self, r: Range<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeInclusive<usize>> for ByteString { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeInclusive<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeFrom<usize>> for ByteString { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeFrom<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeTo<usize>> for ByteString { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeTo<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeToInclusive<usize>> for ByteString { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeToInclusive<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<usize> for ByteString { + #[inline] + fn index_mut(&mut self, idx: usize) -> &mut u8 { + &mut self.0[idx] + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeFull> for ByteString { + #[inline] + fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr { + self.as_mut_bytestr() + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<Range<usize>> for ByteString { + #[inline] + fn index_mut(&mut self, r: Range<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeInclusive<usize>> for ByteString { + #[inline] + fn index_mut(&mut self, r: RangeInclusive<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeFrom<usize>> for ByteString { + #[inline] + fn index_mut(&mut self, r: RangeFrom<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeTo<usize>> for ByteString { + #[inline] + fn index_mut(&mut self, r: RangeTo<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeToInclusive<usize>> for ByteString { + #[inline] + fn index_mut(&mut self, r: RangeToInclusive<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl hash::Hash for ByteString { + #[inline] + fn hash<H: hash::Hasher>(&self, state: &mut H) { + self.0.hash(state); + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Eq for ByteString {} + +#[unstable(feature = "bstr", issue = "134915")] +impl PartialEq for ByteString { + #[inline] + fn eq(&self, other: &ByteString) -> bool { + self.0 == other.0 + } +} + +macro_rules! impl_partial_eq_ord_cow { + ($lhs:ty, $rhs:ty) => { + #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = (&**other).as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = (&**self).as_ref(); + PartialEq::eq(this, other.as_bytes()) + } + } + + #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> { + let other: &[u8] = (&**other).as_ref(); + PartialOrd::partial_cmp(self.as_bytes(), other) + } + } + + #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> { + let this: &[u8] = (&**self).as_ref(); + PartialOrd::partial_cmp(this, other.as_bytes()) + } + } + }; +} + +// PartialOrd with `Vec<u8>` omitted to avoid inference failures +impl_partial_eq!(ByteString, Vec<u8>); +// PartialOrd with `[u8]` omitted to avoid inference failures +impl_partial_eq!(ByteString, [u8]); +// PartialOrd with `&[u8]` omitted to avoid inference failures +impl_partial_eq!(ByteString, &[u8]); +// PartialOrd with `String` omitted to avoid inference failures +impl_partial_eq!(ByteString, String); +// PartialOrd with `str` omitted to avoid inference failures +impl_partial_eq!(ByteString, str); +// PartialOrd with `&str` omitted to avoid inference failures +impl_partial_eq!(ByteString, &str); +impl_partial_eq_ord!(ByteString, ByteStr); +impl_partial_eq_ord!(ByteString, &ByteStr); +// PartialOrd with `[u8; N]` omitted to avoid inference failures +impl_partial_eq_n!(ByteString, [u8; N]); +// PartialOrd with `&[u8; N]` omitted to avoid inference failures +impl_partial_eq_n!(ByteString, &[u8; N]); +impl_partial_eq_ord_cow!(ByteString, Cow<'_, ByteStr>); +impl_partial_eq_ord_cow!(ByteString, Cow<'_, str>); +impl_partial_eq_ord_cow!(ByteString, Cow<'_, [u8]>); + +#[unstable(feature = "bstr", issue = "134915")] +impl Ord for ByteString { + #[inline] + fn cmp(&self, other: &ByteString) -> Ordering { + Ord::cmp(&self.0, &other.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl PartialOrd for ByteString { + #[inline] + fn partial_cmp(&self, other: &ByteString) -> Option<Ordering> { + PartialOrd::partial_cmp(&self.0, &other.0) + } +} + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl ToOwned for ByteStr { + type Owned = ByteString; + + #[inline] + fn to_owned(&self) -> ByteString { + ByteString(self.0.to_vec()) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl TryFrom<ByteString> for String { + type Error = crate::string::FromUtf8Error; + + #[inline] + fn try_from(s: ByteString) -> Result<Self, Self::Error> { + String::from_utf8(s.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> TryFrom<&'a ByteString> for &'a str { + type Error = crate::str::Utf8Error; + + #[inline] + fn try_from(s: &'a ByteString) -> Result<Self, Self::Error> { + crate::str::from_utf8(s.0.as_slice()) + } +} + +// Additional impls for `ByteStr` that require types from `alloc`: + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl Clone for Box<ByteStr> { + #[inline] + fn clone(&self) -> Self { + Self::from(Box::<[u8]>::from(&self.0)) + } +} + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> { + #[inline] + fn from(s: &'a ByteStr) -> Self { + Cow::Borrowed(s) + } +} + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl From<Box<[u8]>> for Box<ByteStr> { + #[inline] + fn from(s: Box<[u8]>) -> Box<ByteStr> { + // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`. + unsafe { Box::from_raw(Box::into_raw(s) as _) } + } +} + +#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100 +#[unstable(feature = "bstr", issue = "134915")] +impl From<Box<ByteStr>> for Box<[u8]> { + #[inline] + fn from(s: Box<ByteStr>) -> Box<[u8]> { + // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`. + unsafe { Box::from_raw(Box::into_raw(s) as _) } + } +} + +#[unstable(feature = "bstr", issue = "134915")] +#[cfg(not(no_rc))] +impl From<Rc<[u8]>> for Rc<ByteStr> { + #[inline] + fn from(s: Rc<[u8]>) -> Rc<ByteStr> { + // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`. + unsafe { Rc::from_raw(Rc::into_raw(s) as _) } + } +} + +#[unstable(feature = "bstr", issue = "134915")] +#[cfg(not(no_rc))] +impl From<Rc<ByteStr>> for Rc<[u8]> { + #[inline] + fn from(s: Rc<ByteStr>) -> Rc<[u8]> { + // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`. + unsafe { Rc::from_raw(Rc::into_raw(s) as _) } + } +} + +#[unstable(feature = "bstr", issue = "134915")] +#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))] +impl From<Arc<[u8]>> for Arc<ByteStr> { + #[inline] + fn from(s: Arc<[u8]>) -> Arc<ByteStr> { + // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`. + unsafe { Arc::from_raw(Arc::into_raw(s) as _) } + } +} + +#[unstable(feature = "bstr", issue = "134915")] +#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))] +impl From<Arc<ByteStr>> for Arc<[u8]> { + #[inline] + fn from(s: Arc<ByteStr>) -> Arc<[u8]> { + // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`. + unsafe { Arc::from_raw(Arc::into_raw(s) as _) } + } +} + +// PartialOrd with `Vec<u8>` omitted to avoid inference failures +impl_partial_eq!(ByteStr, Vec<u8>); +// PartialOrd with `String` omitted to avoid inference failures +impl_partial_eq!(ByteStr, String); +impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, ByteStr>); +impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, str>); +impl_partial_eq_ord_cow!(&'a ByteStr, Cow<'a, [u8]>); + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> TryFrom<&'a ByteStr> for String { + type Error = core::str::Utf8Error; + + #[inline] + fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> { + Ok(core::str::from_utf8(&s.0)?.into()) + } +} diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 9660023d694..041f80c1f2c 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1442,20 +1442,20 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> { /// /// let mut set = BTreeSet::from([1, 2, 3, 4]); /// - /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) }; + /// let mut cursor = set.upper_bound_mut(Bound::Included(&3)); /// assert_eq!(cursor.peek_prev(), Some(&3)); /// assert_eq!(cursor.peek_next(), Some(&4)); /// - /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) }; + /// let mut cursor = set.upper_bound_mut(Bound::Excluded(&3)); /// assert_eq!(cursor.peek_prev(), Some(&2)); /// assert_eq!(cursor.peek_next(), Some(&3)); /// - /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) }; + /// let mut cursor = set.upper_bound_mut(Bound::Unbounded); /// assert_eq!(cursor.peek_prev(), Some(&4)); /// assert_eq!(cursor.peek_next(), None); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] - pub unsafe fn upper_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> + pub fn upper_bound_mut<Q: ?Sized>(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> where T: Borrow<Q> + Ord, Q: Ord, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 0b6a55297e1..1c33f8f60d8 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1735,6 +1735,52 @@ impl<T, A: Allocator> VecDeque<T, A> { } } + /// Removes and returns the first element from the deque if the predicate + /// returns `true`, or [`None`] if the predicate returns false or the deque + /// is empty (the predicate will not be called in that case). + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_deque_pop_if)] + /// use std::collections::VecDeque; + /// + /// let mut deque: VecDeque<i32> = vec![0, 1, 2, 3, 4].into(); + /// let pred = |x: &mut i32| *x % 2 == 0; + /// + /// assert_eq!(deque.pop_front_if(pred), Some(0)); + /// assert_eq!(deque, [1, 2, 3, 4]); + /// assert_eq!(deque.pop_front_if(pred), None); + /// ``` + #[unstable(feature = "vec_deque_pop_if", issue = "135889")] + pub fn pop_front_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> { + let first = self.front_mut()?; + if predicate(first) { self.pop_front() } else { None } + } + + /// Removes and returns the last element from the deque if the predicate + /// returns `true`, or [`None`] if the predicate returns false or the deque + /// is empty (the predicate will not be called in that case). + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_deque_pop_if)] + /// use std::collections::VecDeque; + /// + /// let mut deque: VecDeque<i32> = vec![0, 1, 2, 3, 4].into(); + /// let pred = |x: &mut i32| *x % 2 == 0; + /// + /// assert_eq!(deque.pop_back_if(pred), Some(4)); + /// assert_eq!(deque, [0, 1, 2, 3]); + /// assert_eq!(deque.pop_back_if(pred), None); + /// ``` + #[unstable(feature = "vec_deque_pop_if", issue = "135889")] + pub fn pop_back_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> { + let first = self.back_mut()?; + if predicate(first) { self.pop_back() } else { None } + } + /// Prepends an element to the deque. /// /// # Examples diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index b4f08debc93..28e4217e303 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -102,6 +102,8 @@ #![feature(async_fn_traits)] #![feature(async_iterator)] #![feature(box_uninit_write)] +#![feature(bstr)] +#![feature(bstr_internals)] #![feature(clone_to_uninit)] #![feature(coerce_unsized)] #![feature(const_eval_select)] @@ -228,6 +230,8 @@ mod boxed { pub use std::boxed::Box; } pub mod borrow; +#[unstable(feature = "bstr", issue = "134915")] +pub mod bstr; pub mod collections; #[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))] pub mod ffi; diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index cd2afd7a473..54673ceb1da 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2511,9 +2511,9 @@ impl<T, A: Allocator> Vec<T, A> { } } - /// Removes and returns the last element in a vector if the predicate + /// Removes and returns the last element from a vector if the predicate /// returns `true`, or [`None`] if the predicate returns false or the vector - /// is empty. + /// is empty (the predicate will not be called in that case). /// /// # Examples /// @@ -2528,12 +2528,9 @@ impl<T, A: Allocator> Vec<T, A> { /// assert_eq!(vec.pop_if(pred), None); /// ``` #[unstable(feature = "vec_pop_if", issue = "122741")] - pub fn pop_if<F>(&mut self, f: F) -> Option<T> - where - F: FnOnce(&mut T) -> bool, - { + pub fn pop_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option<T> { let last = self.last_mut()?; - if f(last) { self.pop() } else { None } + if predicate(last) { self.pop() } else { None } } /// Moves all the elements of `other` into `self`, leaving `other` empty. @@ -2574,9 +2571,11 @@ impl<T, A: Allocator> Vec<T, A> { self.len += count; } - /// Removes the specified range from the vector in bulk, returning all - /// removed elements as an iterator. If the iterator is dropped before - /// being fully consumed, it drops the remaining removed elements. + /// Removes the subslice indicated by the given range from the vector, + /// returning a double-ended iterator over the removed subslice. + /// + /// If the iterator is dropped before being fully consumed, + /// it drops the remaining removed elements. /// /// The returned iterator keeps a mutable borrow on the vector to optimize /// its implementation. @@ -3016,10 +3015,9 @@ impl<T: Clone, A: Allocator> Vec<T, A> { /// Iterates over the slice `other`, clones each element, and then appends /// it to this `Vec`. The `other` slice is traversed in-order. /// - /// Note that this function is same as [`extend`] except that it is - /// specialized to work with slices instead. If and when Rust gets - /// specialization this function will likely be deprecated (but still - /// available). + /// Note that this function is the same as [`extend`], + /// except that it also works with slice elements that are Clone but not Copy. + /// If Rust gets specialization this function may be deprecated. /// /// # Examples /// diff --git a/library/alloc/tests/collections/binary_heap.rs b/library/alloc/tests/collections/binary_heap.rs index 55405ffe8c4..95f4c3e614f 100644 --- a/library/alloc/tests/collections/binary_heap.rs +++ b/library/alloc/tests/collections/binary_heap.rs @@ -502,9 +502,7 @@ fn test_retain_catch_unwind() { // even if the order might not be correct. // // Destructors must be called exactly once per element. -// FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(target_os = "emscripten"))] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_safe() { use std::cmp; diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 393bdfe48b7..391ff04a4b8 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -38,6 +38,7 @@ #![feature(str_as_str)] #![feature(strict_provenance_lints)] #![feature(vec_pop_if)] +#![feature(vec_deque_pop_if)] #![feature(unique_rc_arc)] #![feature(macro_metavar_expr_concat)] #![allow(internal_features)] @@ -93,9 +94,6 @@ fn test_rng() -> rand_xorshift::XorShiftRng { rand::SeedableRng::from_seed(seed) } -// FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten. -// See https://github.com/kripken/emscripten-fastcomp/issues/169 -#[cfg(not(target_os = "emscripten"))] #[test] fn test_boxed_hasher() { let ordinary_hash = hash(&5u32); diff --git a/library/alloc/tests/slice.rs b/library/alloc/tests/slice.rs index 9625e3d2b5e..f990a41b679 100644 --- a/library/alloc/tests/slice.rs +++ b/library/alloc/tests/slice.rs @@ -1414,7 +1414,6 @@ fn test_box_slice_clone() { #[test] #[allow(unused_must_use)] // here, we care about the side effects of `.clone()` -#[cfg_attr(target_os = "emscripten", ignore)] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_box_slice_clone_panics() { use std::sync::Arc; diff --git a/library/alloc/tests/sort/tests.rs b/library/alloc/tests/sort/tests.rs index 4cc79010e8f..d321f8df518 100644 --- a/library/alloc/tests/sort/tests.rs +++ b/library/alloc/tests/sort/tests.rs @@ -11,7 +11,14 @@ use crate::sort::{Sort, known_good_stable_sort, patterns}; #[cfg(miri)] const TEST_LENGTHS: &[usize] = &[2, 3, 4, 7, 10, 15, 20, 24, 33, 50, 100, 171, 300]; -#[cfg(not(miri))] +// node.js gives out of memory error to use with length 1_100_000 +#[cfg(all(not(miri), target_os = "emscripten"))] +const TEST_LENGTHS: &[usize] = &[ + 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 20, 24, 30, 32, 33, 35, 50, 100, 200, 500, 1_000, + 2_048, 5_000, 10_000, 100_000, +]; + +#[cfg(all(not(miri), not(target_os = "emscripten")))] const TEST_LENGTHS: &[usize] = &[ 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 20, 24, 30, 32, 33, 35, 50, 100, 200, 500, 1_000, 2_048, 5_000, 10_000, 100_000, 1_100_000, diff --git a/library/alloc/tests/sync.rs b/library/alloc/tests/sync.rs index 7a9a4abfdc6..6d3ab1b1d11 100644 --- a/library/alloc/tests/sync.rs +++ b/library/alloc/tests/sync.rs @@ -128,6 +128,7 @@ fn try_unwrap() { } #[test] +#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads fn into_inner() { for _ in 0..100 // ^ Increase chances of hitting potential race conditions diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index b24daec2968..fe1db56414e 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1587,9 +1587,7 @@ fn extract_if_complex() { } } -// FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(target_os = "emscripten"))] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn extract_if_consumed_panic() { use std::rc::Rc; @@ -1640,9 +1638,7 @@ fn extract_if_consumed_panic() { } } -// FIXME: Re-enable emscripten once it can catch panics #[test] -#[cfg(not(target_os = "emscripten"))] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn extract_if_unconsumed_panic() { use std::rc::Rc; diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index 4b8d3c735f7..1b03c29e5bd 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -81,6 +81,45 @@ fn test_parameterized<T: Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) { } #[test] +fn test_pop_if() { + let mut deq: VecDeque<_> = vec![0, 1, 2, 3, 4].into(); + let pred = |x: &mut i32| *x % 2 == 0; + + assert_eq!(deq.pop_front_if(pred), Some(0)); + assert_eq!(deq, [1, 2, 3, 4]); + + assert_eq!(deq.pop_front_if(pred), None); + assert_eq!(deq, [1, 2, 3, 4]); + + assert_eq!(deq.pop_back_if(pred), Some(4)); + assert_eq!(deq, [1, 2, 3]); + + assert_eq!(deq.pop_back_if(pred), None); + assert_eq!(deq, [1, 2, 3]); +} + +#[test] +fn test_pop_if_empty() { + let mut deq = VecDeque::<i32>::new(); + assert_eq!(deq.pop_front_if(|_| true), None); + assert_eq!(deq.pop_back_if(|_| true), None); + assert!(deq.is_empty()); +} + +#[test] +fn test_pop_if_mutates() { + let mut v: VecDeque<_> = vec![-1, 1].into(); + let pred = |x: &mut i32| { + *x *= 2; + false + }; + assert_eq!(v.pop_front_if(pred), None); + assert_eq!(v, [-2, 1]); + assert_eq!(v.pop_back_if(pred), None); + assert_eq!(v, [-2, 2]); +} + +#[test] fn test_push_front_grow() { let mut deq = VecDeque::new(); for i in 0..66 { diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 46c55c437cc..b7c6db6c78d 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -15,19 +15,6 @@ edition = "2021" test = false bench = false -[[test]] -name = "coretests" -path = "tests/lib.rs" - -[[bench]] -name = "corebenches" -path = "benches/lib.rs" -test = true - -[dev-dependencies] -rand = { version = "0.8.5", default-features = false } -rand_xorshift = { version = "0.3.0", default-features = false } - [features] # Make panics and failed asserts immediately abort without formatting any message panic_immediate_abort = [] diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index cb130f60cec..81d828a971c 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -1,6 +1,14 @@ #![doc = include_str!("../../stdarch/crates/core_arch/src/core_arch_docs.md")] -#[allow(unused_imports)] +#[allow( + // some targets don't have anything to reexport, which + // makes the `pub use` unused and unreachable, allow + // both lints as to not have `#[cfg]`s + // + // cf. https://github.com/rust-lang/rust/pull/116033#issuecomment-1760085575 + unused_imports, + unreachable_pub +)] #[stable(feature = "simd_arch", since = "1.27.0")] pub use crate::core_arch::arch::*; diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 2ae5ded1fd5..28329bb0908 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -156,7 +156,6 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T; 1] { /// The error type returned when a conversion from a slice to an array fails. #[stable(feature = "try_from", since = "1.34.0")] -#[rustc_allowed_through_unstable_modules] #[derive(Debug, Copy, Clone)] pub struct TryFromSliceError(()); @@ -893,7 +892,7 @@ impl<T> Guard<'_, T> { /// /// No more than N elements must be initialized. #[inline] - pub unsafe fn push_unchecked(&mut self, item: T) { + pub(crate) unsafe fn push_unchecked(&mut self, item: T) { // SAFETY: If `initialized` was correct before and the caller does not // invoke this method more than N times then writes will be in-bounds // and slots will not be initialized more than once. diff --git a/library/core/src/bstr.rs b/library/core/src/bstr.rs new file mode 100644 index 00000000000..74e07f3d242 --- /dev/null +++ b/library/core/src/bstr.rs @@ -0,0 +1,581 @@ +//! The `ByteStr` type and trait implementations. + +use crate::borrow::{Borrow, BorrowMut}; +use crate::cmp::Ordering; +use crate::ops::{ + Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, + RangeTo, RangeToInclusive, +}; +use crate::{fmt, hash}; + +/// A wrapper for `&[u8]` representing a human-readable string that's conventionally, but not +/// always, UTF-8. +/// +/// Unlike `&str`, this type permits non-UTF-8 contents, making it suitable for user input, +/// non-native filenames (as `Path` only supports native filenames), and other applications that +/// need to round-trip whatever data the user provides. +/// +/// For an owned, growable byte string buffer, use +/// [`ByteString`](../../std/bstr/struct.ByteString.html). +/// +/// `ByteStr` implements `Deref` to `[u8]`, so all methods available on `[u8]` are available on +/// `ByteStr`. +/// +/// # Representation +/// +/// A `&ByteStr` has the same representation as a `&str`. That is, a `&ByteStr` is a wide pointer +/// which includes a pointer to some bytes and a length. +/// +/// # Trait implementations +/// +/// The `ByteStr` type has a number of trait implementations, and in particular, defines equality +/// and comparisons between `&ByteStr`, `&str`, and `&[u8]`, for convenience. +/// +/// The `Debug` implementation for `ByteStr` shows its bytes as a normal string, with invalid UTF-8 +/// presented as hex escape sequences. +/// +/// The `Display` implementation behaves as if the `ByteStr` were first lossily converted to a +/// `str`, with invalid UTF-8 presented as the Unicode replacement character: � +/// +#[unstable(feature = "bstr", issue = "134915")] +#[repr(transparent)] +#[doc(alias = "BStr")] +pub struct ByteStr(pub [u8]); + +impl ByteStr { + /// Creates a `ByteStr` slice from anything that can be converted to a byte slice. + /// + /// This is a zero-cost conversion. + /// + /// # Example + /// + /// You can create a `ByteStr` from a byte array, a byte slice or a string slice: + /// + /// ``` + /// # #![feature(bstr)] + /// # use std::bstr::ByteStr; + /// let a = ByteStr::new(b"abc"); + /// let b = ByteStr::new(&b"abc"[..]); + /// let c = ByteStr::new("abc"); + /// + /// assert_eq!(a, b); + /// assert_eq!(a, c); + /// ``` + #[inline] + #[unstable(feature = "bstr", issue = "134915")] + pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self { + ByteStr::from_bytes(bytes.as_ref()) + } + + #[doc(hidden)] + #[unstable(feature = "bstr_internals", issue = "none")] + #[inline] + pub fn from_bytes(slice: &[u8]) -> &Self { + // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to + // the wrapped type into a reference to the wrapper type. + unsafe { &*(slice as *const [u8] as *const Self) } + } + + #[doc(hidden)] + #[unstable(feature = "bstr_internals", issue = "none")] + #[inline] + pub fn from_bytes_mut(slice: &mut [u8]) -> &mut Self { + // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to + // the wrapped type into a reference to the wrapper type. + unsafe { &mut *(slice as *mut [u8] as *mut Self) } + } + + #[doc(hidden)] + #[unstable(feature = "bstr_internals", issue = "none")] + #[inline] + pub fn as_bytes(&self) -> &[u8] { + &self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Deref for ByteStr { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + &self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl DerefMut for ByteStr { + #[inline] + fn deref_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +#[unstable(feature = "deref_pure_trait", issue = "87121")] +unsafe impl DerefPure for ByteStr {} + +#[unstable(feature = "bstr", issue = "134915")] +impl fmt::Debug for ByteStr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "\"")?; + for chunk in self.utf8_chunks() { + for c in chunk.valid().chars() { + match c { + '\0' => write!(f, "\\0")?, + '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?, + _ => write!(f, "{}", c.escape_debug())?, + } + } + write!(f, "{}", chunk.invalid().escape_ascii())?; + } + write!(f, "\"")?; + Ok(()) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl fmt::Display for ByteStr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for chunk in this.utf8_chunks() { + f.write_str(chunk.valid())?; + if !chunk.invalid().is_empty() { + f.write_str("\u{FFFD}")?; + } + } + Ok(()) + } + + let Some(align) = f.align() else { + return fmt_nopad(self, f); + }; + let nchars: usize = self + .utf8_chunks() + .map(|chunk| chunk.valid().len() + if chunk.invalid().is_empty() { 0 } else { 1 }) + .sum(); + let padding = f.width().unwrap_or(0).saturating_sub(nchars); + let fill = f.fill(); + let (lpad, rpad) = match align { + fmt::Alignment::Left => (0, padding), + fmt::Alignment::Right => (padding, 0), + fmt::Alignment::Center => { + let half = padding / 2; + (half, half + padding % 2) + } + }; + for _ in 0..lpad { + write!(f, "{fill}")?; + } + fmt_nopad(self, f)?; + for _ in 0..rpad { + write!(f, "{fill}")?; + } + + Ok(()) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl AsRef<[u8]> for ByteStr { + #[inline] + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl AsRef<ByteStr> for ByteStr { + #[inline] + fn as_ref(&self) -> &ByteStr { + self + } +} + +// `impl AsRef<ByteStr> for [u8]` omitted to avoid widespread inference failures + +#[unstable(feature = "bstr", issue = "134915")] +impl AsRef<ByteStr> for str { + #[inline] + fn as_ref(&self) -> &ByteStr { + ByteStr::new(self) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl AsMut<[u8]> for ByteStr { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +// `impl AsMut<ByteStr> for [u8]` omitted to avoid widespread inference failures + +// `impl Borrow<ByteStr> for [u8]` omitted to avoid widespread inference failures + +// `impl Borrow<ByteStr> for str` omitted to avoid widespread inference failures + +#[unstable(feature = "bstr", issue = "134915")] +impl Borrow<[u8]> for ByteStr { + #[inline] + fn borrow(&self) -> &[u8] { + &self.0 + } +} + +// `impl BorrowMut<ByteStr> for [u8]` omitted to avoid widespread inference failures + +#[unstable(feature = "bstr", issue = "134915")] +impl BorrowMut<[u8]> for ByteStr { + #[inline] + fn borrow_mut(&mut self) -> &mut [u8] { + &mut self.0 + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> Default for &'a ByteStr { + fn default() -> Self { + ByteStr::from_bytes(b"") + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> Default for &'a mut ByteStr { + fn default() -> Self { + ByteStr::from_bytes_mut(&mut []) + } +} + +// Omitted due to inference failures +// +// #[unstable(feature = "bstr", issue = "134915")] +// impl<'a, const N: usize> From<&'a [u8; N]> for &'a ByteStr { +// #[inline] +// fn from(s: &'a [u8; N]) -> Self { +// ByteStr::from_bytes(s) +// } +// } +// +// #[unstable(feature = "bstr", issue = "134915")] +// impl<'a> From<&'a [u8]> for &'a ByteStr { +// #[inline] +// fn from(s: &'a [u8]) -> Self { +// ByteStr::from_bytes(s) +// } +// } + +// Omitted due to slice-from-array-issue-113238: +// +// #[unstable(feature = "bstr", issue = "134915")] +// impl<'a> From<&'a ByteStr> for &'a [u8] { +// #[inline] +// fn from(s: &'a ByteStr) -> Self { +// &s.0 +// } +// } +// +// #[unstable(feature = "bstr", issue = "134915")] +// impl<'a> From<&'a mut ByteStr> for &'a mut [u8] { +// #[inline] +// fn from(s: &'a mut ByteStr) -> Self { +// &mut s.0 +// } +// } + +// Omitted due to inference failures +// +// #[unstable(feature = "bstr", issue = "134915")] +// impl<'a> From<&'a str> for &'a ByteStr { +// #[inline] +// fn from(s: &'a str) -> Self { +// ByteStr::from_bytes(s.as_bytes()) +// } +// } + +#[unstable(feature = "bstr", issue = "134915")] +impl hash::Hash for ByteStr { + #[inline] + fn hash<H: hash::Hasher>(&self, state: &mut H) { + self.0.hash(state); + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<usize> for ByteStr { + type Output = u8; + + #[inline] + fn index(&self, idx: usize) -> &u8 { + &self.0[idx] + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeFull> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, _: RangeFull) -> &ByteStr { + self + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<Range<usize>> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: Range<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeInclusive<usize>> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeInclusive<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeFrom<usize>> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeFrom<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeTo<usize>> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeTo<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Index<RangeToInclusive<usize>> for ByteStr { + type Output = ByteStr; + + #[inline] + fn index(&self, r: RangeToInclusive<usize>) -> &ByteStr { + ByteStr::from_bytes(&self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<usize> for ByteStr { + #[inline] + fn index_mut(&mut self, idx: usize) -> &mut u8 { + &mut self.0[idx] + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeFull> for ByteStr { + #[inline] + fn index_mut(&mut self, _: RangeFull) -> &mut ByteStr { + self + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<Range<usize>> for ByteStr { + #[inline] + fn index_mut(&mut self, r: Range<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeInclusive<usize>> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeInclusive<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeFrom<usize>> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeFrom<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeTo<usize>> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeTo<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl IndexMut<RangeToInclusive<usize>> for ByteStr { + #[inline] + fn index_mut(&mut self, r: RangeToInclusive<usize>) -> &mut ByteStr { + ByteStr::from_bytes_mut(&mut self.0[r]) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl Eq for ByteStr {} + +#[unstable(feature = "bstr", issue = "134915")] +impl PartialEq<ByteStr> for ByteStr { + #[inline] + fn eq(&self, other: &ByteStr) -> bool { + &self.0 == &other.0 + } +} + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq { + ($lhs:ty, $rhs:ty) => { + #[allow(unused_lifetimes)] + impl<'a> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = other.as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + impl<'a> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = self.as_ref(); + PartialEq::eq(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq; + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq_ord { + ($lhs:ty, $rhs:ty) => { + $crate::bstr::impl_partial_eq!($lhs, $rhs); + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialOrd<$rhs> for $lhs { + #[inline] + fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> { + let other: &[u8] = other.as_ref(); + PartialOrd::partial_cmp(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<'a> PartialOrd<$lhs> for $rhs { + #[inline] + fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> { + let this: &[u8] = self.as_ref(); + PartialOrd::partial_cmp(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq_ord; + +#[doc(hidden)] +#[macro_export] +#[unstable(feature = "bstr_internals", issue = "none")] +macro_rules! impl_partial_eq_n { + ($lhs:ty, $rhs:ty) => { + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<const N: usize> PartialEq<$rhs> for $lhs { + #[inline] + fn eq(&self, other: &$rhs) -> bool { + let other: &[u8] = other.as_ref(); + PartialEq::eq(self.as_bytes(), other) + } + } + + #[allow(unused_lifetimes)] + #[unstable(feature = "bstr", issue = "134915")] + impl<const N: usize> PartialEq<$lhs> for $rhs { + #[inline] + fn eq(&self, other: &$lhs) -> bool { + let this: &[u8] = self.as_ref(); + PartialEq::eq(this, other.as_bytes()) + } + } + }; +} + +#[doc(hidden)] +#[unstable(feature = "bstr_internals", issue = "none")] +pub use impl_partial_eq_n; + +// PartialOrd with `[u8]` omitted to avoid inference failures +impl_partial_eq!(ByteStr, [u8]); +// PartialOrd with `&[u8]` omitted to avoid inference failures +impl_partial_eq!(ByteStr, &[u8]); +// PartialOrd with `str` omitted to avoid inference failures +impl_partial_eq!(ByteStr, str); +// PartialOrd with `&str` omitted to avoid inference failures +impl_partial_eq!(ByteStr, &str); +// PartialOrd with `[u8; N]` omitted to avoid inference failures +impl_partial_eq_n!(ByteStr, [u8; N]); +// PartialOrd with `[u8; N]` omitted to avoid inference failures +impl_partial_eq_n!(ByteStr, &[u8; N]); + +#[unstable(feature = "bstr", issue = "134915")] +impl Ord for ByteStr { + #[inline] + fn cmp(&self, other: &ByteStr) -> Ordering { + Ord::cmp(&self.0, &other.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl PartialOrd for ByteStr { + #[inline] + fn partial_cmp(&self, other: &ByteStr) -> Option<Ordering> { + PartialOrd::partial_cmp(&self.0, &other.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> TryFrom<&'a ByteStr> for &'a str { + type Error = crate::str::Utf8Error; + + #[inline] + fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> { + crate::str::from_utf8(&s.0) + } +} + +#[unstable(feature = "bstr", issue = "134915")] +impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str { + type Error = crate::str::Utf8Error; + + #[inline] + fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> { + crate::str::from_utf8_mut(&mut s.0) + } +} diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 306d565a77e..20187e478aa 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -22,8 +22,8 @@ //! (mutable via `&T`), in contrast with typical Rust types that exhibit 'inherited mutability' //! (mutable only via `&mut T`). //! -//! Cell types come in three flavors: `Cell<T>`, `RefCell<T>`, and `OnceCell<T>`. Each provides -//! a different way of providing safe interior mutability. +//! Cell types come in four flavors: `Cell<T>`, `RefCell<T>`, `OnceCell<T>`, and `LazyCell<T>`. +//! Each provides a different way of providing safe interior mutability. //! //! ## `Cell<T>` //! diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index ec1aed53eaf..00300328b64 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -311,6 +311,16 @@ unsafe impl CloneToUninit for crate::ffi::CStr { } } +#[unstable(feature = "bstr", issue = "134915")] +unsafe impl CloneToUninit for crate::bstr::ByteStr { + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + unsafe fn clone_to_uninit(&self, dst: *mut u8) { + // SAFETY: ByteStr is a `#[repr(transparent)]` wrapper around `[u8]` + unsafe { self.as_bytes().clone_to_uninit(dst) } + } +} + /// Implementations of `Clone` for primitive types. /// /// Implementations that cannot be described in Rust diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index 0685f525dca..0c3329f676e 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -163,28 +163,28 @@ pub(crate) struct EscapeIterInner<const N: usize> { } impl<const N: usize> EscapeIterInner<N> { - pub const fn backslash(c: ascii::Char) -> Self { + pub(crate) const fn backslash(c: ascii::Char) -> Self { let (data, range) = backslash(c); Self { data, alive: range } } - pub const fn ascii(c: u8) -> Self { + pub(crate) const fn ascii(c: u8) -> Self { let (data, range) = escape_ascii(c); Self { data, alive: range } } - pub const fn unicode(c: char) -> Self { + pub(crate) const fn unicode(c: char) -> Self { let (data, range) = escape_unicode(c); Self { data, alive: range } } #[inline] - pub const fn empty() -> Self { + pub(crate) const fn empty() -> Self { Self { data: [ascii::Char::Null; N], alive: 0..0 } } #[inline] - pub fn as_ascii(&self) -> &[ascii::Char] { + pub(crate) fn as_ascii(&self) -> &[ascii::Char] { // SAFETY: `self.alive` is guaranteed to be a valid range for indexing `self.data`. unsafe { self.data.get_unchecked(usize::from(self.alive.start)..usize::from(self.alive.end)) @@ -192,34 +192,34 @@ impl<const N: usize> EscapeIterInner<N> { } #[inline] - pub fn as_str(&self) -> &str { + pub(crate) fn as_str(&self) -> &str { self.as_ascii().as_str() } #[inline] - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { usize::from(self.alive.end - self.alive.start) } - pub fn next(&mut self) -> Option<u8> { + pub(crate) fn next(&mut self) -> Option<u8> { let i = self.alive.next()?; // SAFETY: `i` is guaranteed to be a valid index for `self.data`. unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) } } - pub fn next_back(&mut self) -> Option<u8> { + pub(crate) fn next_back(&mut self) -> Option<u8> { let i = self.alive.next_back()?; // SAFETY: `i` is guaranteed to be a valid index for `self.data`. unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) } } - pub fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { + pub(crate) fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { self.alive.advance_by(n) } - pub fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { + pub(crate) fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> { self.alive.advance_back_by(n) } } diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 5f32775822b..79d094556c4 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -172,10 +172,10 @@ mod c_char_definition { target_arch = "xtensa", ) ))] { - pub type c_char = u8; + pub(super) type c_char = u8; } else { // On every other target, c_char is signed. - pub type c_char = i8; + pub(super) type c_char = i8; } } } @@ -183,11 +183,11 @@ mod c_char_definition { mod c_int_definition { cfg_if! { if #[cfg(any(target_arch = "avr", target_arch = "msp430"))] { - pub type c_int = i16; - pub type c_uint = u16; + pub(super) type c_int = i16; + pub(super) type c_uint = u16; } else { - pub type c_int = i32; - pub type c_uint = u32; + pub(super) type c_int = i32; + pub(super) type c_uint = u32; } } } @@ -195,12 +195,12 @@ mod c_int_definition { mod c_long_definition { cfg_if! { if #[cfg(all(target_pointer_width = "64", not(windows)))] { - pub type c_long = i64; - pub type c_ulong = u64; + pub(super) type c_long = i64; + pub(super) type c_ulong = u64; } else { // The minimal size of `long` in the C standard is 32 bits - pub type c_long = i32; - pub type c_ulong = u32; + pub(super) type c_long = i32; + pub(super) type c_ulong = u32; } } } diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs index f67c592d8d8..cceb186b31e 100644 --- a/library/core/src/ffi/va_list.rs +++ b/library/core/src/ffi/va_list.rs @@ -302,18 +302,28 @@ impl<'f> Drop for VaListImpl<'f> { } } -extern "rust-intrinsic" { - /// Destroy the arglist `ap` after initialization with `va_start` or - /// `va_copy`. - #[rustc_nounwind] - fn va_end(ap: &mut VaListImpl<'_>); +/// Destroy the arglist `ap` after initialization with `va_start` or +/// `va_copy`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +unsafe fn va_end(_ap: &mut VaListImpl<'_>) { + unreachable!() +} - /// Copies the current location of arglist `src` to the arglist `dst`. - #[rustc_nounwind] - fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>); +/// Copies the current location of arglist `src` to the arglist `dst`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +unsafe fn va_copy<'f>(_dest: *mut VaListImpl<'f>, _src: &VaListImpl<'f>) { + unreachable!() +} - /// Loads an argument of type `T` from the `va_list` `ap` and increment the - /// argument `ap` points to. - #[rustc_nounwind] - fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T; +/// Loads an argument of type `T` from the `va_list` `ap` and increment the +/// argument `ap` points to. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +unsafe fn va_arg<T: sealed_trait::VaArgSafe>(_ap: &mut VaListImpl<'_>) -> T { + unreachable!() } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index a033b8bd305..a1bf3a4d7a7 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -288,7 +288,7 @@ pub enum DebugAsHex { /// /// `FormattingOptions` is a [`Formatter`] without an attached [`Write`] trait. /// It is mainly used to construct `Formatter` instances. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "formatting_options", issue = "118117")] pub struct FormattingOptions { flags: u32, @@ -508,6 +508,15 @@ impl FormattingOptions { } } +#[unstable(feature = "formatting_options", issue = "118117")] +impl Default for FormattingOptions { + /// Same as [`FormattingOptions::new()`]. + fn default() -> Self { + // The `#[derive(Default)]` implementation would set `fill` to `\0` instead of space. + Self::new() + } +} + /// Configuration for formatting. /// /// A `Formatter` represents various options related to formatting. Users do not diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 9c054b99a27..80f6e32b6b2 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -597,3 +597,138 @@ pub const fn black_box<T>(dummy: T) -> T { pub const fn must_use<T>(value: T) -> T { value } + +/// Hints to the compiler that a branch condition is likely to be true. +/// Returns the value passed to it. +/// +/// It can be used with `if` or boolean `match` expressions. +/// +/// When used outside of a branch condition, it may still influence a nearby branch, but +/// probably will not have any effect. +/// +/// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to +/// compound expressions, such as `likely(a && b)`. When applied to compound expressions, it has +/// the following effect: +/// ```text +/// likely(!a) => !unlikely(a) +/// likely(a && b) => likely(a) && likely(b) +/// likely(a || b) => a || likely(b) +/// ``` +/// +/// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code. +/// +/// # Examples +/// +/// ``` +/// #![feature(likely_unlikely)] +/// use core::hint::likely; +/// +/// fn foo(x: i32) { +/// if likely(x > 0) { +/// println!("this branch is likely to be taken"); +/// } else { +/// println!("this branch is unlikely to be taken"); +/// } +/// +/// match likely(x > 0) { +/// true => println!("this branch is likely to be taken"), +/// false => println!("this branch is unlikely to be taken"), +/// } +/// +/// // Use outside of a branch condition may still influence a nearby branch +/// let cond = likely(x != 0); +/// if cond { +/// println!("this branch is likely to be taken"); +/// } +/// } +/// ``` +/// +/// +#[unstable(feature = "likely_unlikely", issue = "26179")] +#[inline(always)] +pub const fn likely(b: bool) -> bool { + crate::intrinsics::likely(b) +} + +/// Hints to the compiler that a branch condition is unlikely to be true. +/// Returns the value passed to it. +/// +/// It can be used with `if` or boolean `match` expressions. +/// +/// When used outside of a branch condition, it may still influence a nearby branch, but +/// probably will not have any effect. +/// +/// It can also be applied to parts of expressions, such as `likely(a) && unlikely(b)`, or to +/// compound expressions, such as `unlikely(a && b)`. When applied to compound expressions, it has +/// the following effect: +/// ```text +/// unlikely(!a) => !likely(a) +/// unlikely(a && b) => a && unlikely(b) +/// unlikely(a || b) => unlikely(a) || unlikely(b) +/// ``` +/// +/// See also the function [`cold_path()`] which may be more appropriate for idiomatic Rust code. +/// +/// # Examples +/// +/// ``` +/// #![feature(likely_unlikely)] +/// use core::hint::unlikely; +/// +/// fn foo(x: i32) { +/// if unlikely(x > 0) { +/// println!("this branch is unlikely to be taken"); +/// } else { +/// println!("this branch is likely to be taken"); +/// } +/// +/// match unlikely(x > 0) { +/// true => println!("this branch is unlikely to be taken"), +/// false => println!("this branch is likely to be taken"), +/// } +/// +/// // Use outside of a branch condition may still influence a nearby branch +/// let cond = unlikely(x != 0); +/// if cond { +/// println!("this branch is likely to be taken"); +/// } +/// } +/// ``` +#[unstable(feature = "likely_unlikely", issue = "26179")] +#[inline(always)] +pub const fn unlikely(b: bool) -> bool { + crate::intrinsics::unlikely(b) +} + +/// Hints to the compiler that given path is cold, i.e., unlikely to be taken. The compiler may +/// choose to optimize paths that are not cold at the expense of paths that are cold. +/// +/// # Examples +/// +/// ``` +/// #![feature(cold_path)] +/// use core::hint::cold_path; +/// +/// fn foo(x: &[i32]) { +/// if let Some(first) = x.get(0) { +/// // this is the fast path +/// } else { +/// // this path is unlikely +/// cold_path(); +/// } +/// } +/// +/// fn bar(x: i32) -> i32 { +/// match x { +/// 1 => 10, +/// 2 => 100, +/// 3 => { cold_path(); 1000 }, // this branch is unlikely +/// _ => { cold_path(); 10000 }, // this is also unlikely +/// } +/// } +/// ``` +#[unstable(feature = "cold_path", issue = "26179")] +#[inline(always)] +pub const fn cold_path() { + crate::intrinsics::cold_path() +} diff --git a/library/core/src/intrinsics/simd.rs b/library/core/src/intrinsics/simd.rs index d03d801b936..e59d3aff379 100644 --- a/library/core/src/intrinsics/simd.rs +++ b/library/core/src/intrinsics/simd.rs @@ -2,669 +2,939 @@ //! //! In this module, a "vector" is any `repr(simd)` type. -extern "rust-intrinsic" { - /// Inserts an element into a vector, returning the updated vector. - /// - /// `T` must be a vector with element type `U`. - /// - /// # Safety - /// - /// `idx` must be in-bounds of the vector. - #[rustc_nounwind] - pub fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T; - - /// Extracts an element from a vector. - /// - /// `T` must be a vector with element type `U`. - /// - /// # Safety - /// - /// `idx` must be in-bounds of the vector. - #[rustc_nounwind] - pub fn simd_extract<T, U>(x: T, idx: u32) -> U; - - /// Adds two simd vectors elementwise. - /// - /// `T` must be a vector of integer or floating point primitive types. - #[rustc_nounwind] - pub fn simd_add<T>(x: T, y: T) -> T; - - /// Subtracts `rhs` from `lhs` elementwise. - /// - /// `T` must be a vector of integer or floating point primitive types. - #[rustc_nounwind] - pub fn simd_sub<T>(lhs: T, rhs: T) -> T; - - /// Multiplies two simd vectors elementwise. - /// - /// `T` must be a vector of integer or floating point primitive types. - #[rustc_nounwind] - pub fn simd_mul<T>(x: T, y: T) -> T; - - /// Divides `lhs` by `rhs` elementwise. - /// - /// `T` must be a vector of integer or floating point primitive types. - /// - /// # Safety - /// For integers, `rhs` must not contain any zero elements. - /// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior. - #[rustc_nounwind] - pub fn simd_div<T>(lhs: T, rhs: T) -> T; - - /// Returns remainder of two vectors elementwise. - /// - /// `T` must be a vector of integer or floating point primitive types. - /// - /// # Safety - /// For integers, `rhs` must not contain any zero elements. - /// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior. - #[rustc_nounwind] - pub fn simd_rem<T>(lhs: T, rhs: T) -> T; - - /// Shifts vector left elementwise, with UB on overflow. - /// - /// Shifts `lhs` left by `rhs`, shifting in sign bits for signed types. - /// - /// `T` must be a vector of integer primitive types. - /// - /// # Safety - /// - /// Each element of `rhs` must be less than `<int>::BITS`. - #[rustc_nounwind] - pub fn simd_shl<T>(lhs: T, rhs: T) -> T; - - /// Shifts vector right elementwise, with UB on overflow. - /// - /// `T` must be a vector of integer primitive types. - /// - /// Shifts `lhs` right by `rhs`, shifting in sign bits for signed types. - /// - /// # Safety - /// - /// Each element of `rhs` must be less than `<int>::BITS`. - #[rustc_nounwind] - pub fn simd_shr<T>(lhs: T, rhs: T) -> T; - - /// "Ands" vectors elementwise. - /// - /// `T` must be a vector of integer primitive types. - #[rustc_nounwind] - pub fn simd_and<T>(x: T, y: T) -> T; - - /// "Ors" vectors elementwise. - /// - /// `T` must be a vector of integer primitive types. - #[rustc_nounwind] - pub fn simd_or<T>(x: T, y: T) -> T; - - /// "Exclusive ors" vectors elementwise. - /// - /// `T` must be a vector of integer primitive types. - #[rustc_nounwind] - pub fn simd_xor<T>(x: T, y: T) -> T; - - /// Numerically casts a vector, elementwise. - /// - /// `T` and `U` must be vectors of integer or floating point primitive types, and must have the - /// same length. - /// - /// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB. - /// When casting integers to floats, the result is rounded. - /// Otherwise, truncates or extends the value, maintaining the sign for signed integers. - /// - /// # Safety - /// Casting from integer types is always safe. - /// Casting between two float types is also always safe. - /// - /// Casting floats to integers truncates, following the same rules as `to_int_unchecked`. - /// Specifically, each element must: - /// * Not be `NaN` - /// * Not be infinite - /// * Be representable in the return type, after truncating off its fractional part - #[rustc_nounwind] - pub fn simd_cast<T, U>(x: T) -> U; - - /// Numerically casts a vector, elementwise. - /// - /// `T` and `U` be a vectors of integer or floating point primitive types, and must have the - /// same length. - /// - /// Like `simd_cast`, but saturates float-to-integer conversions (NaN becomes 0). - /// This matches regular `as` and is always safe. - /// - /// When casting floats to integers, the result is truncated. - /// When casting integers to floats, the result is rounded. - /// Otherwise, truncates or extends the value, maintaining the sign for signed integers. - #[rustc_nounwind] - pub fn simd_as<T, U>(x: T) -> U; - - /// Negates a vector elementwise. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// Rust panics for `-<int>::Min` due to overflow, but it is not UB with this intrinsic. - #[rustc_nounwind] - pub fn simd_neg<T>(x: T) -> T; - - /// Returns absolute value of a vector, elementwise. - /// - /// `T` must be a vector of floating-point primitive types. - #[rustc_nounwind] - pub fn simd_fabs<T>(x: T) -> T; - - /// Returns the minimum of two vectors, elementwise. - /// - /// `T` must be a vector of floating-point primitive types. - /// - /// Follows IEEE-754 `minNum` semantics. - #[rustc_nounwind] - pub fn simd_fmin<T>(x: T, y: T) -> T; - - /// Returns the maximum of two vectors, elementwise. - /// - /// `T` must be a vector of floating-point primitive types. - /// - /// Follows IEEE-754 `maxNum` semantics. - #[rustc_nounwind] - pub fn simd_fmax<T>(x: T, y: T) -> T; - - /// Tests elementwise equality of two vectors. - /// - /// `T` must be a vector of floating-point primitive types. - /// - /// `U` must be a vector of integers with the same number of elements and element size as `T`. - /// - /// Returns `0` for false and `!0` for true. - #[rustc_nounwind] - pub fn simd_eq<T, U>(x: T, y: T) -> U; - - /// Tests elementwise inequality equality of two vectors. - /// - /// `T` must be a vector of floating-point primitive types. - /// - /// `U` must be a vector of integers with the same number of elements and element size as `T`. - /// - /// Returns `0` for false and `!0` for true. - #[rustc_nounwind] - pub fn simd_ne<T, U>(x: T, y: T) -> U; - - /// Tests if `x` is less than `y`, elementwise. - /// - /// `T` must be a vector of floating-point primitive types. - /// - /// `U` must be a vector of integers with the same number of elements and element size as `T`. - /// - /// Returns `0` for false and `!0` for true. - #[rustc_nounwind] - pub fn simd_lt<T, U>(x: T, y: T) -> U; - - /// Tests if `x` is less than or equal to `y`, elementwise. - /// - /// `T` must be a vector of floating-point primitive types. - /// - /// `U` must be a vector of integers with the same number of elements and element size as `T`. - /// - /// Returns `0` for false and `!0` for true. - #[rustc_nounwind] - pub fn simd_le<T, U>(x: T, y: T) -> U; - - /// Tests if `x` is greater than `y`, elementwise. - /// - /// `T` must be a vector of floating-point primitive types. - /// - /// `U` must be a vector of integers with the same number of elements and element size as `T`. - /// - /// Returns `0` for false and `!0` for true. - #[rustc_nounwind] - pub fn simd_gt<T, U>(x: T, y: T) -> U; - - /// Tests if `x` is greater than or equal to `y`, elementwise. - /// - /// `T` must be a vector of floating-point primitive types. - /// - /// `U` must be a vector of integers with the same number of elements and element size as `T`. - /// - /// Returns `0` for false and `!0` for true. - #[rustc_nounwind] - pub fn simd_ge<T, U>(x: T, y: T) -> U; - - /// Shuffles two vectors by const indices. - /// - /// `T` must be a vector. - /// - /// `U` must be a **const** vector of `u32`s. This means it must either refer to a named - /// const or be given as an inline const expression (`const { ... }`). - /// - /// `V` must be a vector with the same element type as `T` and the same length as `U`. - /// - /// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy` - /// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds - /// of `xy`. - #[rustc_nounwind] - pub fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V; - - /// Reads a vector of pointers. - /// - /// `T` must be a vector. - /// - /// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`. - /// - /// `V` must be a vector of integers with the same length as `T` (but any element size). - /// - /// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, read the pointer. - /// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from - /// `val`. - /// - /// # Safety - /// Unmasked values in `T` must be readable as if by `<ptr>::read` (e.g. aligned to the element - /// type). - /// - /// `mask` must only contain `0` or `!0` values. - #[rustc_nounwind] - pub fn simd_gather<T, U, V>(val: T, ptr: U, mask: V) -> T; - - /// Writes to a vector of pointers. - /// - /// `T` must be a vector. - /// - /// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`. - /// - /// `V` must be a vector of integers with the same length as `T` (but any element size). - /// - /// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, write the - /// corresponding value in `val` to the pointer. - /// Otherwise if the corresponding value in `mask` is `0`, do nothing. - /// - /// The stores happen in left-to-right order. - /// (This is relevant in case two of the stores overlap.) - /// - /// # Safety - /// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element - /// type). - /// - /// `mask` must only contain `0` or `!0` values. - #[rustc_nounwind] - pub fn simd_scatter<T, U, V>(val: T, ptr: U, mask: V); - - /// Reads a vector of pointers. - /// - /// `T` must be a vector. - /// - /// `U` must be a pointer to the element type of `T` - /// - /// `V` must be a vector of integers with the same length as `T` (but any element size). - /// - /// For each element, if the corresponding value in `mask` is `!0`, read the corresponding - /// pointer offset from `ptr`. - /// The first element is loaded from `ptr`, the second from `ptr.wrapping_offset(1)` and so on. - /// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from - /// `val`. - /// - /// # Safety - /// Unmasked values in `T` must be readable as if by `<ptr>::read` (e.g. aligned to the element - /// type). - /// - /// `mask` must only contain `0` or `!0` values. - #[rustc_nounwind] - pub fn simd_masked_load<V, U, T>(mask: V, ptr: U, val: T) -> T; - - /// Writes to a vector of pointers. - /// - /// `T` must be a vector. - /// - /// `U` must be a pointer to the element type of `T` - /// - /// `V` must be a vector of integers with the same length as `T` (but any element size). - /// - /// For each element, if the corresponding value in `mask` is `!0`, write the corresponding - /// value in `val` to the pointer offset from `ptr`. - /// The first element is written to `ptr`, the second to `ptr.wrapping_offset(1)` and so on. - /// Otherwise if the corresponding value in `mask` is `0`, do nothing. - /// - /// # Safety - /// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element - /// type). - /// - /// `mask` must only contain `0` or `!0` values. - #[rustc_nounwind] - pub fn simd_masked_store<V, U, T>(mask: V, ptr: U, val: T); - - /// Adds two simd vectors elementwise, with saturation. - /// - /// `T` must be a vector of integer primitive types. - #[rustc_nounwind] - pub fn simd_saturating_add<T>(x: T, y: T) -> T; - - /// Subtracts two simd vectors elementwise, with saturation. - /// - /// `T` must be a vector of integer primitive types. - /// - /// Subtract `rhs` from `lhs`. - #[rustc_nounwind] - pub fn simd_saturating_sub<T>(lhs: T, rhs: T) -> T; - - /// Adds elements within a vector from left to right. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - /// - /// Starting with the value `y`, add the elements of `x` and accumulate. - #[rustc_nounwind] - pub fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U; - - /// Adds elements within a vector in arbitrary order. May also be re-associated with - /// unordered additions on the inputs/outputs. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - #[rustc_nounwind] - pub fn simd_reduce_add_unordered<T, U>(x: T) -> U; - - /// Multiplies elements within a vector from left to right. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - /// - /// Starting with the value `y`, multiply the elements of `x` and accumulate. - #[rustc_nounwind] - pub fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U; - - /// Multiplies elements within a vector in arbitrary order. May also be re-associated with - /// unordered additions on the inputs/outputs. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - #[rustc_nounwind] - pub fn simd_reduce_mul_unordered<T, U>(x: T) -> U; - - /// Checks if all mask values are true. - /// - /// `T` must be a vector of integer primitive types. - /// - /// # Safety - /// `x` must contain only `0` or `!0`. - #[rustc_nounwind] - pub fn simd_reduce_all<T>(x: T) -> bool; - - /// Checks if any mask value is true. - /// - /// `T` must be a vector of integer primitive types. - /// - /// # Safety - /// `x` must contain only `0` or `!0`. - #[rustc_nounwind] - pub fn simd_reduce_any<T>(x: T) -> bool; - - /// Returns the maximum element of a vector. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - /// - /// For floating-point values, uses IEEE-754 `maxNum`. - #[rustc_nounwind] - pub fn simd_reduce_max<T, U>(x: T) -> U; - - /// Returns the minimum element of a vector. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - /// - /// For floating-point values, uses IEEE-754 `minNum`. - #[rustc_nounwind] - pub fn simd_reduce_min<T, U>(x: T) -> U; - - /// Logical "ands" all elements together. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - #[rustc_nounwind] - pub fn simd_reduce_and<T, U>(x: T) -> U; - - /// Logical "ors" all elements together. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - #[rustc_nounwind] - pub fn simd_reduce_or<T, U>(x: T) -> U; - - /// Logical "exclusive ors" all elements together. - /// - /// `T` must be a vector of integer or floating-point primitive types. - /// - /// `U` must be the element type of `T`. - #[rustc_nounwind] - pub fn simd_reduce_xor<T, U>(x: T) -> U; - - /// Truncates an integer vector to a bitmask. - /// - /// `T` must be an integer vector. - /// - /// `U` must be either the smallest unsigned integer with at least as many bits as the length - /// of `T`, or the smallest array of `u8` with at least as many bits as the length of `T`. - /// - /// Each element is truncated to a single bit and packed into the result. - /// - /// No matter whether the output is an array or an unsigned integer, it is treated as a single - /// contiguous list of bits. The bitmask is always packed on the least-significant side of the - /// output, and padded with 0s in the most-significant bits. The order of the bits depends on - /// endianness: - /// - /// * On little endian, the least significant bit corresponds to the first vector element. - /// * On big endian, the least significant bit corresponds to the last vector element. - /// - /// For example, `[!0, 0, !0, !0]` packs to - /// - `0b1101u8` or `[0b1101]` on little endian, and - /// - `0b1011u8` or `[0b1011]` on big endian. - /// - /// To consider a larger example, - /// `[!0, 0, 0, 0, 0, 0, 0, 0, !0, !0, 0, 0, 0, 0, !0, 0]` packs to - /// - `0b0100001100000001u16` or `[0b00000001, 0b01000011]` on little endian, and - /// - `0b1000000011000010u16` or `[0b10000000, 0b11000010]` on big endian. - /// - /// And finally, a non-power-of-2 example with multiple bytes: - /// `[!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]` packs to - /// - `0b0101001011u16` or `[0b01001011, 0b01]` on little endian, and - /// - `0b1101001010u16` or `[0b11, 0b01001010]` on big endian. - /// - /// # Safety - /// `x` must contain only `0` and `!0`. - #[rustc_nounwind] - pub fn simd_bitmask<T, U>(x: T) -> U; - - /// Selects elements from a mask. - /// - /// `M` must be an integer vector. - /// - /// `T` must be a vector with the same number of elements as `M`. - /// - /// For each element, if the corresponding value in `mask` is `!0`, select the element from - /// `if_true`. If the corresponding value in `mask` is `0`, select the element from - /// `if_false`. - /// - /// # Safety - /// `mask` must only contain `0` and `!0`. - #[rustc_nounwind] - pub fn simd_select<M, T>(mask: M, if_true: T, if_false: T) -> T; - - /// Selects elements from a bitmask. - /// - /// `M` must be an unsigned integer or array of `u8`, matching `simd_bitmask`. - /// - /// `T` must be a vector. - /// - /// For each element, if the bit in `mask` is `1`, select the element from - /// `if_true`. If the corresponding bit in `mask` is `0`, select the element from - /// `if_false`. - /// - /// The bitmask bit order matches `simd_bitmask`. - /// - /// # Safety - /// Padding bits must be all zero. - #[rustc_nounwind] - pub fn simd_select_bitmask<M, T>(m: M, yes: T, no: T) -> T; - - /// Calculates the offset from a pointer vector elementwise, potentially - /// wrapping. - /// - /// `T` must be a vector of pointers. - /// - /// `U` must be a vector of `isize` or `usize` with the same number of elements as `T`. - /// - /// Operates as if by `<ptr>::wrapping_offset`. - #[rustc_nounwind] - pub fn simd_arith_offset<T, U>(ptr: T, offset: U) -> T; - - /// Casts a vector of pointers. - /// - /// `T` and `U` must be vectors of pointers with the same number of elements. - #[rustc_nounwind] - pub fn simd_cast_ptr<T, U>(ptr: T) -> U; - - /// Exposes a vector of pointers as a vector of addresses. - /// - /// `T` must be a vector of pointers. - /// - /// `U` must be a vector of `usize` with the same length as `T`. - #[rustc_nounwind] - pub fn simd_expose_provenance<T, U>(ptr: T) -> U; - - /// Creates a vector of pointers from a vector of addresses. - /// - /// `T` must be a vector of `usize`. - /// - /// `U` must be a vector of pointers, with the same length as `T`. - #[rustc_nounwind] - pub fn simd_with_exposed_provenance<T, U>(addr: T) -> U; - - /// Swaps bytes of each element. - /// - /// `T` must be a vector of integers. - #[rustc_nounwind] - pub fn simd_bswap<T>(x: T) -> T; - - /// Reverses bits of each element. - /// - /// `T` must be a vector of integers. - #[rustc_nounwind] - pub fn simd_bitreverse<T>(x: T) -> T; - - /// Counts the leading zeros of each element. - /// - /// `T` must be a vector of integers. - #[rustc_nounwind] - pub fn simd_ctlz<T>(x: T) -> T; - - /// Counts the number of ones in each element. - /// - /// `T` must be a vector of integers. - #[rustc_nounwind] - pub fn simd_ctpop<T>(x: T) -> T; - - /// Counts the trailing zeros of each element. - /// - /// `T` must be a vector of integers. - #[rustc_nounwind] - pub fn simd_cttz<T>(x: T) -> T; - - /// Rounds up each element to the next highest integer-valued float. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_ceil<T>(x: T) -> T; - - /// Rounds down each element to the next lowest integer-valued float. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_floor<T>(x: T) -> T; - - /// Rounds each element to the closest integer-valued float. - /// Ties are resolved by rounding away from 0. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_round<T>(x: T) -> T; - - /// Returns the integer part of each element as an integer-valued float. - /// In other words, non-integer values are truncated towards zero. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_trunc<T>(x: T) -> T; - - /// Takes the square root of each element. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_fsqrt<T>(x: T) -> T; - - /// Computes `(x*y) + z` for each element, but without any intermediate rounding. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_fma<T>(x: T, y: T, z: T) -> T; - - /// Computes `(x*y) + z` for each element, non-deterministically executing either - /// a fused multiply-add or two operations with rounding of the intermediate result. - /// - /// The operation is fused if the code generator determines that target instruction - /// set has support for a fused operation, and that the fused operation is more efficient - /// than the equivalent, separate pair of mul and add instructions. It is unspecified - /// whether or not a fused operation is selected, and that may depend on optimization - /// level and context, for example. It may even be the case that some SIMD lanes get fused - /// and others do not. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_relaxed_fma<T>(x: T, y: T, z: T) -> T; - - // Computes the sine of each element. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_fsin<T>(a: T) -> T; - - // Computes the cosine of each element. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_fcos<T>(a: T) -> T; - - // Computes the exponential function of each element. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_fexp<T>(a: T) -> T; - - // Computes 2 raised to the power of each element. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_fexp2<T>(a: T) -> T; - - // Computes the base 10 logarithm of each element. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_flog10<T>(a: T) -> T; - - // Computes the base 2 logarithm of each element. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_flog2<T>(a: T) -> T; - - // Computes the natural logarithm of each element. - /// - /// `T` must be a vector of floats. - #[rustc_nounwind] - pub fn simd_flog<T>(a: T) -> T; +/// Inserts an element into a vector, returning the updated vector. +/// +/// `T` must be a vector with element type `U`. +/// +/// # Safety +/// +/// `idx` must be in-bounds of the vector. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_insert<T, U>(_x: T, _idx: u32, _val: U) -> T { + unreachable!() +} + +/// Extracts an element from a vector. +/// +/// `T` must be a vector with element type `U`. +/// +/// # Safety +/// +/// `idx` must be in-bounds of the vector. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_extract<T, U>(_x: T, _idx: u32) -> U { + unreachable!() +} + +/// Adds two simd vectors elementwise. +/// +/// `T` must be a vector of integer or floating point primitive types. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_add<T>(_x: T, _y: T) -> T { + unreachable!() +} + +/// Subtracts `rhs` from `lhs` elementwise. +/// +/// `T` must be a vector of integer or floating point primitive types. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_sub<T>(_lhs: T, _rhs: T) -> T { + unreachable!() +} + +/// Multiplies two simd vectors elementwise. +/// +/// `T` must be a vector of integer or floating point primitive types. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_mul<T>(_x: T, _y: T) -> T { + unreachable!() +} + +/// Divides `lhs` by `rhs` elementwise. +/// +/// `T` must be a vector of integer or floating point primitive types. +/// +/// # Safety +/// For integers, `rhs` must not contain any zero elements. +/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_div<T>(_lhs: T, _rhs: T) -> T { + unreachable!() +} + +/// Returns remainder of two vectors elementwise. +/// +/// `T` must be a vector of integer or floating point primitive types. +/// +/// # Safety +/// For integers, `rhs` must not contain any zero elements. +/// Additionally for signed integers, `<int>::MIN / -1` is undefined behavior. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_rem<T>(_lhs: T, _rhs: T) -> T { + unreachable!() +} + +/// Shifts vector left elementwise, with UB on overflow. +/// +/// Shifts `lhs` left by `rhs`, shifting in sign bits for signed types. +/// +/// `T` must be a vector of integer primitive types. +/// +/// # Safety +/// +/// Each element of `rhs` must be less than `<int>::BITS`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_shl<T>(_lhs: T, _rhs: T) -> T { + unreachable!() +} + +/// Shifts vector right elementwise, with UB on overflow. +/// +/// `T` must be a vector of integer primitive types. +/// +/// Shifts `lhs` right by `rhs`, shifting in sign bits for signed types. +/// +/// # Safety +/// +/// Each element of `rhs` must be less than `<int>::BITS`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_shr<T>(_lhs: T, _rhs: T) -> T { + unreachable!() +} + +/// "Ands" vectors elementwise. +/// +/// `T` must be a vector of integer primitive types. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_and<T>(_x: T, _y: T) -> T { + unreachable!() +} + +/// "Ors" vectors elementwise. +/// +/// `T` must be a vector of integer primitive types. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_or<T>(_x: T, _y: T) -> T { + unreachable!() +} + +/// "Exclusive ors" vectors elementwise. +/// +/// `T` must be a vector of integer primitive types. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_xor<T>(_x: T, _y: T) -> T { + unreachable!() +} + +/// Numerically casts a vector, elementwise. +/// +/// `T` and `U` must be vectors of integer or floating point primitive types, and must have the +/// same length. +/// +/// When casting floats to integers, the result is truncated. Out-of-bounds result lead to UB. +/// When casting integers to floats, the result is rounded. +/// Otherwise, truncates or extends the value, maintaining the sign for signed integers. +/// +/// # Safety +/// Casting from integer types is always safe. +/// Casting between two float types is also always safe. +/// +/// Casting floats to integers truncates, following the same rules as `to_int_unchecked`. +/// Specifically, each element must: +/// * Not be `NaN` +/// * Not be infinite +/// * Be representable in the return type, after truncating off its fractional part +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_cast<T, U>(_x: T) -> U { + unreachable!() +} + +/// Numerically casts a vector, elementwise. +/// +/// `T` and `U` be a vectors of integer or floating point primitive types, and must have the +/// same length. +/// +/// Like `simd_cast`, but saturates float-to-integer conversions (NaN becomes 0). +/// This matches regular `as` and is always safe. +/// +/// When casting floats to integers, the result is truncated. +/// When casting integers to floats, the result is rounded. +/// Otherwise, truncates or extends the value, maintaining the sign for signed integers. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_as<T, U>(_x: T) -> U { + unreachable!() +} + +/// Negates a vector elementwise. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// Rust panics for `-<int>::Min` due to overflow, but it is not UB with this intrinsic. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_neg<T>(_x: T) -> T { + unreachable!() +} + +/// Returns absolute value of a vector, elementwise. +/// +/// `T` must be a vector of floating-point primitive types. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fabs<T>(_x: T) -> T { + unreachable!() +} + +/// Returns the minimum of two vectors, elementwise. +/// +/// `T` must be a vector of floating-point primitive types. +/// +/// Follows IEEE-754 `minNum` semantics. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fmin<T>(_x: T, _y: T) -> T { + unreachable!() +} + +/// Returns the maximum of two vectors, elementwise. +/// +/// `T` must be a vector of floating-point primitive types. +/// +/// Follows IEEE-754 `maxNum` semantics. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fmax<T>(_x: T, _y: T) -> T { + unreachable!() +} + +/// Tests elementwise equality of two vectors. +/// +/// `T` must be a vector of floating-point primitive types. +/// +/// `U` must be a vector of integers with the same number of elements and element size as `T`. +/// +/// Returns `0` for false and `!0` for true. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_eq<T, U>(_x: T, _y: T) -> U { + unreachable!() +} + +/// Tests elementwise inequality equality of two vectors. +/// +/// `T` must be a vector of floating-point primitive types. +/// +/// `U` must be a vector of integers with the same number of elements and element size as `T`. +/// +/// Returns `0` for false and `!0` for true. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_ne<T, U>(_x: T, _y: T) -> U { + unreachable!() +} + +/// Tests if `x` is less than `y`, elementwise. +/// +/// `T` must be a vector of floating-point primitive types. +/// +/// `U` must be a vector of integers with the same number of elements and element size as `T`. +/// +/// Returns `0` for false and `!0` for true. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_lt<T, U>(_x: T, _y: T) -> U { + unreachable!() +} + +/// Tests if `x` is less than or equal to `y`, elementwise. +/// +/// `T` must be a vector of floating-point primitive types. +/// +/// `U` must be a vector of integers with the same number of elements and element size as `T`. +/// +/// Returns `0` for false and `!0` for true. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_le<T, U>(_x: T, _y: T) -> U { + unreachable!() +} + +/// Tests if `x` is greater than `y`, elementwise. +/// +/// `T` must be a vector of floating-point primitive types. +/// +/// `U` must be a vector of integers with the same number of elements and element size as `T`. +/// +/// Returns `0` for false and `!0` for true. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_gt<T, U>(_x: T, _y: T) -> U { + unreachable!() +} + +/// Tests if `x` is greater than or equal to `y`, elementwise. +/// +/// `T` must be a vector of floating-point primitive types. +/// +/// `U` must be a vector of integers with the same number of elements and element size as `T`. +/// +/// Returns `0` for false and `!0` for true. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_ge<T, U>(_x: T, _y: T) -> U { + unreachable!() +} + +/// Shuffles two vectors by const indices. +/// +/// `T` must be a vector. +/// +/// `U` must be a **const** vector of `u32`s. This means it must either refer to a named +/// const or be given as an inline const expression (`const { ... }`). +/// +/// `V` must be a vector with the same element type as `T` and the same length as `U`. +/// +/// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy` +/// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds +/// of `xy`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_shuffle<T, U, V>(_x: T, _y: T, _idx: U) -> V { + unreachable!() +} + +/// Reads a vector of pointers. +/// +/// `T` must be a vector. +/// +/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`. +/// +/// `V` must be a vector of integers with the same length as `T` (but any element size). +/// +/// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, read the pointer. +/// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from +/// `val`. +/// +/// # Safety +/// Unmasked values in `T` must be readable as if by `<ptr>::read` (e.g. aligned to the element +/// type). +/// +/// `mask` must only contain `0` or `!0` values. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_gather<T, U, V>(_val: T, _ptr: U, _mask: V) -> T { + unreachable!() +} + +/// Writes to a vector of pointers. +/// +/// `T` must be a vector. +/// +/// `U` must be a vector of pointers to the element type of `T`, with the same length as `T`. +/// +/// `V` must be a vector of integers with the same length as `T` (but any element size). +/// +/// For each pointer in `ptr`, if the corresponding value in `mask` is `!0`, write the +/// corresponding value in `val` to the pointer. +/// Otherwise if the corresponding value in `mask` is `0`, do nothing. +/// +/// The stores happen in left-to-right order. +/// (This is relevant in case two of the stores overlap.) +/// +/// # Safety +/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element +/// type). +/// +/// `mask` must only contain `0` or `!0` values. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_scatter<T, U, V>(_val: T, _ptr: U, _mask: V) { + unreachable!() +} + +/// Reads a vector of pointers. +/// +/// `T` must be a vector. +/// +/// `U` must be a pointer to the element type of `T` +/// +/// `V` must be a vector of integers with the same length as `T` (but any element size). +/// +/// For each element, if the corresponding value in `mask` is `!0`, read the corresponding +/// pointer offset from `ptr`. +/// The first element is loaded from `ptr`, the second from `ptr.wrapping_offset(1)` and so on. +/// Otherwise if the corresponding value in `mask` is `0`, return the corresponding value from +/// `val`. +/// +/// # Safety +/// Unmasked values in `T` must be readable as if by `<ptr>::read` (e.g. aligned to the element +/// type). +/// +/// `mask` must only contain `0` or `!0` values. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_masked_load<V, U, T>(_mask: V, _ptr: U, _val: T) -> T { + unreachable!() +} + +/// Writes to a vector of pointers. +/// +/// `T` must be a vector. +/// +/// `U` must be a pointer to the element type of `T` +/// +/// `V` must be a vector of integers with the same length as `T` (but any element size). +/// +/// For each element, if the corresponding value in `mask` is `!0`, write the corresponding +/// value in `val` to the pointer offset from `ptr`. +/// The first element is written to `ptr`, the second to `ptr.wrapping_offset(1)` and so on. +/// Otherwise if the corresponding value in `mask` is `0`, do nothing. +/// +/// # Safety +/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element +/// type). +/// +/// `mask` must only contain `0` or `!0` values. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_masked_store<V, U, T>(_mask: V, _ptr: U, _val: T) { + unreachable!() +} + +/// Adds two simd vectors elementwise, with saturation. +/// +/// `T` must be a vector of integer primitive types. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_saturating_add<T>(_x: T, _y: T) -> T { + unreachable!() +} + +/// Subtracts two simd vectors elementwise, with saturation. +/// +/// `T` must be a vector of integer primitive types. +/// +/// Subtract `rhs` from `lhs`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_saturating_sub<T>(_lhs: T, _rhs: T) -> T { + unreachable!() +} + +/// Adds elements within a vector from left to right. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +/// +/// Starting with the value `y`, add the elements of `x` and accumulate. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_add_ordered<T, U>(_x: T, _y: U) -> U { + unreachable!() +} + +/// Adds elements within a vector in arbitrary order. May also be re-associated with +/// unordered additions on the inputs/outputs. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_add_unordered<T, U>(_x: T) -> U { + unreachable!() +} + +/// Multiplies elements within a vector from left to right. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +/// +/// Starting with the value `y`, multiply the elements of `x` and accumulate. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_mul_ordered<T, U>(_x: T, _y: U) -> U { + unreachable!() +} + +/// Multiplies elements within a vector in arbitrary order. May also be re-associated with +/// unordered additions on the inputs/outputs. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_mul_unordered<T, U>(_x: T) -> U { + unreachable!() +} + +/// Checks if all mask values are true. +/// +/// `T` must be a vector of integer primitive types. +/// +/// # Safety +/// `x` must contain only `0` or `!0`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_all<T>(_x: T) -> bool { + unreachable!() +} + +/// Checks if any mask value is true. +/// +/// `T` must be a vector of integer primitive types. +/// +/// # Safety +/// `x` must contain only `0` or `!0`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_any<T>(_x: T) -> bool { + unreachable!() +} + +/// Returns the maximum element of a vector. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +/// +/// For floating-point values, uses IEEE-754 `maxNum`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_max<T, U>(_x: T) -> U { + unreachable!() +} + +/// Returns the minimum element of a vector. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +/// +/// For floating-point values, uses IEEE-754 `minNum`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_min<T, U>(_x: T) -> U { + unreachable!() +} + +/// Logical "ands" all elements together. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_and<T, U>(_x: T) -> U { + unreachable!() +} + +/// Logical "ors" all elements together. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_or<T, U>(_x: T) -> U { + unreachable!() +} + +/// Logical "exclusive ors" all elements together. +/// +/// `T` must be a vector of integer or floating-point primitive types. +/// +/// `U` must be the element type of `T`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_reduce_xor<T, U>(_x: T) -> U { + unreachable!() +} + +/// Truncates an integer vector to a bitmask. +/// +/// `T` must be an integer vector. +/// +/// `U` must be either the smallest unsigned integer with at least as many bits as the length +/// of `T`, or the smallest array of `u8` with at least as many bits as the length of `T`. +/// +/// Each element is truncated to a single bit and packed into the result. +/// +/// No matter whether the output is an array or an unsigned integer, it is treated as a single +/// contiguous list of bits. The bitmask is always packed on the least-significant side of the +/// output, and padded with 0s in the most-significant bits. The order of the bits depends on +/// endianness: +/// +/// * On little endian, the least significant bit corresponds to the first vector element. +/// * On big endian, the least significant bit corresponds to the last vector element. +/// +/// For example, `[!0, 0, !0, !0]` packs to +/// - `0b1101u8` or `[0b1101]` on little endian, and +/// - `0b1011u8` or `[0b1011]` on big endian. +/// +/// To consider a larger example, +/// `[!0, 0, 0, 0, 0, 0, 0, 0, !0, !0, 0, 0, 0, 0, !0, 0]` packs to +/// - `0b0100001100000001u16` or `[0b00000001, 0b01000011]` on little endian, and +/// - `0b1000000011000010u16` or `[0b10000000, 0b11000010]` on big endian. +/// +/// And finally, a non-power-of-2 example with multiple bytes: +/// `[!0, !0, 0, !0, 0, 0, !0, 0, !0, 0]` packs to +/// - `0b0101001011u16` or `[0b01001011, 0b01]` on little endian, and +/// - `0b1101001010u16` or `[0b11, 0b01001010]` on big endian. +/// +/// # Safety +/// `x` must contain only `0` and `!0`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_bitmask<T, U>(_x: T) -> U { + unreachable!() +} + +/// Selects elements from a mask. +/// +/// `M` must be an integer vector. +/// +/// `T` must be a vector with the same number of elements as `M`. +/// +/// For each element, if the corresponding value in `mask` is `!0`, select the element from +/// `if_true`. If the corresponding value in `mask` is `0`, select the element from +/// `if_false`. +/// +/// # Safety +/// `mask` must only contain `0` and `!0`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_select<M, T>(_mask: M, _if_true: T, _if_false: T) -> T { + unreachable!() +} + +/// Selects elements from a bitmask. +/// +/// `M` must be an unsigned integer or array of `u8`, matching `simd_bitmask`. +/// +/// `T` must be a vector. +/// +/// For each element, if the bit in `mask` is `1`, select the element from +/// `if_true`. If the corresponding bit in `mask` is `0`, select the element from +/// `if_false`. +/// +/// The bitmask bit order matches `simd_bitmask`. +/// +/// # Safety +/// Padding bits must be all zero. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_select_bitmask<M, T>(_m: M, _yes: T, _no: T) -> T { + unreachable!() +} + +/// Calculates the offset from a pointer vector elementwise, potentially +/// wrapping. +/// +/// `T` must be a vector of pointers. +/// +/// `U` must be a vector of `isize` or `usize` with the same number of elements as `T`. +/// +/// Operates as if by `<ptr>::wrapping_offset`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_arith_offset<T, U>(_ptr: T, _offset: U) -> T { + unreachable!() +} + +/// Casts a vector of pointers. +/// +/// `T` and `U` must be vectors of pointers with the same number of elements. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_cast_ptr<T, U>(_ptr: T) -> U { + unreachable!() +} + +/// Exposes a vector of pointers as a vector of addresses. +/// +/// `T` must be a vector of pointers. +/// +/// `U` must be a vector of `usize` with the same length as `T`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_expose_provenance<T, U>(_ptr: T) -> U { + unreachable!() +} + +/// Creates a vector of pointers from a vector of addresses. +/// +/// `T` must be a vector of `usize`. +/// +/// `U` must be a vector of pointers, with the same length as `T`. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_with_exposed_provenance<T, U>(_addr: T) -> U { + unreachable!() +} + +/// Swaps bytes of each element. +/// +/// `T` must be a vector of integers. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_bswap<T>(_x: T) -> T { + unreachable!() +} + +/// Reverses bits of each element. +/// +/// `T` must be a vector of integers. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_bitreverse<T>(_x: T) -> T { + unreachable!() +} + +/// Counts the leading zeros of each element. +/// +/// `T` must be a vector of integers. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_ctlz<T>(_x: T) -> T { + unreachable!() +} + +/// Counts the number of ones in each element. +/// +/// `T` must be a vector of integers. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_ctpop<T>(_x: T) -> T { + unreachable!() +} + +/// Counts the trailing zeros of each element. +/// +/// `T` must be a vector of integers. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_cttz<T>(_x: T) -> T { + unreachable!() +} + +/// Rounds up each element to the next highest integer-valued float. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_ceil<T>(_x: T) -> T { + unreachable!() +} + +/// Rounds down each element to the next lowest integer-valued float. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_floor<T>(_x: T) -> T { + unreachable!() +} + +/// Rounds each element to the closest integer-valued float. +/// Ties are resolved by rounding away from 0. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_round<T>(_x: T) -> T { + unreachable!() +} + +/// Returns the integer part of each element as an integer-valued float. +/// In other words, non-integer values are truncated towards zero. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_trunc<T>(_x: T) -> T { + unreachable!() +} + +/// Takes the square root of each element. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fsqrt<T>(_x: T) -> T { + unreachable!() +} + +/// Computes `(x*y) + z` for each element, but without any intermediate rounding. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fma<T>(_x: T, _y: T, _z: T) -> T { + unreachable!() +} + +/// Computes `(x*y) + z` for each element, non-deterministically executing either +/// a fused multiply-add or two operations with rounding of the intermediate result. +/// +/// The operation is fused if the code generator determines that target instruction +/// set has support for a fused operation, and that the fused operation is more efficient +/// than the equivalent, separate pair of mul and add instructions. It is unspecified +/// whether or not a fused operation is selected, and that may depend on optimization +/// level and context, for example. It may even be the case that some SIMD lanes get fused +/// and others do not. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_relaxed_fma<T>(_x: T, _y: T, _z: T) -> T { + unreachable!() +} + +// Computes the sine of each element. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fsin<T>(_a: T) -> T { + unreachable!() +} + +// Computes the cosine of each element. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fcos<T>(_a: T) -> T { + unreachable!() +} + +// Computes the exponential function of each element. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fexp<T>(_a: T) -> T { + unreachable!() +} + +// Computes 2 raised to the power of each element. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_fexp2<T>(_a: T) -> T { + unreachable!() +} + +// Computes the base 10 logarithm of each element. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_flog10<T>(_a: T) -> T { + unreachable!() +} + +// Computes the base 2 logarithm of each element. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_flog2<T>(_a: T) -> T { + unreachable!() +} + +// Computes the natural logarithm of each element. +/// +/// `T` must be a vector of floats. +#[rustc_intrinsic] +#[rustc_intrinsic_must_be_overridden] +#[rustc_nounwind] +pub unsafe fn simd_flog<T>(_a: T) -> T { + unreachable!() } diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index e845bb34426..c18e0405f72 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -44,7 +44,7 @@ //! called. The `lang` attribute is called `eh_personality`. // Since core defines many fundamental lang items, all tests live in a -// separate crate, libcoretest (library/core/tests), to avoid bizarre issues. +// separate crate, coretests (library/coretests), to avoid bizarre issues. // // Here we explicitly #[cfg]-out this whole crate when testing. If we don't do // this, both the generated test artifact and the linked libtest (which @@ -101,6 +101,7 @@ #![warn(multiple_supertrait_upcastable)] #![allow(internal_features)] #![deny(ffi_unwind_calls)] +#![warn(unreachable_pub)] // Do not check link redundancy on bootstraping phase #![allow(rustdoc::redundant_explicit_links)] #![warn(rustdoc::unescaped_backticks)] @@ -110,6 +111,8 @@ #![feature(array_ptr_get)] #![feature(asm_experimental_arch)] #![feature(bigint_helper_methods)] +#![feature(bstr)] +#![feature(bstr_internals)] #![feature(const_carrying_mul_add)] #![feature(const_eval_select)] #![feature(core_intrinsics)] @@ -335,6 +338,8 @@ pub mod ascii; pub mod asserting; #[unstable(feature = "async_iterator", issue = "79024")] pub mod async_iter; +#[unstable(feature = "bstr", issue = "134915")] +pub mod bstr; pub mod cell; pub mod char; pub mod ffi; @@ -396,7 +401,8 @@ pub mod primitive; unused_imports, unsafe_op_in_unsafe_fn, ambiguous_glob_reexports, - deprecated_in_future + deprecated_in_future, + unreachable_pub )] #[allow(rustdoc::bare_urls)] mod core_arch; diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 01af964a83e..a793fc2aa2e 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -6,6 +6,13 @@ #![stable(feature = "rust1", since = "1.0.0")] +mod variance; + +#[unstable(feature = "phantom_variance_markers", issue = "135806")] +pub use self::variance::{ + PhantomContravariant, PhantomContravariantLifetime, PhantomCovariant, PhantomCovariantLifetime, + PhantomInvariant, PhantomInvariantLifetime, Variance, variance, +}; use crate::cell::UnsafeCell; use crate::cmp; use crate::fmt::Debug; diff --git a/library/core/src/marker/variance.rs b/library/core/src/marker/variance.rs new file mode 100644 index 00000000000..23334e6575d --- /dev/null +++ b/library/core/src/marker/variance.rs @@ -0,0 +1,260 @@ +#![unstable(feature = "phantom_variance_markers", issue = "135806")] + +use super::PhantomData; +use crate::any::type_name; +use crate::cmp::Ordering; +use crate::fmt; +use crate::hash::{Hash, Hasher}; + +macro_rules! first_token { + ($first:tt $($rest:tt)*) => { + $first + }; +} + +macro_rules! phantom_type { + ($( + $(#[$attr:meta])* + pub struct $name:ident <$t:ident> ($($inner:tt)*); + )*) => {$( + $(#[$attr])* + pub struct $name<$t>($($inner)*) where T: ?Sized; + + impl<T> $name<T> + where T: ?Sized + { + /// Constructs a new instance of the variance marker. + pub const fn new() -> Self { + Self(PhantomData) + } + } + + impl<T> self::sealed::Sealed for $name<T> where T: ?Sized { + const VALUE: Self = Self::new(); + } + impl<T> Variance for $name<T> where T: ?Sized {} + + impl<T> Default for $name<T> + where T: ?Sized + { + fn default() -> Self { + Self(PhantomData) + } + } + + impl<T> fmt::Debug for $name<T> + where T: ?Sized + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}<{}>", stringify!($name), type_name::<T>()) + } + } + + impl<T> Clone for $name<T> + where T: ?Sized + { + fn clone(&self) -> Self { + *self + } + } + + impl<T> Copy for $name<T> where T: ?Sized {} + + impl<T> PartialEq for $name<T> + where T: ?Sized + { + fn eq(&self, _: &Self) -> bool { + true + } + } + + impl<T> Eq for $name<T> where T: ?Sized {} + + impl<T> PartialOrd for $name<T> + where T: ?Sized + { + fn partial_cmp(&self, _: &Self) -> Option<Ordering> { + Some(Ordering::Equal) + } + } + + impl<T> Ord for $name<T> + where T: ?Sized + { + fn cmp(&self, _: &Self) -> Ordering { + Ordering::Equal + } + } + + impl<T> Hash for $name<T> + where T: ?Sized + { + fn hash<H: Hasher>(&self, _: &mut H) {} + } + )*}; +} + +macro_rules! phantom_lifetime { + ($( + $(#[$attr:meta])* + pub struct $name:ident <$lt:lifetime> ($($inner:tt)*); + )*) => {$( + $(#[$attr])* + #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct $name<$lt>($($inner)*); + + impl $name<'_> { + /// Constructs a new instance of the variance marker. + pub const fn new() -> Self { + Self(first_token!($($inner)*)(PhantomData)) + } + } + + impl self::sealed::Sealed for $name<'_> { + const VALUE: Self = Self::new(); + } + impl Variance for $name<'_> {} + + impl fmt::Debug for $name<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", stringify!($name)) + } + } + )*}; +} + +phantom_lifetime! { + /// Zero-sized type used to mark a lifetime as covariant. + /// + /// Covariant lifetimes must live at least as long as declared. See [the reference][1] for more + /// information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::<PhantomCovariantLifetime<'a>>() == 0` + /// * `align_of::<PhantomCovariantLifetime<'a>>() == 1` + pub struct PhantomCovariantLifetime<'a>(PhantomCovariant<&'a ()>); + /// Zero-sized type used to mark a lifetime as contravariant. + /// + /// Contravariant lifetimes must live at most as long as declared. See [the reference][1] for + /// more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::<PhantomContravariantLifetime<'a>>() == 0` + /// * `align_of::<PhantomContravariantLifetime<'a>>() == 1` + pub struct PhantomContravariantLifetime<'a>(PhantomContravariant<&'a ()>); + /// Zero-sized type used to mark a lifetime as invariant. + /// + /// Invariant lifetimes must be live for the exact length declared, neither shorter nor longer. + /// See [the reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `'a`, the following are guaranteed: + /// * `size_of::<PhantomInvariantLifetime<'a>>() == 0` + /// * `align_of::<PhantomInvariantLifetime<'a>>() == 1` + pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>); +} + +phantom_type! { + /// Zero-sized type used to mark a type parameter as covariant. + /// + /// Types used as part of the return value from a function are covariant. If the type is _also_ + /// passed as a parameter then it is [invariant][PhantomInvariant]. See [the reference][1] for + /// more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::<PhantomCovariant<T>>() == 0` + /// * `align_of::<PhantomCovariant<T>>() == 1` + pub struct PhantomCovariant<T>(PhantomData<fn() -> T>); + /// Zero-sized type used to mark a type parameter as contravariant. + /// + /// Types passed as arguments to a function are contravariant. If the type is _also_ part of the + /// return value from a function then it is [invariant][PhantomInvariant]. See [the + /// reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::<PhantomContravariant<T>>() == 0` + /// * `align_of::<PhantomContravariant<T>>() == 1` + pub struct PhantomContravariant<T>(PhantomData<fn(T)>); + /// Zero-sized type used to mark a type parameter as invariant. + /// + /// Types that are both passed as an argument _and_ used as part of the return value from a + /// function are invariant. See [the reference][1] for more information. + /// + /// [1]: https://doc.rust-lang.org/stable/reference/subtyping.html#variance + /// + /// ## Layout + /// + /// For all `T`, the following are guaranteed: + /// * `size_of::<PhantomInvariant<T>>() == 0` + /// * `align_of::<PhantomInvariant<T>>() == 1` + pub struct PhantomInvariant<T>(PhantomData<fn(T) -> T>); +} + +mod sealed { + pub trait Sealed { + const VALUE: Self; + } +} + +/// A marker trait for phantom variance types. +pub trait Variance: sealed::Sealed + Default {} + +/// Construct a variance marker; equivalent to [`Default::default`]. +/// +/// This type can be any of the following. You generally should not need to explicitly name the +/// type, however. +/// +/// - [`PhantomCovariant`] +/// - [`PhantomContravariant`] +/// - [`PhantomInvariant`] +/// - [`PhantomCovariantLifetime`] +/// - [`PhantomContravariantLifetime`] +/// - [`PhantomInvariantLifetime`] +/// +/// # Example +/// +/// ```rust +/// #![feature(phantom_variance_markers)] +/// +/// use core::marker::{PhantomCovariant, variance}; +/// +/// struct BoundFn<F, P, R> +/// where +/// F: Fn(P) -> R, +/// { +/// function: F, +/// parameter: P, +/// return_value: PhantomCovariant<R>, +/// } +/// +/// let bound_fn = BoundFn { +/// function: core::convert::identity, +/// parameter: 5u8, +/// return_value: variance(), +/// }; +/// ``` +pub const fn variance<T>() -> T +where + T: Variance, +{ + T::VALUE +} diff --git a/library/core/src/net/display_buffer.rs b/library/core/src/net/display_buffer.rs index a7d12217081..625ad5401f5 100644 --- a/library/core/src/net/display_buffer.rs +++ b/library/core/src/net/display_buffer.rs @@ -2,19 +2,19 @@ use crate::mem::MaybeUninit; use crate::{fmt, str}; /// Used for slow path in `Display` implementations when alignment is required. -pub struct DisplayBuffer<const SIZE: usize> { +pub(super) struct DisplayBuffer<const SIZE: usize> { buf: [MaybeUninit<u8>; SIZE], len: usize, } impl<const SIZE: usize> DisplayBuffer<SIZE> { #[inline] - pub const fn new() -> Self { + pub(super) const fn new() -> Self { Self { buf: [MaybeUninit::uninit(); SIZE], len: 0 } } #[inline] - pub fn as_str(&self) -> &str { + pub(super) fn as_str(&self) -> &str { // SAFETY: `buf` is only written to by the `fmt::Write::write_str` implementation // which writes a valid UTF-8 string to `buf` and correctly sets `len`. unsafe { diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 7dd5c214012..b11ba056853 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1539,8 +1539,9 @@ impl Ipv6Addr { /// // Addresses reserved for benchmarking (`2001:2::/48`) /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false); /// - /// // Addresses reserved for documentation (`2001:db8::/32`) + /// // Addresses reserved for documentation (`2001:db8::/32` and `3fff::/20`) /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false); + /// assert_eq!(Ipv6Addr::new(0x3fff, 0, 0, 0, 0, 0, 0, 0).is_global(), false); /// /// // Unique local addresses (`fc00::/7`) /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false); @@ -1686,11 +1687,12 @@ impl Ipv6Addr { } /// Returns [`true`] if this is an address reserved for documentation - /// (`2001:db8::/32`). + /// (`2001:db8::/32` and `3fff::/20`). /// - /// This property is defined in [IETF RFC 3849]. + /// This property is defined by [IETF RFC 3849] and [IETF RFC 9637]. /// /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849 + /// [IETF RFC 9637]: https://tools.ietf.org/html/rfc9637 /// /// # Examples /// @@ -1701,12 +1703,13 @@ impl Ipv6Addr { /// /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_documentation(), false); /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0).is_documentation(), true); + /// assert_eq!(Ipv6Addr::new(0x3fff, 0, 0, 0, 0, 0, 0, 0).is_documentation(), true); /// ``` #[unstable(feature = "ip", issue = "27709")] #[must_use] #[inline] pub const fn is_documentation(&self) -> bool { - (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8) + matches!(self.segments(), [0x2001, 0xdb8, ..] | [0x3fff, 0..=0x0fff, ..]) } /// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`). diff --git a/library/core/src/num/dec2flt/decimal.rs b/library/core/src/num/dec2flt/decimal.rs index be9c0eccd5e..b37724ba62d 100644 --- a/library/core/src/num/dec2flt/decimal.rs +++ b/library/core/src/num/dec2flt/decimal.rs @@ -12,7 +12,7 @@ use crate::num::dec2flt::common::{ByteSlice, is_8digits}; #[derive(Clone)] -pub struct Decimal { +pub(super) struct Decimal { /// The number of significant digits in the decimal. pub num_digits: usize, /// The offset of the decimal point in the significant digits. @@ -55,13 +55,13 @@ impl Decimal { /// /// In Python: /// `-emin + p2 + math.floor((emin+ 1)*math.log(2, b)-math.log(1-2**(-p2), b))` - pub const MAX_DIGITS: usize = 768; + pub(super) const MAX_DIGITS: usize = 768; /// The max digits that can be exactly represented in a 64-bit integer. - pub const MAX_DIGITS_WITHOUT_OVERFLOW: usize = 19; - pub const DECIMAL_POINT_RANGE: i32 = 2047; + pub(super) const MAX_DIGITS_WITHOUT_OVERFLOW: usize = 19; + pub(super) const DECIMAL_POINT_RANGE: i32 = 2047; /// Append a digit to the buffer. - pub fn try_add_digit(&mut self, digit: u8) { + pub(super) fn try_add_digit(&mut self, digit: u8) { if self.num_digits < Self::MAX_DIGITS { self.digits[self.num_digits] = digit; } @@ -69,7 +69,7 @@ impl Decimal { } /// Trim trailing zeros from the buffer. - pub fn trim(&mut self) { + pub(super) fn trim(&mut self) { // All of the following calls to `Decimal::trim` can't panic because: // // 1. `parse_decimal` sets `num_digits` to a max of `Decimal::MAX_DIGITS`. @@ -83,7 +83,7 @@ impl Decimal { } } - pub fn round(&self) -> u64 { + pub(super) fn round(&self) -> u64 { if self.num_digits == 0 || self.decimal_point < 0 { return 0; } else if self.decimal_point > 18 { @@ -111,7 +111,7 @@ impl Decimal { } /// Computes decimal * 2^shift. - pub fn left_shift(&mut self, shift: usize) { + pub(super) fn left_shift(&mut self, shift: usize) { if self.num_digits == 0 { return; } @@ -152,7 +152,7 @@ impl Decimal { } /// Computes decimal * 2^-shift. - pub fn right_shift(&mut self, shift: usize) { + pub(super) fn right_shift(&mut self, shift: usize) { let mut read_index = 0; let mut write_index = 0; let mut n = 0_u64; @@ -202,7 +202,7 @@ impl Decimal { } /// Parse a big integer representation of the float as a decimal. -pub fn parse_decimal(mut s: &[u8]) -> Decimal { +pub(super) fn parse_decimal(mut s: &[u8]) -> Decimal { let mut d = Decimal::default(); let start = s; diff --git a/library/core/src/num/dec2flt/fpu.rs b/library/core/src/num/dec2flt/fpu.rs index 8d62684f8d3..daeee1755b0 100644 --- a/library/core/src/num/dec2flt/fpu.rs +++ b/library/core/src/num/dec2flt/fpu.rs @@ -1,7 +1,7 @@ //! Platform-specific, assembly instructions to avoid //! intermediate rounding on architectures with FPUs. -pub use fpu_precision::set_precision; +pub(super) use fpu_precision::set_precision; // On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available. // The x87 FPU operates with 80 bits of precision by default, which means that operations will @@ -42,7 +42,7 @@ mod fpu_precision { /// - 0b10, double precision i.e., 64-bits /// - 0b11, double extended precision i.e., 80-bits (default state) /// The 0b01 value is reserved and should not be used. - pub struct FPUControlWord(u16); + pub(crate) struct FPUControlWord(u16); fn set_cw(cw: u16) { // SAFETY: the `fldcw` instruction has been audited to be able to work correctly with @@ -57,7 +57,7 @@ mod fpu_precision { } /// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`. - pub fn set_precision<T>() -> FPUControlWord { + pub(crate) fn set_precision<T>() -> FPUControlWord { let mut cw = 0_u16; // Compute the value for the Precision Control field that is appropriate for `T`. @@ -97,5 +97,5 @@ mod fpu_precision { // precision of the computation is determined on a per-operation basis. #[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))] mod fpu_precision { - pub fn set_precision<T>() {} + pub(crate) fn set_precision<T>() {} } diff --git a/library/core/src/num/dec2flt/table.rs b/library/core/src/num/dec2flt/table.rs index 4856074a62b..942c2eacfd2 100644 --- a/library/core/src/num/dec2flt/table.rs +++ b/library/core/src/num/dec2flt/table.rs @@ -6,16 +6,17 @@ //! //! DO NOT MODIFY: Generated by `src/etc/dec2flt_table.py` -pub const SMALLEST_POWER_OF_FIVE: i32 = -342; -pub const LARGEST_POWER_OF_FIVE: i32 = 308; -pub const N_POWERS_OF_FIVE: usize = (LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize; +pub(super) const SMALLEST_POWER_OF_FIVE: i32 = -342; +pub(super) const LARGEST_POWER_OF_FIVE: i32 = 308; +pub(super) const N_POWERS_OF_FIVE: usize = + (LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize; // Use static to avoid long compile times: Rust compiler errors // can have the entire table compiled multiple times, and then // emit code multiple times, even if it's stripped out in // the final binary. #[rustfmt::skip] -pub static POWER_OF_FIVE_128: [(u64, u64); N_POWERS_OF_FIVE] = [ +pub(super) static POWER_OF_FIVE_128: [(u64, u64); N_POWERS_OF_FIVE] = [ (0xeef453d6923bd65a, 0x113faa2906a13b3f), // 5^-342 (0x9558b4661b6565f8, 0x4ac7ca59a424c507), // 5^-341 (0xbaaee17fa23ebf76, 0x5d79bcf00d2df649), // 5^-340 diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs index 0ce31b40a38..28a3f5d880a 100644 --- a/library/core/src/num/int_log10.rs +++ b/library/core/src/num/int_log10.rs @@ -3,7 +3,7 @@ // 0 < val <= u8::MAX #[inline] -pub const fn u8(val: u8) -> u32 { +pub(super) const fn u8(val: u8) -> u32 { let val = val as u32; // For better performance, avoid branches by assembling the solution @@ -45,13 +45,13 @@ const fn less_than_5(val: u32) -> u32 { // 0 < val <= u16::MAX #[inline] -pub const fn u16(val: u16) -> u32 { +pub(super) const fn u16(val: u16) -> u32 { less_than_5(val as u32) } // 0 < val <= u32::MAX #[inline] -pub const fn u32(mut val: u32) -> u32 { +pub(super) const fn u32(mut val: u32) -> u32 { let mut log = 0; if val >= 100_000 { val /= 100_000; @@ -62,7 +62,7 @@ pub const fn u32(mut val: u32) -> u32 { // 0 < val <= u64::MAX #[inline] -pub const fn u64(mut val: u64) -> u32 { +pub(super) const fn u64(mut val: u64) -> u32 { let mut log = 0; if val >= 10_000_000_000 { val /= 10_000_000_000; @@ -77,7 +77,7 @@ pub const fn u64(mut val: u64) -> u32 { // 0 < val <= u128::MAX #[inline] -pub const fn u128(mut val: u128) -> u32 { +pub(super) const fn u128(mut val: u128) -> u32 { let mut log = 0; if val >= 100_000_000_000_000_000_000_000_000_000_000 { val /= 100_000_000_000_000_000_000_000_000_000_000; @@ -93,49 +93,49 @@ pub const fn u128(mut val: u128) -> u32 { #[cfg(target_pointer_width = "16")] #[inline] -pub const fn usize(val: usize) -> u32 { +pub(super) const fn usize(val: usize) -> u32 { u16(val as _) } #[cfg(target_pointer_width = "32")] #[inline] -pub const fn usize(val: usize) -> u32 { +pub(super) const fn usize(val: usize) -> u32 { u32(val as _) } #[cfg(target_pointer_width = "64")] #[inline] -pub const fn usize(val: usize) -> u32 { +pub(super) const fn usize(val: usize) -> u32 { u64(val as _) } // 0 < val <= i8::MAX #[inline] -pub const fn i8(val: i8) -> u32 { +pub(super) const fn i8(val: i8) -> u32 { u8(val as u8) } // 0 < val <= i16::MAX #[inline] -pub const fn i16(val: i16) -> u32 { +pub(super) const fn i16(val: i16) -> u32 { u16(val as u16) } // 0 < val <= i32::MAX #[inline] -pub const fn i32(val: i32) -> u32 { +pub(super) const fn i32(val: i32) -> u32 { u32(val as u32) } // 0 < val <= i64::MAX #[inline] -pub const fn i64(val: i64) -> u32 { +pub(super) const fn i64(val: i64) -> u32 { u64(val as u64) } // 0 < val <= i128::MAX #[inline] -pub const fn i128(val: i128) -> u32 { +pub(super) const fn i128(val: i128) -> u32 { u128(val as u128) } @@ -143,6 +143,6 @@ pub const fn i128(val: i128) -> u32 { /// on every single primitive type. #[cold] #[track_caller] -pub const fn panic_for_nonpositive_argument() -> ! { +pub(super) const fn panic_for_nonpositive_argument() -> ! { panic!("argument of integer logarithm must be positive") } diff --git a/library/core/src/num/int_sqrt.rs b/library/core/src/num/int_sqrt.rs index 601e81f6993..c7a322c08c1 100644 --- a/library/core/src/num/int_sqrt.rs +++ b/library/core/src/num/int_sqrt.rs @@ -37,7 +37,7 @@ const U8_ISQRT_WITH_REMAINDER: [(u8, u8); 256] = { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] -pub const fn u8(n: u8) -> u8 { +pub(super) const fn u8(n: u8) -> u8 { U8_ISQRT_WITH_REMAINDER[n as usize].0 } @@ -58,7 +58,7 @@ macro_rules! signed_fn { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub const unsafe fn $SignedT(n: $SignedT) -> $SignedT { + pub(super) const unsafe fn $SignedT(n: $SignedT) -> $SignedT { debug_assert!(n >= 0, "Negative input inside `isqrt`."); $UnsignedT(n as $UnsignedT) as $SignedT } @@ -83,7 +83,7 @@ macro_rules! unsigned_fn { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub const fn $UnsignedT(mut n: $UnsignedT) -> $UnsignedT { + pub(super) const fn $UnsignedT(mut n: $UnsignedT) -> $UnsignedT { if n <= <$HalfBitsT>::MAX as $UnsignedT { $HalfBitsT(n as $HalfBitsT) as $UnsignedT } else { @@ -311,6 +311,6 @@ unsigned_fn!(u128, u64, u128_stages); /// on every single primitive type. #[cold] #[track_caller] -pub const fn panic_for_negative_argument() -> ! { +pub(super) const fn panic_for_negative_argument() -> ! { panic!("argument of integer square root cannot be negative") } diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index dbce64420ac..61e83ebfad7 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -90,6 +90,26 @@ impl_zeroable_primitive!( /// /// assert_eq!(size_of::<Option<NonZero<u32>>>(), size_of::<u32>()); /// ``` +/// +/// # Layout +/// +/// `NonZero<T>` is guaranteed to have the same layout and bit validity as `T` +/// with the exception that the all-zero bit pattern is invalid. +/// `Option<NonZero<T>>` is guaranteed to be compatible with `T`, including in +/// FFI. +/// +/// Thanks to the [null pointer optimization], `NonZero<T>` and +/// `Option<NonZero<T>>` are guaranteed to have the same size and alignment: +/// +/// ``` +/// # use std::mem::{size_of, align_of}; +/// use std::num::NonZero; +/// +/// assert_eq!(size_of::<NonZero<u32>>(), size_of::<Option<NonZero<u32>>>()); +/// assert_eq!(align_of::<NonZero<u32>>(), align_of::<Option<NonZero<u32>>>()); +/// ``` +/// +/// [null pointer optimization]: crate::option#representation #[stable(feature = "generic_nonzero", since = "1.79.0")] #[repr(transparent)] #[rustc_nonnull_optimization_guaranteed] @@ -1165,8 +1185,12 @@ macro_rules! nonzero_integer_signedness_dependent_impls { impl Div<NonZero<$Int>> for $Int { type Output = $Int; + /// Same as `self / other.get()`, but because `other` is a `NonZero<_>`, + /// there's never a runtime check for division-by-zero. + /// /// This operation rounds towards zero, truncating any fractional /// part of the exact result, and cannot panic. + #[doc(alias = "unchecked_div")] #[inline] fn div(self, other: NonZero<$Int>) -> $Int { // SAFETY: Division by zero is checked because `other` is non-zero, @@ -1177,6 +1201,9 @@ macro_rules! nonzero_integer_signedness_dependent_impls { #[stable(feature = "nonzero_div_assign", since = "1.79.0")] impl DivAssign<NonZero<$Int>> for $Int { + /// Same as `self /= other.get()`, but because `other` is a `NonZero<_>`, + /// there's never a runtime check for division-by-zero. + /// /// This operation rounds towards zero, truncating any fractional /// part of the exact result, and cannot panic. #[inline] diff --git a/library/core/src/num/overflow_panic.rs b/library/core/src/num/overflow_panic.rs index 203037ffb43..e30573dd3f3 100644 --- a/library/core/src/num/overflow_panic.rs +++ b/library/core/src/num/overflow_panic.rs @@ -4,48 +4,48 @@ #[cold] #[track_caller] -pub const fn add() -> ! { +pub(super) const fn add() -> ! { panic!("attempt to add with overflow") } #[cold] #[track_caller] -pub const fn sub() -> ! { +pub(super) const fn sub() -> ! { panic!("attempt to subtract with overflow") } #[cold] #[track_caller] -pub const fn mul() -> ! { +pub(super) const fn mul() -> ! { panic!("attempt to multiply with overflow") } #[cold] #[track_caller] -pub const fn div() -> ! { +pub(super) const fn div() -> ! { panic!("attempt to divide with overflow") } #[cold] #[track_caller] -pub const fn rem() -> ! { +pub(super) const fn rem() -> ! { panic!("attempt to calculate the remainder with overflow") } #[cold] #[track_caller] -pub const fn neg() -> ! { +pub(super) const fn neg() -> ! { panic!("attempt to negate with overflow") } #[cold] #[track_caller] -pub const fn shr() -> ! { +pub(super) const fn shr() -> ! { panic!("attempt to shift right with overflow") } #[cold] #[track_caller] -pub const fn shl() -> ! { +pub(super) const fn shl() -> ! { panic!("attempt to shift left with overflow") } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 404e4bcffd3..c8433b3bb16 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2663,8 +2663,8 @@ macro_rules! uint_impl { /// /// Basic usage: /// - /// Please note that this example is shared between integer types. - /// Which explains why `u32` is used here. + /// Please note that this example is shared between integer types, + /// which explains why `u32` is used here. /// /// ``` /// #![feature(bigint_helper_methods)] @@ -2677,6 +2677,35 @@ macro_rules! uint_impl { "(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX));" )] /// ``` + /// + /// This is the core per-digit operation for "grade school" O(n²) multiplication. + /// + /// Please note that this example is shared between integer types, + /// using `u8` for simplicity of the demonstration. + /// + /// ``` + /// #![feature(bigint_helper_methods)] + /// + /// fn quadratic_mul<const N: usize>(a: [u8; N], b: [u8; N]) -> [u8; N] { + /// let mut out = [0; N]; + /// for j in 0..N { + /// let mut carry = 0; + /// for i in 0..(N - j) { + /// (out[j + i], carry) = u8::carrying_mul_add(a[i], b[j], out[j + i], carry); + /// } + /// } + /// out + /// } + /// + /// // -1 * -1 == 1 + /// assert_eq!(quadratic_mul([0xFF; 3], [0xFF; 3]), [1, 0, 0]); + /// + /// assert_eq!(u32::wrapping_mul(0x9e3779b9, 0x7f4a7c15), 0xCFFC982D); + /// assert_eq!( + /// quadratic_mul(u32::to_le_bytes(0x9e3779b9), u32::to_le_bytes(0x7f4a7c15)), + /// u32::to_le_bytes(0xCFFC982D) + /// ); + /// ``` #[unstable(feature = "bigint_helper_methods", issue = "85532")] #[rustc_const_unstable(feature = "bigint_helper_methods", issue = "85532")] #[must_use = "this returns the result of the operation, \ diff --git a/library/core/src/num/wrapping.rs b/library/core/src/num/wrapping.rs index 1156b389e28..55fa91d0b9f 100644 --- a/library/core/src/num/wrapping.rs +++ b/library/core/src/num/wrapping.rs @@ -1058,33 +1058,33 @@ mod shift_max { #[cfg(target_pointer_width = "16")] mod platform { - pub const usize: u32 = super::u16; - pub const isize: u32 = super::i16; + pub(crate) const usize: u32 = super::u16; + pub(crate) const isize: u32 = super::i16; } #[cfg(target_pointer_width = "32")] mod platform { - pub const usize: u32 = super::u32; - pub const isize: u32 = super::i32; + pub(crate) const usize: u32 = super::u32; + pub(crate) const isize: u32 = super::i32; } #[cfg(target_pointer_width = "64")] mod platform { - pub const usize: u32 = super::u64; - pub const isize: u32 = super::i64; + pub(crate) const usize: u32 = super::u64; + pub(crate) const isize: u32 = super::i64; } - pub const i8: u32 = (1 << 3) - 1; - pub const i16: u32 = (1 << 4) - 1; - pub const i32: u32 = (1 << 5) - 1; - pub const i64: u32 = (1 << 6) - 1; - pub const i128: u32 = (1 << 7) - 1; - pub use self::platform::isize; - - pub const u8: u32 = i8; - pub const u16: u32 = i16; - pub const u32: u32 = i32; - pub const u64: u32 = i64; - pub const u128: u32 = i128; - pub use self::platform::usize; + pub(super) const i8: u32 = (1 << 3) - 1; + pub(super) const i16: u32 = (1 << 4) - 1; + pub(super) const i32: u32 = (1 << 5) - 1; + pub(super) const i64: u32 = (1 << 6) - 1; + pub(super) const i128: u32 = (1 << 7) - 1; + pub(super) use self::platform::isize; + + pub(super) const u8: u32 = i8; + pub(super) const u16: u32 = i16; + pub(super) const u32: u32 = i32; + pub(super) const u64: u32 = i64; + pub(super) const u128: u32 = i128; + pub(super) use self::platform::usize; } diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs index dce3514a159..b82184b15b2 100644 --- a/library/core/src/ops/index_range.rs +++ b/library/core/src/ops/index_range.rs @@ -18,7 +18,7 @@ impl IndexRange { /// # Safety /// - `start <= end` #[inline] - pub const unsafe fn new_unchecked(start: usize, end: usize) -> Self { + pub(crate) const unsafe fn new_unchecked(start: usize, end: usize) -> Self { ub_checks::assert_unsafe_precondition!( check_library_ub, "IndexRange::new_unchecked requires `start <= end`", @@ -28,22 +28,22 @@ impl IndexRange { } #[inline] - pub const fn zero_to(end: usize) -> Self { + pub(crate) const fn zero_to(end: usize) -> Self { IndexRange { start: 0, end } } #[inline] - pub const fn start(&self) -> usize { + pub(crate) const fn start(&self) -> usize { self.start } #[inline] - pub const fn end(&self) -> usize { + pub(crate) const fn end(&self) -> usize { self.end } #[inline] - pub const fn len(&self) -> usize { + pub(crate) const fn len(&self) -> usize { // SAFETY: By invariant, this cannot wrap // Using the intrinsic because a UB check here impedes LLVM optimization. (#131563) unsafe { crate::intrinsics::unchecked_sub(self.end, self.start) } @@ -79,7 +79,7 @@ impl IndexRange { /// /// This is designed to help implement `Iterator::advance_by`. #[inline] - pub fn take_prefix(&mut self, n: usize) -> Self { + pub(crate) fn take_prefix(&mut self, n: usize) -> Self { let mid = if n <= self.len() { // SAFETY: We just checked that this will be between start and end, // and thus the addition cannot overflow. @@ -99,7 +99,7 @@ impl IndexRange { /// /// This is designed to help implement `Iterator::advance_back_by`. #[inline] - pub fn take_suffix(&mut self, n: usize) -> Self { + pub(crate) fn take_suffix(&mut self, n: usize) -> Self { let mid = if n <= self.len() { // SAFETY: We just checked that this will be between start and end, // and thus the subtraction cannot overflow. diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index cd444c86ed0..3ba2957526f 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -338,6 +338,7 @@ pub trait FromResidual<R = <Self as Try>::Residual> { #[inline] #[track_caller] // because `Result::from_residual` has it #[lang = "from_yeet"] +#[allow(unreachable_pub)] // not-exposed but still used via lang-item pub fn from_yeet<T, Y>(yeeted: Y) -> T where T: FromResidual<Yeet<Y>>, @@ -383,12 +384,14 @@ impl<T> NeverShortCircuit<T> { /// This is useful for implementing infallible functions in terms of the `try_` ones, /// without accidentally capturing extra generic parameters in a closure. #[inline] - pub fn wrap_mut_1<A>(mut f: impl FnMut(A) -> T) -> impl FnMut(A) -> NeverShortCircuit<T> { + pub(crate) fn wrap_mut_1<A>( + mut f: impl FnMut(A) -> T, + ) -> impl FnMut(A) -> NeverShortCircuit<T> { move |a| NeverShortCircuit(f(a)) } #[inline] - pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { + pub(crate) fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { move |a, b| NeverShortCircuit(f(a, b)) } } diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 71044190f0c..2a0bf89fcf7 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -156,8 +156,8 @@ //! //! In order to implement the second option, we must in some way enforce its key invariant, //! *i.e.* prevent the value from being *moved* or otherwise invalidated (you may notice this -//! sounds an awful lot like the definition of *pinning* a value). There a few ways one might be -//! able to enforce this invariant in Rust: +//! sounds an awful lot like the definition of *pinning* a value). There are a few ways one might +//! be able to enforce this invariant in Rust: //! //! 1. Offer a wholly `unsafe` API to interact with the object, thus requiring every caller to //! uphold the invariant themselves diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index ba5746d0ade..1993a7491e1 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -1099,10 +1099,15 @@ impl<T> [T] { /// assert!(iter.next().is_none()); /// ``` /// - /// There's no `windows_mut`, as that existing would let safe code violate the - /// "only one `&mut` at a time to the same thing" rule. However, you can sometimes - /// use [`Cell::as_slice_of_cells`](crate::cell::Cell::as_slice_of_cells) in - /// conjunction with `windows` to accomplish something similar: + /// Because the [Iterator] trait cannot represent the required lifetimes, + /// there is no `windows_mut` analog to `windows`; + /// `[0,1,2].windows_mut(2).collect()` would violate [the rules of references] + /// (though a [LendingIterator] analog is possible). You can sometimes use + /// [`Cell::as_slice_of_cells`](crate::cell::Cell::as_slice_of_cells) in + /// conjunction with `windows` instead: + /// + /// [the rules of references]: https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references + /// [LendingIterator]: https://blog.rust-lang.org/2022/10/28/gats-stabilization.html /// ``` /// use std::cell::Cell; /// diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs index 1e4865a7caa..d8e0acb565c 100644 --- a/library/core/src/slice/rotate.rs +++ b/library/core/src/slice/rotate.rs @@ -60,7 +60,7 @@ use crate::{cmp, ptr}; /// we cannot swap any more, but a smaller rotation problem is left to solve /// ``` /// when `left < right` the swapping happens from the left instead. -pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) { +pub(super) unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) { type BufType = [usize; 32]; if T::IS_ZST { return; diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index fda26a67299..859ac163230 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -3727,33 +3727,33 @@ pub fn fence(order: Ordering) { /// /// # Examples /// -/// Without `compiler_fence`, the `assert_eq!` in following code -/// is *not* guaranteed to succeed, despite everything happening in a single thread. -/// To see why, remember that the compiler is free to swap the stores to -/// `IMPORTANT_VARIABLE` and `IS_READY` since they are both -/// `Ordering::Relaxed`. If it does, and the signal handler is invoked right -/// after `IS_READY` is updated, then the signal handler will see -/// `IS_READY=1`, but `IMPORTANT_VARIABLE=0`. -/// Using a `compiler_fence` remedies this situation. +/// Without the two `compiler_fence` calls, the read of `IMPORTANT_VARIABLE` in `signal_handler` +/// is *undefined behavior* due to a data race, despite everything happening in a single thread. +/// This is because the signal handler is considered to run concurrently with its associated +/// thread, and explicit synchronization is required to pass data between a thread and its +/// signal handler. The code below uses two `compiler_fence` calls to establish the usual +/// release-acquire synchronization pattern (see [`fence`] for an image). /// /// ``` -/// use std::sync::atomic::{AtomicBool, AtomicUsize}; +/// use std::sync::atomic::AtomicBool; /// use std::sync::atomic::Ordering; /// use std::sync::atomic::compiler_fence; /// -/// static IMPORTANT_VARIABLE: AtomicUsize = AtomicUsize::new(0); +/// static mut IMPORTANT_VARIABLE: usize = 0; /// static IS_READY: AtomicBool = AtomicBool::new(false); /// /// fn main() { -/// IMPORTANT_VARIABLE.store(42, Ordering::Relaxed); -/// // prevent earlier writes from being moved beyond this point +/// unsafe { IMPORTANT_VARIABLE = 42 }; +/// // Marks earlier writes as being released with future relaxed stores. /// compiler_fence(Ordering::Release); /// IS_READY.store(true, Ordering::Relaxed); /// } /// /// fn signal_handler() { /// if IS_READY.load(Ordering::Relaxed) { -/// assert_eq!(IMPORTANT_VARIABLE.load(Ordering::Relaxed), 42); +/// // Acquires writes that were released with relaxed stores that we read from. +/// compiler_fence(Ordering::Acquire); +/// assert_eq!(unsafe { IMPORTANT_VARIABLE }, 42); /// } /// } /// ``` diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 6066aa99216..49dbdeb1a6d 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -17,6 +17,8 @@ pub(crate) use unicode_data::uppercase::lookup as Uppercase; pub(crate) use unicode_data::white_space::lookup as White_Space; pub(crate) mod printable; + +#[allow(unreachable_pub)] mod unicode_data; /// The version of [Unicode](https://www.unicode.org/) that the Unicode parts of diff --git a/library/coretests/Cargo.toml b/library/coretests/Cargo.toml new file mode 100644 index 00000000000..ec940abea11 --- /dev/null +++ b/library/coretests/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "coretests" +version = "0.0.0" +license = "MIT OR Apache-2.0" +repository = "https://github.com/rust-lang/rust.git" +description = "Tests for the Rust Core Library" +autotests = false +autobenches = false +edition = "2021" + +[lib] +path = "lib.rs" +test = false +bench = false + +[[test]] +name = "coretests" +path = "tests/lib.rs" + +[[bench]] +name = "corebenches" +path = "benches/lib.rs" +test = true + +[dev-dependencies] +rand = { version = "0.8.5", default-features = false } +rand_xorshift = { version = "0.3.0", default-features = false } diff --git a/library/core/benches/any.rs b/library/coretests/benches/any.rs index 6b150432f87..6b150432f87 100644 --- a/library/core/benches/any.rs +++ b/library/coretests/benches/any.rs diff --git a/library/core/benches/array.rs b/library/coretests/benches/array.rs index 751f3235a5f..751f3235a5f 100644 --- a/library/core/benches/array.rs +++ b/library/coretests/benches/array.rs diff --git a/library/core/benches/ascii.rs b/library/coretests/benches/ascii.rs index 3fe45aa360b..3fe45aa360b 100644 --- a/library/core/benches/ascii.rs +++ b/library/coretests/benches/ascii.rs diff --git a/library/core/benches/ascii/is_ascii.rs b/library/coretests/benches/ascii/is_ascii.rs index ced7084fb0e..ced7084fb0e 100644 --- a/library/core/benches/ascii/is_ascii.rs +++ b/library/coretests/benches/ascii/is_ascii.rs diff --git a/library/core/benches/char/methods.rs b/library/coretests/benches/char/methods.rs index ed71920a4fc..ed71920a4fc 100644 --- a/library/core/benches/char/methods.rs +++ b/library/coretests/benches/char/methods.rs diff --git a/library/core/benches/char/mod.rs b/library/coretests/benches/char/mod.rs index 9ca51a76847..9ca51a76847 100644 --- a/library/core/benches/char/mod.rs +++ b/library/coretests/benches/char/mod.rs diff --git a/library/core/benches/fmt.rs b/library/coretests/benches/fmt.rs index ed478b0f1e0..ed478b0f1e0 100644 --- a/library/core/benches/fmt.rs +++ b/library/coretests/benches/fmt.rs diff --git a/library/core/benches/hash/mod.rs b/library/coretests/benches/hash/mod.rs index 4f2e152b695..4f2e152b695 100644 --- a/library/core/benches/hash/mod.rs +++ b/library/coretests/benches/hash/mod.rs diff --git a/library/core/benches/hash/sip.rs b/library/coretests/benches/hash/sip.rs index c6562d3c011..c6562d3c011 100644 --- a/library/core/benches/hash/sip.rs +++ b/library/coretests/benches/hash/sip.rs diff --git a/library/core/benches/iter.rs b/library/coretests/benches/iter.rs index e14f26b7290..e14f26b7290 100644 --- a/library/core/benches/iter.rs +++ b/library/coretests/benches/iter.rs diff --git a/library/core/benches/lib.rs b/library/coretests/benches/lib.rs index 32d15c386cb..32d15c386cb 100644 --- a/library/core/benches/lib.rs +++ b/library/coretests/benches/lib.rs diff --git a/library/core/benches/net/addr_parser.rs b/library/coretests/benches/net/addr_parser.rs index bbf2ea3eb97..bbf2ea3eb97 100644 --- a/library/core/benches/net/addr_parser.rs +++ b/library/coretests/benches/net/addr_parser.rs diff --git a/library/core/benches/net/mod.rs b/library/coretests/benches/net/mod.rs index c29aed46ccd..c29aed46ccd 100644 --- a/library/core/benches/net/mod.rs +++ b/library/coretests/benches/net/mod.rs diff --git a/library/core/benches/num/dec2flt/mod.rs b/library/coretests/benches/num/dec2flt/mod.rs index bad211f240c..bad211f240c 100644 --- a/library/core/benches/num/dec2flt/mod.rs +++ b/library/coretests/benches/num/dec2flt/mod.rs diff --git a/library/core/benches/num/flt2dec/mod.rs b/library/coretests/benches/num/flt2dec/mod.rs index 428d0bbbbfb..428d0bbbbfb 100644 --- a/library/core/benches/num/flt2dec/mod.rs +++ b/library/coretests/benches/num/flt2dec/mod.rs diff --git a/library/core/benches/num/flt2dec/strategy/dragon.rs b/library/coretests/benches/num/flt2dec/strategy/dragon.rs index 45266971403..45266971403 100644 --- a/library/core/benches/num/flt2dec/strategy/dragon.rs +++ b/library/coretests/benches/num/flt2dec/strategy/dragon.rs diff --git a/library/core/benches/num/flt2dec/strategy/grisu.rs b/library/coretests/benches/num/flt2dec/strategy/grisu.rs index d20f9b02f7e..d20f9b02f7e 100644 --- a/library/core/benches/num/flt2dec/strategy/grisu.rs +++ b/library/coretests/benches/num/flt2dec/strategy/grisu.rs diff --git a/library/core/benches/num/int_log/mod.rs b/library/coretests/benches/num/int_log/mod.rs index e5874ddf03b..e5874ddf03b 100644 --- a/library/core/benches/num/int_log/mod.rs +++ b/library/coretests/benches/num/int_log/mod.rs diff --git a/library/core/benches/num/int_pow/mod.rs b/library/coretests/benches/num/int_pow/mod.rs index 46f47028d56..46f47028d56 100644 --- a/library/core/benches/num/int_pow/mod.rs +++ b/library/coretests/benches/num/int_pow/mod.rs diff --git a/library/core/benches/num/int_sqrt/mod.rs b/library/coretests/benches/num/int_sqrt/mod.rs index e47b92e866e..e47b92e866e 100644 --- a/library/core/benches/num/int_sqrt/mod.rs +++ b/library/coretests/benches/num/int_sqrt/mod.rs diff --git a/library/core/benches/num/mod.rs b/library/coretests/benches/num/mod.rs index b36100e59a9..b36100e59a9 100644 --- a/library/core/benches/num/mod.rs +++ b/library/coretests/benches/num/mod.rs diff --git a/library/core/benches/ops.rs b/library/coretests/benches/ops.rs index 3d0b3302957..3d0b3302957 100644 --- a/library/core/benches/ops.rs +++ b/library/coretests/benches/ops.rs diff --git a/library/core/benches/pattern.rs b/library/coretests/benches/pattern.rs index b0f8b39c22e..b0f8b39c22e 100644 --- a/library/core/benches/pattern.rs +++ b/library/coretests/benches/pattern.rs diff --git a/library/core/benches/slice.rs b/library/coretests/benches/slice.rs index 29a66b62199..29a66b62199 100644 --- a/library/core/benches/slice.rs +++ b/library/coretests/benches/slice.rs diff --git a/library/core/benches/str.rs b/library/coretests/benches/str.rs index 2f7d9d56a70..2f7d9d56a70 100644 --- a/library/core/benches/str.rs +++ b/library/coretests/benches/str.rs diff --git a/library/core/benches/str/char_count.rs b/library/coretests/benches/str/char_count.rs index 343e23dcf41..343e23dcf41 100644 --- a/library/core/benches/str/char_count.rs +++ b/library/coretests/benches/str/char_count.rs diff --git a/library/core/benches/str/corpora.rs b/library/coretests/benches/str/corpora.rs index b4ac625061d..b4ac625061d 100644 --- a/library/core/benches/str/corpora.rs +++ b/library/coretests/benches/str/corpora.rs diff --git a/library/core/benches/str/debug.rs b/library/coretests/benches/str/debug.rs index e41d4fa110a..e41d4fa110a 100644 --- a/library/core/benches/str/debug.rs +++ b/library/coretests/benches/str/debug.rs diff --git a/library/core/benches/str/iter.rs b/library/coretests/benches/str/iter.rs index d2586cef258..d2586cef258 100644 --- a/library/core/benches/str/iter.rs +++ b/library/coretests/benches/str/iter.rs diff --git a/library/core/benches/tuple.rs b/library/coretests/benches/tuple.rs index dcda7c641aa..dcda7c641aa 100644 --- a/library/core/benches/tuple.rs +++ b/library/coretests/benches/tuple.rs diff --git a/library/coretests/lib.rs b/library/coretests/lib.rs new file mode 100644 index 00000000000..b49208cd4eb --- /dev/null +++ b/library/coretests/lib.rs @@ -0,0 +1 @@ +// Intentionally left empty. diff --git a/library/core/tests/alloc.rs b/library/coretests/tests/alloc.rs index b88f1821cd7..b88f1821cd7 100644 --- a/library/core/tests/alloc.rs +++ b/library/coretests/tests/alloc.rs diff --git a/library/core/tests/any.rs b/library/coretests/tests/any.rs index 25002617d0b..25002617d0b 100644 --- a/library/core/tests/any.rs +++ b/library/coretests/tests/any.rs diff --git a/library/core/tests/array.rs b/library/coretests/tests/array.rs index b6d18f1ec38..b6d18f1ec38 100644 --- a/library/core/tests/array.rs +++ b/library/coretests/tests/array.rs diff --git a/library/core/tests/ascii.rs b/library/coretests/tests/ascii.rs index ce09ee507f1..ce09ee507f1 100644 --- a/library/core/tests/ascii.rs +++ b/library/coretests/tests/ascii.rs diff --git a/library/core/tests/ascii_char.rs b/library/coretests/tests/ascii_char.rs index 75b5fd4b9e6..75b5fd4b9e6 100644 --- a/library/core/tests/ascii_char.rs +++ b/library/coretests/tests/ascii_char.rs diff --git a/library/core/tests/asserting.rs b/library/coretests/tests/asserting.rs index 1d9670886eb..1d9670886eb 100644 --- a/library/core/tests/asserting.rs +++ b/library/coretests/tests/asserting.rs diff --git a/library/core/tests/async_iter/mod.rs b/library/coretests/tests/async_iter/mod.rs index 4f425d7286d..4f425d7286d 100644 --- a/library/core/tests/async_iter/mod.rs +++ b/library/coretests/tests/async_iter/mod.rs diff --git a/library/core/tests/atomic.rs b/library/coretests/tests/atomic.rs index 0ffba538b20..0ffba538b20 100644 --- a/library/core/tests/atomic.rs +++ b/library/coretests/tests/atomic.rs diff --git a/library/core/tests/bool.rs b/library/coretests/tests/bool.rs index 47f6459915b..47f6459915b 100644 --- a/library/core/tests/bool.rs +++ b/library/coretests/tests/bool.rs diff --git a/library/coretests/tests/bstr.rs b/library/coretests/tests/bstr.rs new file mode 100644 index 00000000000..cd4d69d6b33 --- /dev/null +++ b/library/coretests/tests/bstr.rs @@ -0,0 +1,52 @@ +use core::bstr::ByteStr; + +#[test] +fn test_debug() { + assert_eq!( + r#""\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff""#, + format!("{:?}", ByteStr::new(b"\0\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x11\x12\r\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f \x7f\x80\x81\xfe\xff")), + ); +} + +#[test] +fn test_display() { + let b1 = ByteStr::new("abc"); + let b2 = ByteStr::new(b"\xf0\x28\x8c\xbc"); + + assert_eq!(&format!("{b1}"), "abc"); + assert_eq!(&format!("{b2}"), "�(��"); + + assert_eq!(&format!("{b1:<7}!"), "abc !"); + assert_eq!(&format!("{b1:>7}!"), " abc!"); + assert_eq!(&format!("{b1:^7}!"), " abc !"); + assert_eq!(&format!("{b1:^6}!"), " abc !"); + assert_eq!(&format!("{b1:-<7}!"), "abc----!"); + assert_eq!(&format!("{b1:->7}!"), "----abc!"); + assert_eq!(&format!("{b1:-^7}!"), "--abc--!"); + assert_eq!(&format!("{b1:-^6}!"), "-abc--!"); + + assert_eq!(&format!("{b2:<7}!"), "�(�� !"); + assert_eq!(&format!("{b2:>7}!"), " �(��!"); + assert_eq!(&format!("{b2:^7}!"), " �(�� !"); + assert_eq!(&format!("{b2:^6}!"), " �(�� !"); + assert_eq!(&format!("{b2:-<7}!"), "�(��---!"); + assert_eq!(&format!("{b2:->7}!"), "---�(��!"); + assert_eq!(&format!("{b2:-^7}!"), "-�(��--!"); + assert_eq!(&format!("{b2:-^6}!"), "-�(��-!"); + + assert_eq!(&format!("{b1:<2}!"), "abc!"); + assert_eq!(&format!("{b1:>2}!"), "abc!"); + assert_eq!(&format!("{b1:^2}!"), "abc!"); + assert_eq!(&format!("{b1:-<2}!"), "abc!"); + assert_eq!(&format!("{b1:->2}!"), "abc!"); + assert_eq!(&format!("{b1:-^2}!"), "abc!"); + + assert_eq!(&format!("{b2:<3}!"), "�(��!"); + assert_eq!(&format!("{b2:>3}!"), "�(��!"); + assert_eq!(&format!("{b2:^3}!"), "�(��!"); + assert_eq!(&format!("{b2:^2}!"), "�(��!"); + assert_eq!(&format!("{b2:-<3}!"), "�(��!"); + assert_eq!(&format!("{b2:->3}!"), "�(��!"); + assert_eq!(&format!("{b2:-^3}!"), "�(��!"); + assert_eq!(&format!("{b2:-^2}!"), "�(��!"); +} diff --git a/library/core/tests/cell.rs b/library/coretests/tests/cell.rs index d6a401c2b4d..d6a401c2b4d 100644 --- a/library/core/tests/cell.rs +++ b/library/coretests/tests/cell.rs diff --git a/library/core/tests/char.rs b/library/coretests/tests/char.rs index 6422387e956..6422387e956 100644 --- a/library/core/tests/char.rs +++ b/library/coretests/tests/char.rs diff --git a/library/core/tests/clone.rs b/library/coretests/tests/clone.rs index 054b1d3d498..054b1d3d498 100644 --- a/library/core/tests/clone.rs +++ b/library/coretests/tests/clone.rs diff --git a/library/core/tests/cmp.rs b/library/coretests/tests/cmp.rs index 6c4e2146f91..6c4e2146f91 100644 --- a/library/core/tests/cmp.rs +++ b/library/coretests/tests/cmp.rs diff --git a/library/core/tests/const_ptr.rs b/library/coretests/tests/const_ptr.rs index d874f08317f..d874f08317f 100644 --- a/library/core/tests/const_ptr.rs +++ b/library/coretests/tests/const_ptr.rs diff --git a/library/core/tests/convert.rs b/library/coretests/tests/convert.rs index f76dd277884..f76dd277884 100644 --- a/library/core/tests/convert.rs +++ b/library/coretests/tests/convert.rs diff --git a/library/core/tests/error.rs b/library/coretests/tests/error.rs index 996566d3848..996566d3848 100644 --- a/library/core/tests/error.rs +++ b/library/coretests/tests/error.rs diff --git a/library/core/tests/ffi.rs b/library/coretests/tests/ffi.rs index 2b33fbd95f0..2b33fbd95f0 100644 --- a/library/core/tests/ffi.rs +++ b/library/coretests/tests/ffi.rs diff --git a/library/core/tests/ffi/cstr.rs b/library/coretests/tests/ffi/cstr.rs index 9bf4c21a9ab..9bf4c21a9ab 100644 --- a/library/core/tests/ffi/cstr.rs +++ b/library/coretests/tests/ffi/cstr.rs diff --git a/library/core/tests/fmt/builders.rs b/library/coretests/tests/fmt/builders.rs index ba4801f5912..ba4801f5912 100644 --- a/library/core/tests/fmt/builders.rs +++ b/library/coretests/tests/fmt/builders.rs diff --git a/library/core/tests/fmt/float.rs b/library/coretests/tests/fmt/float.rs index 003782f34dc..003782f34dc 100644 --- a/library/core/tests/fmt/float.rs +++ b/library/coretests/tests/fmt/float.rs diff --git a/library/core/tests/fmt/mod.rs b/library/coretests/tests/fmt/mod.rs index 2c93a9bc80d..025c69c4f62 100644 --- a/library/core/tests/fmt/mod.rs +++ b/library/coretests/tests/fmt/mod.rs @@ -52,6 +52,12 @@ fn test_maybe_uninit_short() { } #[test] +fn formatting_options_ctor() { + use core::fmt::FormattingOptions; + assert_eq!(FormattingOptions::new(), FormattingOptions::default()); +} + +#[test] fn formatting_options_flags() { use core::fmt::*; for sign in [None, Some(Sign::Plus), Some(Sign::Minus)] { diff --git a/library/core/tests/fmt/num.rs b/library/coretests/tests/fmt/num.rs index bc387a46ea7..bc387a46ea7 100644 --- a/library/core/tests/fmt/num.rs +++ b/library/coretests/tests/fmt/num.rs diff --git a/library/core/tests/future.rs b/library/coretests/tests/future.rs index ebfe5a0a66d..ebfe5a0a66d 100644 --- a/library/core/tests/future.rs +++ b/library/coretests/tests/future.rs diff --git a/library/core/tests/hash/mod.rs b/library/coretests/tests/hash/mod.rs index 9f14995f73f..1f10a4733b0 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/coretests/tests/hash/mod.rs @@ -141,9 +141,6 @@ fn test_custom_state() { // const { assert!(hash(&Custom { hash: 6 }) == 6) }; } -// FIXME: Instantiated functions with i128 in the signature is not supported in Emscripten. -// See https://github.com/kripken/emscripten-fastcomp/issues/169 -#[cfg(not(target_os = "emscripten"))] #[test] fn test_indirect_hasher() { let mut hasher = MyHasher { hash: 0 }; diff --git a/library/core/tests/hash/sip.rs b/library/coretests/tests/hash/sip.rs index f79954f916b..f79954f916b 100644 --- a/library/core/tests/hash/sip.rs +++ b/library/coretests/tests/hash/sip.rs diff --git a/library/core/tests/intrinsics.rs b/library/coretests/tests/intrinsics.rs index 744a6a0d2dd..744a6a0d2dd 100644 --- a/library/core/tests/intrinsics.rs +++ b/library/coretests/tests/intrinsics.rs diff --git a/library/core/tests/io/borrowed_buf.rs b/library/coretests/tests/io/borrowed_buf.rs index a5dd4e52577..a5dd4e52577 100644 --- a/library/core/tests/io/borrowed_buf.rs +++ b/library/coretests/tests/io/borrowed_buf.rs diff --git a/library/core/tests/io/mod.rs b/library/coretests/tests/io/mod.rs index a24893a525a..a24893a525a 100644 --- a/library/core/tests/io/mod.rs +++ b/library/coretests/tests/io/mod.rs diff --git a/library/core/tests/iter/adapters/array_chunks.rs b/library/coretests/tests/iter/adapters/array_chunks.rs index fb19a519f63..fb19a519f63 100644 --- a/library/core/tests/iter/adapters/array_chunks.rs +++ b/library/coretests/tests/iter/adapters/array_chunks.rs diff --git a/library/core/tests/iter/adapters/by_ref_sized.rs b/library/coretests/tests/iter/adapters/by_ref_sized.rs index a9c066f0e8c..a9c066f0e8c 100644 --- a/library/core/tests/iter/adapters/by_ref_sized.rs +++ b/library/coretests/tests/iter/adapters/by_ref_sized.rs diff --git a/library/core/tests/iter/adapters/chain.rs b/library/coretests/tests/iter/adapters/chain.rs index 1b2c026ee1e..1b2c026ee1e 100644 --- a/library/core/tests/iter/adapters/chain.rs +++ b/library/coretests/tests/iter/adapters/chain.rs diff --git a/library/core/tests/iter/adapters/cloned.rs b/library/coretests/tests/iter/adapters/cloned.rs index 78babb7feab..78babb7feab 100644 --- a/library/core/tests/iter/adapters/cloned.rs +++ b/library/coretests/tests/iter/adapters/cloned.rs diff --git a/library/core/tests/iter/adapters/copied.rs b/library/coretests/tests/iter/adapters/copied.rs index b12f2035dc1..b12f2035dc1 100644 --- a/library/core/tests/iter/adapters/copied.rs +++ b/library/coretests/tests/iter/adapters/copied.rs diff --git a/library/core/tests/iter/adapters/cycle.rs b/library/coretests/tests/iter/adapters/cycle.rs index 8831c09b48b..8831c09b48b 100644 --- a/library/core/tests/iter/adapters/cycle.rs +++ b/library/coretests/tests/iter/adapters/cycle.rs diff --git a/library/core/tests/iter/adapters/enumerate.rs b/library/coretests/tests/iter/adapters/enumerate.rs index b57d51c077e..b57d51c077e 100644 --- a/library/core/tests/iter/adapters/enumerate.rs +++ b/library/coretests/tests/iter/adapters/enumerate.rs diff --git a/library/core/tests/iter/adapters/filter.rs b/library/coretests/tests/iter/adapters/filter.rs index 167851e3333..167851e3333 100644 --- a/library/core/tests/iter/adapters/filter.rs +++ b/library/coretests/tests/iter/adapters/filter.rs diff --git a/library/core/tests/iter/adapters/filter_map.rs b/library/coretests/tests/iter/adapters/filter_map.rs index 46738eda63f..46738eda63f 100644 --- a/library/core/tests/iter/adapters/filter_map.rs +++ b/library/coretests/tests/iter/adapters/filter_map.rs diff --git a/library/core/tests/iter/adapters/flat_map.rs b/library/coretests/tests/iter/adapters/flat_map.rs index ee945e69801..ee945e69801 100644 --- a/library/core/tests/iter/adapters/flat_map.rs +++ b/library/coretests/tests/iter/adapters/flat_map.rs diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/coretests/tests/iter/adapters/flatten.rs index 66b7b6cb563..66b7b6cb563 100644 --- a/library/core/tests/iter/adapters/flatten.rs +++ b/library/coretests/tests/iter/adapters/flatten.rs diff --git a/library/core/tests/iter/adapters/fuse.rs b/library/coretests/tests/iter/adapters/fuse.rs index f41b379b3ac..f41b379b3ac 100644 --- a/library/core/tests/iter/adapters/fuse.rs +++ b/library/coretests/tests/iter/adapters/fuse.rs diff --git a/library/core/tests/iter/adapters/inspect.rs b/library/coretests/tests/iter/adapters/inspect.rs index 939e3a28a72..939e3a28a72 100644 --- a/library/core/tests/iter/adapters/inspect.rs +++ b/library/coretests/tests/iter/adapters/inspect.rs diff --git a/library/core/tests/iter/adapters/intersperse.rs b/library/coretests/tests/iter/adapters/intersperse.rs index 72ae59b6b2f..72ae59b6b2f 100644 --- a/library/core/tests/iter/adapters/intersperse.rs +++ b/library/coretests/tests/iter/adapters/intersperse.rs diff --git a/library/core/tests/iter/adapters/map.rs b/library/coretests/tests/iter/adapters/map.rs index 77ce3819b32..77ce3819b32 100644 --- a/library/core/tests/iter/adapters/map.rs +++ b/library/coretests/tests/iter/adapters/map.rs diff --git a/library/core/tests/iter/adapters/map_windows.rs b/library/coretests/tests/iter/adapters/map_windows.rs index b677f1cfd55..b677f1cfd55 100644 --- a/library/core/tests/iter/adapters/map_windows.rs +++ b/library/coretests/tests/iter/adapters/map_windows.rs diff --git a/library/core/tests/iter/adapters/mod.rs b/library/coretests/tests/iter/adapters/mod.rs index dedb4c0a9dd..dedb4c0a9dd 100644 --- a/library/core/tests/iter/adapters/mod.rs +++ b/library/coretests/tests/iter/adapters/mod.rs diff --git a/library/core/tests/iter/adapters/peekable.rs b/library/coretests/tests/iter/adapters/peekable.rs index 7f4341b8902..7f4341b8902 100644 --- a/library/core/tests/iter/adapters/peekable.rs +++ b/library/coretests/tests/iter/adapters/peekable.rs diff --git a/library/core/tests/iter/adapters/scan.rs b/library/coretests/tests/iter/adapters/scan.rs index 1d28ca6b7fd..1d28ca6b7fd 100644 --- a/library/core/tests/iter/adapters/scan.rs +++ b/library/coretests/tests/iter/adapters/scan.rs diff --git a/library/core/tests/iter/adapters/skip.rs b/library/coretests/tests/iter/adapters/skip.rs index 8d5d06ad9fb..8d5d06ad9fb 100644 --- a/library/core/tests/iter/adapters/skip.rs +++ b/library/coretests/tests/iter/adapters/skip.rs diff --git a/library/core/tests/iter/adapters/skip_while.rs b/library/coretests/tests/iter/adapters/skip_while.rs index 929d4f6e64f..929d4f6e64f 100644 --- a/library/core/tests/iter/adapters/skip_while.rs +++ b/library/coretests/tests/iter/adapters/skip_while.rs diff --git a/library/core/tests/iter/adapters/step_by.rs b/library/coretests/tests/iter/adapters/step_by.rs index 6f3300e7a88..6f3300e7a88 100644 --- a/library/core/tests/iter/adapters/step_by.rs +++ b/library/coretests/tests/iter/adapters/step_by.rs diff --git a/library/core/tests/iter/adapters/take.rs b/library/coretests/tests/iter/adapters/take.rs index b932059afec..b932059afec 100644 --- a/library/core/tests/iter/adapters/take.rs +++ b/library/coretests/tests/iter/adapters/take.rs diff --git a/library/core/tests/iter/adapters/take_while.rs b/library/coretests/tests/iter/adapters/take_while.rs index 6f1ebab29b3..6f1ebab29b3 100644 --- a/library/core/tests/iter/adapters/take_while.rs +++ b/library/coretests/tests/iter/adapters/take_while.rs diff --git a/library/core/tests/iter/adapters/zip.rs b/library/coretests/tests/iter/adapters/zip.rs index 70392dca0fa..70392dca0fa 100644 --- a/library/core/tests/iter/adapters/zip.rs +++ b/library/coretests/tests/iter/adapters/zip.rs diff --git a/library/core/tests/iter/mod.rs b/library/coretests/tests/iter/mod.rs index 5b2769d0469..5b2769d0469 100644 --- a/library/core/tests/iter/mod.rs +++ b/library/coretests/tests/iter/mod.rs diff --git a/library/core/tests/iter/range.rs b/library/coretests/tests/iter/range.rs index d5d2b8bf2b0..d5d2b8bf2b0 100644 --- a/library/core/tests/iter/range.rs +++ b/library/coretests/tests/iter/range.rs diff --git a/library/core/tests/iter/sources.rs b/library/coretests/tests/iter/sources.rs index 506febaa056..506febaa056 100644 --- a/library/core/tests/iter/sources.rs +++ b/library/coretests/tests/iter/sources.rs diff --git a/library/core/tests/iter/traits/accum.rs b/library/coretests/tests/iter/traits/accum.rs index f3eeb31fe58..f3eeb31fe58 100644 --- a/library/core/tests/iter/traits/accum.rs +++ b/library/coretests/tests/iter/traits/accum.rs diff --git a/library/core/tests/iter/traits/double_ended.rs b/library/coretests/tests/iter/traits/double_ended.rs index 00ef4a6e6a9..00ef4a6e6a9 100644 --- a/library/core/tests/iter/traits/double_ended.rs +++ b/library/coretests/tests/iter/traits/double_ended.rs diff --git a/library/core/tests/iter/traits/iterator.rs b/library/coretests/tests/iter/traits/iterator.rs index e31d2e15b6d..e31d2e15b6d 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/coretests/tests/iter/traits/iterator.rs diff --git a/library/core/tests/iter/traits/mod.rs b/library/coretests/tests/iter/traits/mod.rs index 80619f53f25..80619f53f25 100644 --- a/library/core/tests/iter/traits/mod.rs +++ b/library/coretests/tests/iter/traits/mod.rs diff --git a/library/core/tests/iter/traits/step.rs b/library/coretests/tests/iter/traits/step.rs index bf935af397c..bf935af397c 100644 --- a/library/core/tests/iter/traits/step.rs +++ b/library/coretests/tests/iter/traits/step.rs diff --git a/library/core/tests/lazy.rs b/library/coretests/tests/lazy.rs index 32d0ac51f03..32d0ac51f03 100644 --- a/library/core/tests/lazy.rs +++ b/library/coretests/tests/lazy.rs diff --git a/library/core/tests/lib.rs b/library/coretests/tests/lib.rs index a8980c5f30a..0607d508a48 100644 --- a/library/core/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -11,6 +11,7 @@ #![feature(async_iter_from_iter)] #![feature(async_iterator)] #![feature(bigint_helper_methods)] +#![feature(bstr)] #![feature(cell_update)] #![feature(clone_to_uninit)] #![feature(const_black_box)] @@ -139,6 +140,7 @@ mod asserting; mod async_iter; mod atomic; mod bool; +mod bstr; mod cell; mod char; mod clone; diff --git a/library/core/tests/macros.rs b/library/coretests/tests/macros.rs index b30a40b7df2..b30a40b7df2 100644 --- a/library/core/tests/macros.rs +++ b/library/coretests/tests/macros.rs diff --git a/library/core/tests/macros_bootstrap.rs b/library/coretests/tests/macros_bootstrap.rs index f10ef862c5d..f10ef862c5d 100644 --- a/library/core/tests/macros_bootstrap.rs +++ b/library/coretests/tests/macros_bootstrap.rs diff --git a/library/core/tests/manually_drop.rs b/library/coretests/tests/manually_drop.rs index bbf444471ad..bbf444471ad 100644 --- a/library/core/tests/manually_drop.rs +++ b/library/coretests/tests/manually_drop.rs diff --git a/library/core/tests/mem.rs b/library/coretests/tests/mem.rs index 1b5c5fc82a6..1b5c5fc82a6 100644 --- a/library/core/tests/mem.rs +++ b/library/coretests/tests/mem.rs diff --git a/library/core/tests/net/ip_addr.rs b/library/coretests/tests/net/ip_addr.rs index 707f9a160e1..f01b43282ec 100644 --- a/library/core/tests/net/ip_addr.rs +++ b/library/coretests/tests/net/ip_addr.rs @@ -332,6 +332,7 @@ fn ip_properties() { check!("ff08::", global | multicast); check!("ff0e::", global | multicast); check!("2001:db8:85a3::8a2e:370:7334", doc); + check!("3fff:fff:ffff:ffff:ffff:ffff:ffff:ffff", doc); check!("2001:2::ac32:23ff:21", benchmarking); check!("102:304:506:708:90a:b0c:d0e:f10", global); } @@ -791,6 +792,15 @@ fn ipv6_properties() { ); check!( + "3fff:fff:ffff:ffff:ffff:ffff:ffff:ffff", + &[ + 0x3f, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff + ], + documentation + ); + + check!( "2001:2::ac32:23ff:21", &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21], benchmarking diff --git a/library/core/tests/net/mod.rs b/library/coretests/tests/net/mod.rs index 8f17bbe5548..8f17bbe5548 100644 --- a/library/core/tests/net/mod.rs +++ b/library/coretests/tests/net/mod.rs diff --git a/library/core/tests/net/parser.rs b/library/coretests/tests/net/parser.rs index e03959ac77c..e03959ac77c 100644 --- a/library/core/tests/net/parser.rs +++ b/library/coretests/tests/net/parser.rs diff --git a/library/core/tests/net/socket_addr.rs b/library/coretests/tests/net/socket_addr.rs index 3d013d37e04..3d013d37e04 100644 --- a/library/core/tests/net/socket_addr.rs +++ b/library/coretests/tests/net/socket_addr.rs diff --git a/library/core/tests/nonzero.rs b/library/coretests/tests/nonzero.rs index 43c279053d8..43c279053d8 100644 --- a/library/core/tests/nonzero.rs +++ b/library/coretests/tests/nonzero.rs diff --git a/library/core/tests/num/bignum.rs b/library/coretests/tests/num/bignum.rs index f213fd5366c..f213fd5366c 100644 --- a/library/core/tests/num/bignum.rs +++ b/library/coretests/tests/num/bignum.rs diff --git a/library/core/tests/num/const_from.rs b/library/coretests/tests/num/const_from.rs index fa58e771879..fa58e771879 100644 --- a/library/core/tests/num/const_from.rs +++ b/library/coretests/tests/num/const_from.rs diff --git a/library/core/tests/num/dec2flt/float.rs b/library/coretests/tests/num/dec2flt/float.rs index 7a9587a18d0..7a9587a18d0 100644 --- a/library/core/tests/num/dec2flt/float.rs +++ b/library/coretests/tests/num/dec2flt/float.rs diff --git a/library/core/tests/num/dec2flt/lemire.rs b/library/coretests/tests/num/dec2flt/lemire.rs index f71bbb7c7a3..f71bbb7c7a3 100644 --- a/library/core/tests/num/dec2flt/lemire.rs +++ b/library/coretests/tests/num/dec2flt/lemire.rs diff --git a/library/core/tests/num/dec2flt/mod.rs b/library/coretests/tests/num/dec2flt/mod.rs index 874e0ec7093..874e0ec7093 100644 --- a/library/core/tests/num/dec2flt/mod.rs +++ b/library/coretests/tests/num/dec2flt/mod.rs diff --git a/library/core/tests/num/dec2flt/parse.rs b/library/coretests/tests/num/dec2flt/parse.rs index 4a5d24ba7d5..4a5d24ba7d5 100644 --- a/library/core/tests/num/dec2flt/parse.rs +++ b/library/coretests/tests/num/dec2flt/parse.rs diff --git a/library/core/tests/num/float_iter_sum_identity.rs b/library/coretests/tests/num/float_iter_sum_identity.rs index 6d3224522a8..6d3224522a8 100644 --- a/library/core/tests/num/float_iter_sum_identity.rs +++ b/library/coretests/tests/num/float_iter_sum_identity.rs diff --git a/library/core/tests/num/flt2dec/estimator.rs b/library/coretests/tests/num/flt2dec/estimator.rs index da203b5f362..da203b5f362 100644 --- a/library/core/tests/num/flt2dec/estimator.rs +++ b/library/coretests/tests/num/flt2dec/estimator.rs diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/coretests/tests/num/flt2dec/mod.rs index 3d825224813..3d825224813 100644 --- a/library/core/tests/num/flt2dec/mod.rs +++ b/library/coretests/tests/num/flt2dec/mod.rs diff --git a/library/core/tests/num/flt2dec/random.rs b/library/coretests/tests/num/flt2dec/random.rs index 99fc23af7ea..90042ae03bf 100644 --- a/library/core/tests/num/flt2dec/random.rs +++ b/library/coretests/tests/num/flt2dec/random.rs @@ -84,9 +84,6 @@ where F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>, G: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16), { - if cfg!(target_os = "emscripten") { - return; // using rng pulls in i128 support, which doesn't work - } let mut rng = crate::test_rng(); let f32_range = Uniform::new(0x0000_0001u32, 0x7f80_0000); iterate("f32_random_equivalence_test", k, n, f, g, |_| { @@ -100,9 +97,6 @@ where F: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> Option<(&'a [u8], i16)>, G: for<'a> FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16), { - if cfg!(target_os = "emscripten") { - return; // using rng pulls in i128 support, which doesn't work - } let mut rng = crate::test_rng(); let f64_range = Uniform::new(0x0000_0000_0000_0001u64, 0x7ff0_0000_0000_0000); iterate("f64_random_equivalence_test", k, n, f, g, |_| { diff --git a/library/core/tests/num/flt2dec/strategy/dragon.rs b/library/coretests/tests/num/flt2dec/strategy/dragon.rs index be25fee3f6c..be25fee3f6c 100644 --- a/library/core/tests/num/flt2dec/strategy/dragon.rs +++ b/library/coretests/tests/num/flt2dec/strategy/dragon.rs diff --git a/library/core/tests/num/flt2dec/strategy/grisu.rs b/library/coretests/tests/num/flt2dec/strategy/grisu.rs index 9b2f0453de7..9b2f0453de7 100644 --- a/library/core/tests/num/flt2dec/strategy/grisu.rs +++ b/library/coretests/tests/num/flt2dec/strategy/grisu.rs diff --git a/library/core/tests/num/i128.rs b/library/coretests/tests/num/i128.rs index 745fee05164..745fee05164 100644 --- a/library/core/tests/num/i128.rs +++ b/library/coretests/tests/num/i128.rs diff --git a/library/core/tests/num/i16.rs b/library/coretests/tests/num/i16.rs index 6acb8371b87..6acb8371b87 100644 --- a/library/core/tests/num/i16.rs +++ b/library/coretests/tests/num/i16.rs diff --git a/library/core/tests/num/i32.rs b/library/coretests/tests/num/i32.rs index 38d5071f71d..38d5071f71d 100644 --- a/library/core/tests/num/i32.rs +++ b/library/coretests/tests/num/i32.rs diff --git a/library/core/tests/num/i64.rs b/library/coretests/tests/num/i64.rs index f8dd5f9be7f..f8dd5f9be7f 100644 --- a/library/core/tests/num/i64.rs +++ b/library/coretests/tests/num/i64.rs diff --git a/library/core/tests/num/i8.rs b/library/coretests/tests/num/i8.rs index a10906618c9..a10906618c9 100644 --- a/library/core/tests/num/i8.rs +++ b/library/coretests/tests/num/i8.rs diff --git a/library/core/tests/num/ieee754.rs b/library/coretests/tests/num/ieee754.rs index b0f6a7545aa..b0f6a7545aa 100644 --- a/library/core/tests/num/ieee754.rs +++ b/library/coretests/tests/num/ieee754.rs diff --git a/library/core/tests/num/int_log.rs b/library/coretests/tests/num/int_log.rs index 60902752dab..60902752dab 100644 --- a/library/core/tests/num/int_log.rs +++ b/library/coretests/tests/num/int_log.rs diff --git a/library/core/tests/num/int_macros.rs b/library/coretests/tests/num/int_macros.rs index f13b836378b..f13b836378b 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/coretests/tests/num/int_macros.rs diff --git a/library/core/tests/num/int_sqrt.rs b/library/coretests/tests/num/int_sqrt.rs index d68db0787d2..d68db0787d2 100644 --- a/library/core/tests/num/int_sqrt.rs +++ b/library/coretests/tests/num/int_sqrt.rs diff --git a/library/core/tests/num/midpoint.rs b/library/coretests/tests/num/midpoint.rs index 71e98006784..71e98006784 100644 --- a/library/core/tests/num/midpoint.rs +++ b/library/coretests/tests/num/midpoint.rs diff --git a/library/core/tests/num/mod.rs b/library/coretests/tests/num/mod.rs index 0add9a01e68..0add9a01e68 100644 --- a/library/core/tests/num/mod.rs +++ b/library/coretests/tests/num/mod.rs diff --git a/library/core/tests/num/nan.rs b/library/coretests/tests/num/nan.rs index ef81988c961..ef81988c961 100644 --- a/library/core/tests/num/nan.rs +++ b/library/coretests/tests/num/nan.rs diff --git a/library/core/tests/num/ops.rs b/library/coretests/tests/num/ops.rs index ae8b938250e..7b2aad48978 100644 --- a/library/core/tests/num/ops.rs +++ b/library/coretests/tests/num/ops.rs @@ -51,9 +51,7 @@ macro_rules! test_op { }; } -test_op!(test_neg_defined, Neg::neg(0), 0, i8, i16, i32, i64, f32, f64); -#[cfg(not(target_os = "emscripten"))] -test_op!(test_neg_defined_128, Neg::neg(0), 0, i128); +test_op!(test_neg_defined, Neg::neg(0), 0, i8, i16, i32, i64, i128, f32, f64); test_op!(test_not_defined_bool, Not::not(true), false, bool); @@ -69,17 +67,17 @@ macro_rules! test_arith_op { i16, i32, i64, + i128, isize, u8, u16, u32, u64, + u128, usize, f32, f64 ); - #[cfg(not(target_os = "emscripten"))] - impls_defined!($op, $method($lhs, $rhs), 0, i128, u128); } }; ($fn_name:ident, $op:ident::$method:ident(&mut $lhs:literal, $rhs:literal)) => { @@ -93,17 +91,17 @@ macro_rules! test_arith_op { i16, i32, i64, + i128, isize, u8, u16, u32, u64, + u128, usize, f32, f64 ); - #[cfg(not(target_os = "emscripten"))] - impls_defined!($op, $method(&mut $lhs, $rhs), 0, i128, u128); } }; } @@ -131,15 +129,15 @@ macro_rules! test_bitop { i16, i32, i64, + i128, isize, u8, u16, u32, u64, + u128, usize ); - #[cfg(not(target_os = "emscripten"))] - impls_defined!($op, $method(0, 0), 0, i128, u128); impls_defined!($op, $method(false, false), false, bool); } }; @@ -156,15 +154,15 @@ macro_rules! test_bitop_assign { i16, i32, i64, + i128, isize, u8, u16, u32, u64, + u128, usize ); - #[cfg(not(target_os = "emscripten"))] - impls_defined!($op, $method(&mut 0, 0), 0, i128, u128); impls_defined!($op, $method(&mut false, false), false, bool); } }; @@ -182,9 +180,11 @@ macro_rules! test_shift_inner { $(impl_defined!($op, $method(0,0), 0, $lt, $rt);)+ }; ($op:ident::$method:ident, $lt:ty) => { - test_shift_inner!($op::$method, $lt, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); - #[cfg(not(target_os = "emscripten"))] - test_shift_inner!($op::$method, $lt, i128, u128); + test_shift_inner!( + $op::$method, $lt, + i8, i16, i32, i64, i128, isize, + u8, u16, u32, u64, u128, usize + ); }; } @@ -195,9 +195,11 @@ macro_rules! test_shift { ($test_name:ident, $op:ident::$method:ident) => { #[test] fn $test_name() { - test_shift!($op::$method, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); - #[cfg(not(target_os = "emscripten"))] - test_shift!($op::$method, i128, u128); + test_shift!( + $op::$method, + i8, i16, i32, i64, i128, isize, + u8, u16, u32, u64, u128, usize + ); } }; } @@ -207,9 +209,11 @@ macro_rules! test_shift_assign_inner { $(impl_defined!($op, $method(&mut 0,0), 0, $lt, $rt);)+ }; ($op:ident::$method:ident, $lt:ty) => { - test_shift_assign_inner!($op::$method, $lt, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); - #[cfg(not(target_os = "emscripten"))] - test_shift_assign_inner!($op::$method, $lt, i128, u128); + test_shift_assign_inner!( + $op::$method, $lt, + i8, i16, i32, i64, i128, isize, + u8, u16, u32, u64, u128, usize + ); }; } @@ -220,9 +224,11 @@ macro_rules! test_shift_assign { ($test_name:ident, $op:ident::$method:ident) => { #[test] fn $test_name() { - test_shift_assign!($op::$method, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize); - #[cfg(not(target_os = "emscripten"))] - test_shift_assign!($op::$method, i128, u128); + test_shift_assign!( + $op::$method, + i8, i16, i32, i64, i128, isize, + u8, u16, u32, u64, u128, usize + ); } }; } diff --git a/library/core/tests/num/u128.rs b/library/coretests/tests/num/u128.rs index a7b0f9effef..a7b0f9effef 100644 --- a/library/core/tests/num/u128.rs +++ b/library/coretests/tests/num/u128.rs diff --git a/library/core/tests/num/u16.rs b/library/coretests/tests/num/u16.rs index 010596a34a5..010596a34a5 100644 --- a/library/core/tests/num/u16.rs +++ b/library/coretests/tests/num/u16.rs diff --git a/library/core/tests/num/u32.rs b/library/coretests/tests/num/u32.rs index 687d3bbaa90..687d3bbaa90 100644 --- a/library/core/tests/num/u32.rs +++ b/library/coretests/tests/num/u32.rs diff --git a/library/core/tests/num/u64.rs b/library/coretests/tests/num/u64.rs index ee55071e949..ee55071e949 100644 --- a/library/core/tests/num/u64.rs +++ b/library/coretests/tests/num/u64.rs diff --git a/library/core/tests/num/u8.rs b/library/coretests/tests/num/u8.rs index 12b038ce0f7..12b038ce0f7 100644 --- a/library/core/tests/num/u8.rs +++ b/library/coretests/tests/num/u8.rs diff --git a/library/core/tests/num/uint_macros.rs b/library/coretests/tests/num/uint_macros.rs index 99a2d4cd462..99a2d4cd462 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/coretests/tests/num/uint_macros.rs diff --git a/library/core/tests/num/wrapping.rs b/library/coretests/tests/num/wrapping.rs index c5a71988395..0b9fca8455b 100644 --- a/library/core/tests/num/wrapping.rs +++ b/library/coretests/tests/num/wrapping.rs @@ -64,14 +64,12 @@ wrapping_test!(test_wrapping_i8, i8, i8::MIN, i8::MAX); wrapping_test!(test_wrapping_i16, i16, i16::MIN, i16::MAX); wrapping_test!(test_wrapping_i32, i32, i32::MIN, i32::MAX); wrapping_test!(test_wrapping_i64, i64, i64::MIN, i64::MAX); -#[cfg(not(target_os = "emscripten"))] wrapping_test!(test_wrapping_i128, i128, i128::MIN, i128::MAX); wrapping_test!(test_wrapping_isize, isize, isize::MIN, isize::MAX); wrapping_test!(test_wrapping_u8, u8, u8::MIN, u8::MAX); wrapping_test!(test_wrapping_u16, u16, u16::MIN, u16::MAX); wrapping_test!(test_wrapping_u32, u32, u32::MIN, u32::MAX); wrapping_test!(test_wrapping_u64, u64, u64::MIN, u64::MAX); -#[cfg(not(target_os = "emscripten"))] wrapping_test!(test_wrapping_u128, u128, u128::MIN, u128::MAX); wrapping_test!(test_wrapping_usize, usize, usize::MIN, usize::MAX); diff --git a/library/core/tests/ops.rs b/library/coretests/tests/ops.rs index 501e0f33fe4..501e0f33fe4 100644 --- a/library/core/tests/ops.rs +++ b/library/coretests/tests/ops.rs diff --git a/library/core/tests/ops/control_flow.rs b/library/coretests/tests/ops/control_flow.rs index eacfd63a6c4..eacfd63a6c4 100644 --- a/library/core/tests/ops/control_flow.rs +++ b/library/coretests/tests/ops/control_flow.rs diff --git a/library/core/tests/ops/from_residual.rs b/library/coretests/tests/ops/from_residual.rs index d5c86ccbcd3..d5c86ccbcd3 100644 --- a/library/core/tests/ops/from_residual.rs +++ b/library/coretests/tests/ops/from_residual.rs diff --git a/library/core/tests/option.rs b/library/coretests/tests/option.rs index 336a79a02ce..336a79a02ce 100644 --- a/library/core/tests/option.rs +++ b/library/coretests/tests/option.rs diff --git a/library/core/tests/panic.rs b/library/coretests/tests/panic.rs index 24b6c56b356..24b6c56b356 100644 --- a/library/core/tests/panic.rs +++ b/library/coretests/tests/panic.rs diff --git a/library/core/tests/panic/location.rs b/library/coretests/tests/panic/location.rs index d20241d8380..d20241d8380 100644 --- a/library/core/tests/panic/location.rs +++ b/library/coretests/tests/panic/location.rs diff --git a/library/core/tests/pattern.rs b/library/coretests/tests/pattern.rs index d4bec996d89..d4bec996d89 100644 --- a/library/core/tests/pattern.rs +++ b/library/coretests/tests/pattern.rs diff --git a/library/core/tests/pin.rs b/library/coretests/tests/pin.rs index 026d2ca8de2..026d2ca8de2 100644 --- a/library/core/tests/pin.rs +++ b/library/coretests/tests/pin.rs diff --git a/library/core/tests/pin_macro.rs b/library/coretests/tests/pin_macro.rs index 43542397a61..43542397a61 100644 --- a/library/core/tests/pin_macro.rs +++ b/library/coretests/tests/pin_macro.rs diff --git a/library/core/tests/ptr.rs b/library/coretests/tests/ptr.rs index 7cefb615d03..7cefb615d03 100644 --- a/library/core/tests/ptr.rs +++ b/library/coretests/tests/ptr.rs diff --git a/library/core/tests/result.rs b/library/coretests/tests/result.rs index 90ec844bc57..90ec844bc57 100644 --- a/library/core/tests/result.rs +++ b/library/coretests/tests/result.rs diff --git a/library/core/tests/simd.rs b/library/coretests/tests/simd.rs index b8b5f26ca3f..b8b5f26ca3f 100644 --- a/library/core/tests/simd.rs +++ b/library/coretests/tests/simd.rs diff --git a/library/core/tests/slice.rs b/library/coretests/tests/slice.rs index 510dd4967c9..510dd4967c9 100644 --- a/library/core/tests/slice.rs +++ b/library/coretests/tests/slice.rs diff --git a/library/core/tests/str.rs b/library/coretests/tests/str.rs index f5066343af2..f5066343af2 100644 --- a/library/core/tests/str.rs +++ b/library/coretests/tests/str.rs diff --git a/library/core/tests/str_lossy.rs b/library/coretests/tests/str_lossy.rs index 6e70ea3e285..6e70ea3e285 100644 --- a/library/core/tests/str_lossy.rs +++ b/library/coretests/tests/str_lossy.rs diff --git a/library/core/tests/task.rs b/library/coretests/tests/task.rs index 163b34c9648..163b34c9648 100644 --- a/library/core/tests/task.rs +++ b/library/coretests/tests/task.rs diff --git a/library/core/tests/time.rs b/library/coretests/tests/time.rs index fe7bb11c675..fe7bb11c675 100644 --- a/library/core/tests/time.rs +++ b/library/coretests/tests/time.rs diff --git a/library/core/tests/tuple.rs b/library/coretests/tests/tuple.rs index ea1e281425c..ea1e281425c 100644 --- a/library/core/tests/tuple.rs +++ b/library/coretests/tests/tuple.rs diff --git a/library/core/tests/unicode.rs b/library/coretests/tests/unicode.rs index bbace0ef66c..bbace0ef66c 100644 --- a/library/core/tests/unicode.rs +++ b/library/coretests/tests/unicode.rs diff --git a/library/core/tests/waker.rs b/library/coretests/tests/waker.rs index 4889b8959ec..4889b8959ec 100644 --- a/library/core/tests/waker.rs +++ b/library/coretests/tests/waker.rs diff --git a/library/panic_unwind/src/dummy.rs b/library/panic_unwind/src/dummy.rs index a4bcd216c60..a0d68766918 100644 --- a/library/panic_unwind/src/dummy.rs +++ b/library/panic_unwind/src/dummy.rs @@ -6,10 +6,10 @@ use alloc::boxed::Box; use core::any::Any; use core::intrinsics; -pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> { +pub(crate) unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> { intrinsics::abort() } -pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 { +pub(crate) unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 { intrinsics::abort() } diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index b986fc1c2a8..9127449edb1 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -64,7 +64,7 @@ struct Exception { data: Option<Box<dyn Any + Send>>, } -pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> { +pub(crate) unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> { // intrinsics::try actually gives us a pointer to this structure. #[repr(C)] struct CatchData { @@ -93,7 +93,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> { out } -pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { +pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { let exception = __cxa_allocate_exception(mem::size_of::<Exception>()) as *mut Exception; if exception.is_null() { return uw::_URC_FATAL_PHASE1_ERROR as u32; diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index b2389078afd..e478f6c5fc8 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -58,7 +58,7 @@ struct Exception { cause: Box<dyn Any + Send>, } -pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { +pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { let exception = Box::new(Exception { _uwe: uw::_Unwind_Exception { exception_class: RUST_EXCEPTION_CLASS, @@ -82,7 +82,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { } } -pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> { +pub(crate) unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> { let exception = ptr as *mut uw::_Unwind_Exception; if (*exception).exception_class != RUST_EXCEPTION_CLASS { uw::_Unwind_DeleteException(exception); diff --git a/library/panic_unwind/src/hermit.rs b/library/panic_unwind/src/hermit.rs index 69b9edb77c5..8ac827dd9cc 100644 --- a/library/panic_unwind/src/hermit.rs +++ b/library/panic_unwind/src/hermit.rs @@ -5,14 +5,14 @@ use alloc::boxed::Box; use core::any::Any; -pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> { +pub(crate) unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> { extern "C" { pub fn __rust_abort() -> !; } __rust_abort(); } -pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 { +pub(crate) unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 { extern "C" { pub fn __rust_abort() -> !; } diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index dc78be76cb4..d6828164195 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -26,6 +26,7 @@ #![cfg_attr(miri, allow(dead_code))] #![allow(internal_features)] #![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))] +#![warn(unreachable_pub)] use alloc::boxed::Box; use core::any::Any; diff --git a/library/panic_unwind/src/miri.rs b/library/panic_unwind/src/miri.rs index 695adadd59b..a86f0e91eef 100644 --- a/library/panic_unwind/src/miri.rs +++ b/library/panic_unwind/src/miri.rs @@ -12,14 +12,14 @@ extern "Rust" { fn miri_start_unwind(payload: *mut u8) -> !; } -pub unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 { +pub(crate) unsafe fn panic(payload: Box<dyn Any + Send>) -> u32 { // The payload we pass to `miri_start_unwind` will be exactly the argument we get // in `cleanup` below. So we just box it up once, to get something pointer-sized. let payload_box: Payload = Box::new(payload); miri_start_unwind(Box::into_raw(payload_box) as *mut u8) } -pub unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> { +pub(crate) unsafe fn cleanup(payload_box: *mut u8) -> Box<dyn Any + Send> { // Recover the underlying `Box`. let payload_box: Payload = Box::from_raw(payload_box as *mut _); *payload_box diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 5afa0a19756..21bfe74e1a2 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -111,18 +111,18 @@ struct Exception { mod imp { #[repr(transparent)] #[derive(Copy, Clone)] - pub struct ptr_t(*mut u8); + pub(super) struct ptr_t(*mut u8); impl ptr_t { - pub const fn null() -> Self { + pub(super) const fn null() -> Self { Self(core::ptr::null_mut()) } - pub const fn new(ptr: *mut u8) -> Self { + pub(super) const fn new(ptr: *mut u8) -> Self { Self(ptr) } - pub const fn raw(self) -> *mut u8 { + pub(super) const fn raw(self) -> *mut u8 { self.0 } } @@ -133,18 +133,18 @@ mod imp { // On 64-bit systems, SEH represents pointers as 32-bit offsets from `__ImageBase`. #[repr(transparent)] #[derive(Copy, Clone)] - pub struct ptr_t(u32); + pub(super) struct ptr_t(u32); extern "C" { - pub static __ImageBase: u8; + static __ImageBase: u8; } impl ptr_t { - pub const fn null() -> Self { + pub(super) const fn null() -> Self { Self(0) } - pub fn new(ptr: *mut u8) -> Self { + pub(super) fn new(ptr: *mut u8) -> Self { // We need to expose the provenance of the pointer because it is not carried by // the `u32`, while the FFI needs to have this provenance to excess our statics. // @@ -159,7 +159,7 @@ mod imp { Self(offset as u32) } - pub const fn raw(self) -> u32 { + pub(super) const fn raw(self) -> u32 { self.0 } } @@ -168,7 +168,7 @@ mod imp { use imp::ptr_t; #[repr(C)] -pub struct _ThrowInfo { +struct _ThrowInfo { pub attributes: c_uint, pub pmfnUnwind: ptr_t, pub pForwardCompat: ptr_t, @@ -176,13 +176,13 @@ pub struct _ThrowInfo { } #[repr(C)] -pub struct _CatchableTypeArray { +struct _CatchableTypeArray { pub nCatchableTypes: c_int, pub arrayOfCatchableTypes: [ptr_t; 1], } #[repr(C)] -pub struct _CatchableType { +struct _CatchableType { pub properties: c_uint, pub pType: ptr_t, pub thisDisplacement: _PMD, @@ -191,14 +191,14 @@ pub struct _CatchableType { } #[repr(C)] -pub struct _PMD { +struct _PMD { pub mdisp: c_int, pub pdisp: c_int, pub vdisp: c_int, } #[repr(C)] -pub struct _TypeDescriptor { +struct _TypeDescriptor { pub pVFTable: *const u8, pub spare: *mut u8, pub name: [u8; 11], @@ -288,7 +288,7 @@ cfg_if::cfg_if! { } } -pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { +pub(crate) unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { use core::intrinsics::atomic_store_seqcst; // _CxxThrowException executes entirely on this stack frame, so there's no @@ -350,7 +350,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { _CxxThrowException(throw_ptr, (&raw mut THROW_INFO) as *mut _); } -pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> { +pub(crate) unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> { // A null payload here means that we got here from the catch (...) of // __rust_try. This happens when a non-Rust foreign exception is caught. if payload.is_null() { diff --git a/library/proc_macro/src/bridge/closure.rs b/library/proc_macro/src/bridge/closure.rs index d371ae3cea0..524fdf53d6b 100644 --- a/library/proc_macro/src/bridge/closure.rs +++ b/library/proc_macro/src/bridge/closure.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; #[repr(C)] -pub struct Closure<'a, A, R> { +pub(super) struct Closure<'a, A, R> { call: unsafe extern "C" fn(*mut Env, A) -> R, env: *mut Env, // Prevent Send and Sync impls. `!Send`/`!Sync` is the usual way of doing @@ -26,7 +26,7 @@ impl<'a, A, R, F: FnMut(A) -> R> From<&'a mut F> for Closure<'a, A, R> { } impl<'a, A, R> Closure<'a, A, R> { - pub fn call(&mut self, arg: A) -> R { + pub(super) fn call(&mut self, arg: A) -> R { unsafe { (self.call)(self.env, arg) } } } diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs index 3345e099a37..5f6b3d1b929 100644 --- a/library/proc_macro/src/bridge/fxhash.rs +++ b/library/proc_macro/src/bridge/fxhash.rs @@ -9,7 +9,7 @@ use std::hash::{BuildHasherDefault, Hasher}; use std::ops::BitXor; /// Type alias for a hashmap using the `fx` hash algorithm. -pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>; +pub(super) type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>; /// A speedy hash algorithm for use within rustc. The hashmap in alloc by /// default uses SipHash which isn't quite as speedy as we want. In the compiler @@ -23,7 +23,7 @@ pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>; /// similar or slightly worse than FNV, but the speed of the hash function /// itself is much higher because it works on up to 8 bytes at a time. #[derive(Default)] -pub struct FxHasher { +pub(super) struct FxHasher { hash: usize, } diff --git a/library/proc_macro/src/bridge/rpc.rs b/library/proc_macro/src/bridge/rpc.rs index 202a8e04543..85fd7d13858 100644 --- a/library/proc_macro/src/bridge/rpc.rs +++ b/library/proc_macro/src/bridge/rpc.rs @@ -67,7 +67,7 @@ macro_rules! rpc_encode_decode { mod tag { #[repr(u8)] enum Tag { $($variant),* } - $(pub const $variant: u8 = Tag::$variant as u8;)* + $(pub(crate) const $variant: u8 = Tag::$variant as u8;)* } match self { @@ -89,7 +89,7 @@ macro_rules! rpc_encode_decode { mod tag { #[repr(u8)] enum Tag { $($variant),* } - $(pub const $variant: u8 = Tag::$variant as u8;)* + $(pub(crate) const $variant: u8 = Tag::$variant as u8;)* } match u8::decode(r, s) { diff --git a/library/proc_macro/src/bridge/selfless_reify.rs b/library/proc_macro/src/bridge/selfless_reify.rs index 907ad256e4b..312a79152e2 100644 --- a/library/proc_macro/src/bridge/selfless_reify.rs +++ b/library/proc_macro/src/bridge/selfless_reify.rs @@ -44,7 +44,7 @@ macro_rules! define_reify_functions { fn $name:ident $(<$($param:ident),*>)? for $(extern $abi:tt)? fn($($arg:ident: $arg_ty:ty),*) -> $ret_ty:ty; )+) => { - $(pub const fn $name< + $(pub(super) const fn $name< $($($param,)*)? F: Fn($($arg_ty),*) -> $ret_ty + Copy >(f: F) -> $(extern $abi)? fn($($arg_ty),*) -> $ret_ty { diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index b19c9cee75a..6611ce30a1b 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -32,6 +32,7 @@ #![allow(internal_features)] #![deny(ffi_unwind_calls)] #![warn(rustdoc::unescaped_backticks)] +#![warn(unreachable_pub)] #[unstable(feature = "proc_macro_internals", issue = "27812")] #[doc(hidden)] diff --git a/library/rtstartup/rsbegin.rs b/library/rtstartup/rsbegin.rs index 9a3d95bd8dd..d3ff5c14aa4 100644 --- a/library/rtstartup/rsbegin.rs +++ b/library/rtstartup/rsbegin.rs @@ -19,6 +19,7 @@ #![no_core] #![allow(non_camel_case_types)] #![allow(internal_features)] +#![warn(unreachable_pub)] #[lang = "sized"] trait Sized {} diff --git a/library/rtstartup/rsend.rs b/library/rtstartup/rsend.rs index 2514eb00344..81acfbed447 100644 --- a/library/rtstartup/rsend.rs +++ b/library/rtstartup/rsend.rs @@ -6,6 +6,7 @@ #![crate_type = "rlib"] #![no_core] #![allow(internal_features)] +#![warn(unreachable_pub)] #[lang = "sized"] trait Sized {} diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index da58d7c13bd..9eab75b0696 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -139,7 +139,8 @@ test = true level = "warn" check-cfg = [ 'cfg(bootstrap)', - 'cfg(target_arch, values("xtensa"))', + 'cfg(target_arch, values("xtensa", "aarch64-unknown-nto-qnx710_iosock", "x86_64-pc-nto-qnx710_iosock", "x86_64-pc-nto-qnx800","aarch64-unknown-nto-qnx800"))', + 'cfg(target_env, values("nto71_iosock", "nto80"))', # std use #[path] imports to portable-simd `std_float` crate # and to the `backtrace` crate which messes-up with Cargo list # of declared features, we therefor expect any feature cfg diff --git a/library/std/src/bstr.rs b/library/std/src/bstr.rs new file mode 100644 index 00000000000..dd491771628 --- /dev/null +++ b/library/std/src/bstr.rs @@ -0,0 +1,4 @@ +//! The `ByteStr` and `ByteString` types and trait implementations. + +#[unstable(feature = "bstr", issue = "134915")] +pub use alloc::bstr::{ByteStr, ByteString}; diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 11a29cdae62..bbd506127fb 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -336,7 +336,10 @@ impl Error for VarError { /// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188) /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) /// +/// To pass an environment variable to a child process, you can instead use [`Command::env`]. +/// /// [`std::net::ToSocketAddrs`]: crate::net::ToSocketAddrs +/// [`Command::env`]: crate::process::Command::env /// /// # Panics /// @@ -396,7 +399,12 @@ pub unsafe fn set_var<K: AsRef<OsStr>, V: AsRef<OsStr>>(key: K, value: V) { /// - [Austin Group Bugzilla](https://austingroupbugs.net/view.php?id=188) /// - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2) /// +/// To prevent a child process from inheriting an environment variable, you can +/// instead use [`Command::env_remove`] or [`Command::env_clear`]. +/// /// [`std::net::ToSocketAddrs`]: crate::net::ToSocketAddrs +/// [`Command::env_remove`]: crate::process::Command::env_remove +/// [`Command::env_clear`]: crate::process::Command::env_clear /// /// # Panics /// diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs index 3fac2efe0d7..f5ba2c7b594 100644 --- a/library/std/src/f64/tests.rs +++ b/library/std/src/f64/tests.rs @@ -112,7 +112,6 @@ fn test_neg_zero() { assert_eq!(Fp::Zero, neg_zero.classify()); } -#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_one() { let one: f64 = 1.0f64; @@ -165,7 +164,6 @@ fn test_is_finite() { assert!((-109.2f64).is_finite()); } -#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_is_normal() { let nan: f64 = f64::NAN; @@ -183,7 +181,6 @@ fn test_is_normal() { assert!(!1e-308f64.is_normal()); } -#[cfg_attr(all(target_arch = "wasm32", target_os = "emscripten"), ignore)] // issue 42630 #[test] fn test_classify() { let nan: f64 = f64::NAN; diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 7fb57d41043..c4c8dbccd7a 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -203,8 +203,8 @@ impl OsString { self } - /// Converts the `OsString` into a byte slice. To convert the byte slice back into an - /// `OsString`, use the [`OsStr::from_encoded_bytes_unchecked`] function. + /// Converts the `OsString` into a byte vector. To convert the byte vector back into an + /// `OsString`, use the [`OsString::from_encoded_bytes_unchecked`] function. /// /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8. /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 9b752ed1443..1f8aac48a9a 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2529,6 +2529,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> { /// limited to just these cases: /// /// * The `original` path is not a file or doesn't exist. +/// * The 'link' path already exists. /// /// # Examples /// diff --git a/library/std/src/io/copy/tests.rs b/library/std/src/io/copy/tests.rs index 2e0eb6cdce6..25b1ece2745 100644 --- a/library/std/src/io/copy/tests.rs +++ b/library/std/src/io/copy/tests.rs @@ -126,6 +126,7 @@ mod io_benches { use crate::io::prelude::*; #[bench] + #[cfg_attr(target_os = "emscripten", ignore)] // no /dev fn bench_copy_buf_reader(b: &mut Bencher) { let mut file_in = File::open("/dev/zero").expect("opening /dev/zero failed"); // use dyn to avoid specializations unrelated to readbuf diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 231c8712ebd..cfd03b8e3d6 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -310,6 +310,8 @@ pub use self::error::RawOsError; pub use self::error::SimpleMessage; #[unstable(feature = "io_const_error", issue = "133448")] pub use self::error::const_error; +#[unstable(feature = "anonymous_pipe", issue = "127154")] +pub use self::pipe::{PipeReader, PipeWriter, pipe}; #[stable(feature = "is_terminal", since = "1.70.0")] pub use self::stdio::IsTerminal; pub(crate) use self::stdio::attempt_print_to_stderr; @@ -330,7 +332,6 @@ pub use self::{ }; use crate::mem::take; use crate::ops::{Deref, DerefMut}; -use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; use crate::{cmp, fmt, slice, str, sys}; mod buffered; @@ -338,6 +339,7 @@ pub(crate) mod copy; mod cursor; mod error; mod impls; +mod pipe; pub mod prelude; mod stdio; mod util; @@ -3251,251 +3253,3 @@ impl<B: BufRead> Iterator for Lines<B> { } } } - -/// Create anonymous pipe that is close-on-exec and blocking. -/// -/// # Behavior -/// -/// A pipe is a synchronous, unidirectional data channel between two or more processes, like an -/// interprocess [`mpsc`](crate::sync::mpsc) provided by the OS. In particular: -/// -/// * A read on a [`PipeReader`] blocks until the pipe is non-empty. -/// * A write on a [`PipeWriter`] blocks when the pipe is full. -/// * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`] -/// returns EOF. -/// * [`PipeReader`] can be shared, but only one process will consume the data in the pipe. -/// -/// # Capacity -/// -/// Pipe capacity is platform dependent. To quote the Linux [man page]: -/// -/// > Different implementations have different limits for the pipe capacity. Applications should -/// > not rely on a particular capacity: an application should be designed so that a reading process -/// > consumes data as soon as it is available, so that a writing process does not remain blocked. -/// -/// # Examples -/// -/// ```no_run -/// #![feature(anonymous_pipe)] -/// # #[cfg(miri)] fn main() {} -/// # #[cfg(not(miri))] -/// # fn main() -> std::io::Result<()> { -/// # use std::process::Command; -/// # use std::io::{Read, Write}; -/// let (ping_rx, mut ping_tx) = std::io::pipe()?; -/// let (mut pong_rx, pong_tx) = std::io::pipe()?; -/// -/// // Spawn a process that echoes its input. -/// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?; -/// -/// ping_tx.write_all(b"hello")?; -/// // Close to unblock echo_server's reader. -/// drop(ping_tx); -/// -/// let mut buf = String::new(); -/// // Block until echo_server's writer is closed. -/// pong_rx.read_to_string(&mut buf)?; -/// assert_eq!(&buf, "hello"); -/// -/// echo_server.wait()?; -/// # Ok(()) -/// # } -/// ``` -/// [pipe]: https://man7.org/linux/man-pages/man2/pipe.2.html -/// [CreatePipe]: https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-createpipe -/// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html -#[unstable(feature = "anonymous_pipe", issue = "127154")] -#[inline] -pub fn pipe() -> Result<(PipeReader, PipeWriter)> { - pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer))) -} - -/// Read end of the anonymous pipe. -#[unstable(feature = "anonymous_pipe", issue = "127154")] -#[derive(Debug)] -pub struct PipeReader(pub(crate) AnonPipe); - -/// Write end of the anonymous pipe. -#[unstable(feature = "anonymous_pipe", issue = "127154")] -#[derive(Debug)] -pub struct PipeWriter(pub(crate) AnonPipe); - -impl PipeReader { - /// Create a new [`PipeReader`] instance that shares the same underlying file description. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(anonymous_pipe)] - /// # #[cfg(miri)] fn main() {} - /// # #[cfg(not(miri))] - /// # fn main() -> std::io::Result<()> { - /// # use std::fs; - /// # use std::io::Write; - /// # use std::process::Command; - /// const NUM_SLOT: u8 = 2; - /// const NUM_PROC: u8 = 5; - /// const OUTPUT: &str = "work.txt"; - /// - /// let mut jobs = vec![]; - /// let (reader, mut writer) = std::io::pipe()?; - /// - /// // Write NUM_SLOT characters the pipe. - /// writer.write_all(&[b'|'; NUM_SLOT as usize])?; - /// - /// // Spawn several processes that read a character from the pipe, do some work, then - /// // write back to the pipe. When the pipe is empty, the processes block, so only - /// // NUM_SLOT processes can be working at any given time. - /// for _ in 0..NUM_PROC { - /// jobs.push( - /// Command::new("bash") - /// .args(["-c", - /// &format!( - /// "read -n 1\n\ - /// echo -n 'x' >> '{OUTPUT}'\n\ - /// echo -n '|'", - /// ), - /// ]) - /// .stdin(reader.try_clone()?) - /// .stdout(writer.try_clone()?) - /// .spawn()?, - /// ); - /// } - /// - /// // Wait for all jobs to finish. - /// for mut job in jobs { - /// job.wait()?; - /// } - /// - /// // Check our work and clean up. - /// let xs = fs::read_to_string(OUTPUT)?; - /// fs::remove_file(OUTPUT)?; - /// assert_eq!(xs, "x".repeat(NUM_PROC.into())); - /// # Ok(()) - /// # } - /// ``` - #[unstable(feature = "anonymous_pipe", issue = "127154")] - pub fn try_clone(&self) -> Result<Self> { - self.0.try_clone().map(Self) - } -} - -impl PipeWriter { - /// Create a new [`PipeWriter`] instance that shares the same underlying file description. - /// - /// # Examples - /// - /// ```no_run - /// #![feature(anonymous_pipe)] - /// # #[cfg(miri)] fn main() {} - /// # #[cfg(not(miri))] - /// # fn main() -> std::io::Result<()> { - /// # use std::process::Command; - /// # use std::io::Read; - /// let (mut reader, writer) = std::io::pipe()?; - /// - /// // Spawn a process that writes to stdout and stderr. - /// let mut peer = Command::new("bash") - /// .args([ - /// "-c", - /// "echo -n foo\n\ - /// echo -n bar >&2" - /// ]) - /// .stdout(writer.try_clone()?) - /// .stderr(writer) - /// .spawn()?; - /// - /// // Read and check the result. - /// let mut msg = String::new(); - /// reader.read_to_string(&mut msg)?; - /// assert_eq!(&msg, "foobar"); - /// - /// peer.wait()?; - /// # Ok(()) - /// # } - /// ``` - #[unstable(feature = "anonymous_pipe", issue = "127154")] - pub fn try_clone(&self) -> Result<Self> { - self.0.try_clone().map(Self) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl Read for &PipeReader { - fn read(&mut self, buf: &mut [u8]) -> Result<usize> { - self.0.read(buf) - } - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> { - self.0.read_vectored(bufs) - } - #[inline] - fn is_read_vectored(&self) -> bool { - self.0.is_read_vectored() - } - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { - self.0.read_to_end(buf) - } - fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { - self.0.read_buf(buf) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl Read for PipeReader { - fn read(&mut self, buf: &mut [u8]) -> Result<usize> { - self.0.read(buf) - } - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> { - self.0.read_vectored(bufs) - } - #[inline] - fn is_read_vectored(&self) -> bool { - self.0.is_read_vectored() - } - fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> { - self.0.read_to_end(buf) - } - fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> { - self.0.read_buf(buf) - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl Write for &PipeWriter { - fn write(&mut self, buf: &[u8]) -> Result<usize> { - self.0.write(buf) - } - #[inline] - fn flush(&mut self) -> Result<()> { - Ok(()) - } - - fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> { - self.0.write_vectored(bufs) - } - - #[inline] - fn is_write_vectored(&self) -> bool { - self.0.is_write_vectored() - } -} - -#[unstable(feature = "anonymous_pipe", issue = "127154")] -impl Write for PipeWriter { - fn write(&mut self, buf: &[u8]) -> Result<usize> { - self.0.write(buf) - } - #[inline] - fn flush(&mut self) -> Result<()> { - Ok(()) - } - - fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> { - self.0.write_vectored(bufs) - } - - #[inline] - fn is_write_vectored(&self) -> bool { - self.0.is_write_vectored() - } -} diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs new file mode 100644 index 00000000000..266c7bc9638 --- /dev/null +++ b/library/std/src/io/pipe.rs @@ -0,0 +1,260 @@ +use crate::io; +use crate::sys::anonymous_pipe::{AnonPipe, pipe as pipe_inner}; + +/// Create an anonymous pipe. +/// +/// # Behavior +/// +/// A pipe is a one-way data channel provided by the OS, which works across processes. A pipe is +/// typically used to communicate between two or more separate processes, as there are better, +/// faster ways to communicate within a single process. +/// +/// In particular: +/// +/// * A read on a [`PipeReader`] blocks until the pipe is non-empty. +/// * A write on a [`PipeWriter`] blocks when the pipe is full. +/// * When all copies of a [`PipeWriter`] are closed, a read on the corresponding [`PipeReader`] +/// returns EOF. +/// * [`PipeWriter`] can be shared, and multiple processes or threads can write to it at once, but +/// writes (above a target-specific threshold) may have their data interleaved. +/// * [`PipeReader`] can be shared, and multiple processes or threads can read it at once. Any +/// given byte will only get consumed by one reader. There are no guarantees about data +/// interleaving. +/// * Portable applications cannot assume any atomicity of messages larger than a single byte. +/// +/// # Platform-specific behavior +/// +/// This function currently corresponds to the `pipe` function on Unix and the +/// `CreatePipe` function on Windows. +/// +/// Note that this [may change in the future][changes]. +/// +/// # Capacity +/// +/// Pipe capacity is platform dependent. To quote the Linux [man page]: +/// +/// > Different implementations have different limits for the pipe capacity. Applications should +/// > not rely on a particular capacity: an application should be designed so that a reading process +/// > consumes data as soon as it is available, so that a writing process does not remain blocked. +/// +/// # Examples +/// +/// ```no_run +/// #![feature(anonymous_pipe)] +/// # #[cfg(miri)] fn main() {} +/// # #[cfg(not(miri))] +/// # fn main() -> std::io::Result<()> { +/// use std::process::Command; +/// use std::io::{pipe, Read, Write}; +/// let (ping_rx, mut ping_tx) = pipe()?; +/// let (mut pong_rx, pong_tx) = pipe()?; +/// +/// // Spawn a process that echoes its input. +/// let mut echo_server = Command::new("cat").stdin(ping_rx).stdout(pong_tx).spawn()?; +/// +/// ping_tx.write_all(b"hello")?; +/// // Close to unblock echo_server's reader. +/// drop(ping_tx); +/// +/// let mut buf = String::new(); +/// // Block until echo_server's writer is closed. +/// pong_rx.read_to_string(&mut buf)?; +/// assert_eq!(&buf, "hello"); +/// +/// echo_server.wait()?; +/// # Ok(()) +/// # } +/// ``` +/// [changes]: io#platform-specific-behavior +/// [man page]: https://man7.org/linux/man-pages/man7/pipe.7.html +#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[inline] +pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> { + pipe_inner().map(|(reader, writer)| (PipeReader(reader), PipeWriter(writer))) +} + +/// Read end of an anonymous pipe. +#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[derive(Debug)] +pub struct PipeReader(pub(crate) AnonPipe); + +/// Write end of an anonymous pipe. +#[unstable(feature = "anonymous_pipe", issue = "127154")] +#[derive(Debug)] +pub struct PipeWriter(pub(crate) AnonPipe); + +impl PipeReader { + /// Create a new [`PipeReader`] instance that shares the same underlying file description. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(anonymous_pipe)] + /// # #[cfg(miri)] fn main() {} + /// # #[cfg(not(miri))] + /// # fn main() -> std::io::Result<()> { + /// use std::fs; + /// use std::io::{pipe, Write}; + /// use std::process::Command; + /// const NUM_SLOT: u8 = 2; + /// const NUM_PROC: u8 = 5; + /// const OUTPUT: &str = "work.txt"; + /// + /// let mut jobs = vec![]; + /// let (reader, mut writer) = pipe()?; + /// + /// // Write NUM_SLOT characters the pipe. + /// writer.write_all(&[b'|'; NUM_SLOT as usize])?; + /// + /// // Spawn several processes that read a character from the pipe, do some work, then + /// // write back to the pipe. When the pipe is empty, the processes block, so only + /// // NUM_SLOT processes can be working at any given time. + /// for _ in 0..NUM_PROC { + /// jobs.push( + /// Command::new("bash") + /// .args(["-c", + /// &format!( + /// "read -n 1\n\ + /// echo -n 'x' >> '{OUTPUT}'\n\ + /// echo -n '|'", + /// ), + /// ]) + /// .stdin(reader.try_clone()?) + /// .stdout(writer.try_clone()?) + /// .spawn()?, + /// ); + /// } + /// + /// // Wait for all jobs to finish. + /// for mut job in jobs { + /// job.wait()?; + /// } + /// + /// // Check our work and clean up. + /// let xs = fs::read_to_string(OUTPUT)?; + /// fs::remove_file(OUTPUT)?; + /// assert_eq!(xs, "x".repeat(NUM_PROC.into())); + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "anonymous_pipe", issue = "127154")] + pub fn try_clone(&self) -> io::Result<Self> { + self.0.try_clone().map(Self) + } +} + +impl PipeWriter { + /// Create a new [`PipeWriter`] instance that shares the same underlying file description. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(anonymous_pipe)] + /// # #[cfg(miri)] fn main() {} + /// # #[cfg(not(miri))] + /// # fn main() -> std::io::Result<()> { + /// use std::process::Command; + /// use std::io::{pipe, Read}; + /// let (mut reader, writer) = pipe()?; + /// + /// // Spawn a process that writes to stdout and stderr. + /// let mut peer = Command::new("bash") + /// .args([ + /// "-c", + /// "echo -n foo\n\ + /// echo -n bar >&2" + /// ]) + /// .stdout(writer.try_clone()?) + /// .stderr(writer) + /// .spawn()?; + /// + /// // Read and check the result. + /// let mut msg = String::new(); + /// reader.read_to_string(&mut msg)?; + /// assert_eq!(&msg, "foobar"); + /// + /// peer.wait()?; + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "anonymous_pipe", issue = "127154")] + pub fn try_clone(&self) -> io::Result<Self> { + self.0.try_clone().map(Self) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl io::Read for &PipeReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.0.read(buf) + } + fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> { + self.0.read_vectored(bufs) + } + #[inline] + fn is_read_vectored(&self) -> bool { + self.0.is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + self.0.read_to_end(buf) + } + fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl io::Read for PipeReader { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.0.read(buf) + } + fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> { + self.0.read_vectored(bufs) + } + #[inline] + fn is_read_vectored(&self) -> bool { + self.0.is_read_vectored() + } + fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { + self.0.read_to_end(buf) + } + fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> { + self.0.read_buf(buf) + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl io::Write for &PipeWriter { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.0.write(buf) + } + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { + self.0.write_vectored(bufs) + } + #[inline] + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } +} + +#[unstable(feature = "anonymous_pipe", issue = "127154")] +impl io::Write for PipeWriter { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.0.write(buf) + } + #[inline] + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> { + self.0.write_vectored(bufs) + } + #[inline] + fn is_write_vectored(&self) -> bool { + self.0.is_write_vectored() + } +} diff --git a/library/std/src/io/pipe/tests.rs b/library/std/src/io/pipe/tests.rs new file mode 100644 index 00000000000..c1f3f192ca2 --- /dev/null +++ b/library/std/src/io/pipe/tests.rs @@ -0,0 +1,18 @@ +use crate::io::{Read, Write, pipe}; + +#[test] +#[cfg(all(windows, unix, not(miri)))] +fn pipe_creation_clone_and_rw() { + let (rx, tx) = pipe().unwrap(); + + tx.try_clone().unwrap().write_all(b"12345").unwrap(); + drop(tx); + + let mut rx2 = rx.try_clone().unwrap(); + drop(rx); + + let mut s = String::new(); + rx2.read_to_string(&mut s).unwrap(); + drop(rx2); + assert_eq!(s, "12345"); +} diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs index 85098b3bb18..f64f034cce7 100644 --- a/library/std/src/io/tests.rs +++ b/library/std/src/io/tests.rs @@ -7,7 +7,6 @@ use crate::mem::MaybeUninit; use crate::ops::Deref; #[test] -#[cfg_attr(target_os = "emscripten", ignore)] fn read_until() { let mut buf = Cursor::new(&b"12"[..]); let mut v = Vec::new(); @@ -359,7 +358,6 @@ fn chain_zero_length_read_is_not_eof() { } #[bench] -#[cfg_attr(target_os = "emscripten", ignore)] #[cfg_attr(miri, ignore)] // Miri isn't fast... fn bench_read_to_end(b: &mut test::Bencher) { b.iter(|| { @@ -823,20 +821,3 @@ fn try_oom_error() { let io_err = io::Error::from(reserve_err); assert_eq!(io::ErrorKind::OutOfMemory, io_err.kind()); } - -#[test] -#[cfg(all(windows, unix, not(miri)))] -fn pipe_creation_clone_and_rw() { - let (rx, tx) = std::io::pipe().unwrap(); - - tx.try_clone().unwrap().write_all(b"12345").unwrap(); - drop(tx); - - let mut rx2 = rx.try_clone().unwrap(); - drop(rx); - - let mut s = String::new(); - rx2.read_to_string(&mut s).unwrap(); - drop(rx2); - assert_eq!(s, "12345"); -} diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs index 0c526eafdf3..1d26bf37f4d 100644 --- a/library/std/src/keyword_docs.rs +++ b/library/std/src/keyword_docs.rs @@ -2387,13 +2387,12 @@ mod async_keyword {} /// [`async`]: ../std/keyword.async.html mod await_keyword {} -// FIXME(dyn_compat_renaming): Update URL and link text. #[doc(keyword = "dyn")] // /// `dyn` is a prefix of a [trait object]'s type. /// /// The `dyn` keyword is used to highlight that calls to methods on the associated `Trait` -/// are [dynamically dispatched]. To use the trait this way, it must be 'dyn-compatible'[^1]. +/// are [dynamically dispatched]. To use the trait this way, it must be *dyn compatible*[^1]. /// /// Unlike generic parameters or `impl Trait`, the compiler does not know the concrete type that /// is being passed. That is, the type has been [erased]. @@ -2406,7 +2405,7 @@ mod await_keyword {} /// the function pointer and then that function pointer is called. /// /// See the Reference for more information on [trait objects][ref-trait-obj] -/// and [object safety][ref-obj-safety]. +/// and [dyn compatibility][ref-dyn-compat]. /// /// ## Trade-offs /// @@ -2419,9 +2418,9 @@ mod await_keyword {} /// [trait object]: ../book/ch17-02-trait-objects.html /// [dynamically dispatched]: https://en.wikipedia.org/wiki/Dynamic_dispatch /// [ref-trait-obj]: ../reference/types/trait-object.html -/// [ref-obj-safety]: ../reference/items/traits.html#object-safety +/// [ref-dyn-compat]: ../reference/items/traits.html#dyn-compatibility /// [erased]: https://en.wikipedia.org/wiki/Type_erasure -/// [^1]: Formerly known as 'object safe'. +/// [^1]: Formerly known as *object safe*. mod dyn_keyword {} #[doc(keyword = "union")] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 39f234e4ba6..acb3a0578e5 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -320,6 +320,8 @@ // Library features (core): // tidy-alphabetical-start #![feature(array_chunks)] +#![feature(bstr)] +#![feature(bstr_internals)] #![feature(c_str_module)] #![feature(char_internals)] #![feature(clone_to_uninit)] @@ -581,6 +583,8 @@ pub mod f64; pub mod thread; pub mod ascii; pub mod backtrace; +#[unstable(feature = "bstr", issue = "134915")] +pub mod bstr; pub mod collections; pub mod env; pub mod error; diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index 0cf4902d6d5..00966ee3ecf 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -18,7 +18,7 @@ //! infinite buffer. //! //! 2. A synchronous, bounded channel. The [`sync_channel`] function will -//! return a `(SyncSender, Receiver)` tuple where the storage for pending +//! return a `(Sender, Receiver)` tuple where the storage for pending //! messages is a pre-allocated buffer of a fixed size. All sends will be //! **synchronous** by blocking until there is buffer space available. Note //! that a bound of 0 is allowed, causing the channel to become a "rendezvous" @@ -360,9 +360,17 @@ impl<T> Sender<T> { /// that a return value of [`Err`] means that the data will never be /// received, but a return value of [`Ok`] does *not* mean that the data /// will be received. It is possible for the corresponding receiver to - /// hang up immediately after this function returns [`Ok`]. + /// hang up immediately after this function returns [`Ok`]. However, if + /// the channel is zero-capacity, it acts as a rendezvous channel and a + /// return value of [`Ok`] means that the data has been received. /// - /// This method will never block the current thread. + /// If the channel is full and not disconnected, this call will block until + /// the send operation can proceed. If the channel becomes disconnected, + /// this call will wake up and return an error. The returned error contains + /// the original message. + /// + /// If called on a zero-capacity channel, this method will wait for a receive + /// operation to appear on the other side of the channel. /// /// # Examples /// @@ -650,7 +658,7 @@ impl<T> fmt::Debug for Sender<T> { } /// The receiving half of Rust's [`channel`] (or [`sync_channel`]) type. -/// Different threads can share this [`Sender`] by cloning it. +/// Different threads can share this [`Receiver`] by cloning it. /// /// Messages sent to the channel can be retrieved using [`recv`]. /// diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs index a308fafc68b..53fbc9529e5 100644 --- a/library/std/src/sys/alloc/wasm.rs +++ b/library/std/src/sys/alloc/wasm.rs @@ -1,6 +1,6 @@ //! This is an implementation of a global allocator on wasm targets when -//! emscripten is not in use. In that situation there's no actual runtime for us -//! to lean on for allocation, so instead we provide our own! +//! emscripten or wasi is not in use. In that situation there's no actual runtime +//! for us to lean on for allocation, so instead we provide our own! //! //! The wasm instruction set has two instructions for getting the current //! amount of memory and growing the amount of memory. These instructions are the diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index ec4965c1d71..2bff192a5bd 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -19,8 +19,7 @@ use crate::sys::process::process_common::*; use crate::{fmt, mem, sys}; cfg_if::cfg_if! { - // This workaround is only needed for QNX 7.0 and 7.1. The bug should have been fixed in 8.0 - if #[cfg(any(target_env = "nto70", target_env = "nto71"))] { + if #[cfg(target_os = "nto")] { use crate::thread; use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t}; use crate::time::Duration; @@ -187,12 +186,7 @@ impl Command { // Attempts to fork the process. If successful, returns Ok((0, -1)) // in the child, and Ok((child_pid, -1)) in the parent. - #[cfg(not(any( - target_os = "watchos", - target_os = "tvos", - target_env = "nto70", - target_env = "nto71" - )))] + #[cfg(not(any(target_os = "watchos", target_os = "tvos", target_os = "nto")))] unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> { cvt(libc::fork()) } @@ -201,8 +195,7 @@ impl Command { // or closed a file descriptor while the fork() was occurring". // Documentation says "... or try calling fork() again". This is what we do here. // See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html - // This workaround is only needed for QNX 7.0 and 7.1. The bug should have been fixed in 8.0 - #[cfg(any(target_env = "nto70", target_env = "nto71"))] + #[cfg(target_os = "nto")] unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> { use crate::sys::os::errno; diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index f657f82e6e3..356669980c7 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -130,7 +130,12 @@ impl Thread { } } - #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(any( + target_os = "linux", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "nuttx" + ))] pub fn set_name(name: &CStr) { unsafe { cfg_if::cfg_if! { @@ -139,7 +144,7 @@ impl Thread { const TASK_COMM_LEN: usize = 16; let name = truncate_cstr::<{ TASK_COMM_LEN }>(name); } else { - // FreeBSD and DragonFly BSD do not enforce length limits. + // FreeBSD, DragonFly, FreeBSD and NuttX do not enforce length limits. } }; // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20 for Linux, @@ -150,7 +155,7 @@ impl Thread { } } - #[cfg(any(target_os = "openbsd", target_os = "nuttx"))] + #[cfg(target_os = "openbsd")] pub fn set_name(name: &CStr) { unsafe { libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr()); diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 5d54c790306..361802d101d 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -1,8 +1,7 @@ //! System bindings for the wasm/web platform //! //! This module contains the facade (aka platform-specific) implementations of -//! OS level functionality for wasm. Note that this wasm is *not* the emscripten -//! wasm, so we have no runtime here. +//! OS level functionality for wasm. //! //! This is all super highly experimental and not actually intended for //! wide/production use yet, it's still all in the experimental category. This diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 8141bfac49a..41fe019f110 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -2,7 +2,7 @@ //! //! This module contains the facade (aka platform-specific) implementations of //! OS level functionality for wasm. Note that this wasm is *not* the emscripten -//! wasm, so we have no runtime here. +//! or wasi wasm, so we have no runtime here. //! //! This is all super highly experimental and not actually intended for //! wide/production use yet, it's still all in the experimental category. This diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index b3659351b8c..f8493c21ad4 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -328,9 +328,6 @@ impl File { mem::size_of::<c::FILE_ALLOCATION_INFO>() as u32, ); if result == 0 { - if api::get_last_error().code != 0 { - panic!("FILE_ALLOCATION_INFO failed!!!"); - } let eof = c::FILE_END_OF_FILE_INFO { EndOfFile: 0 }; let result = c::SetFileInformationByHandle( handle.as_raw_handle(), diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 2313f4b5beb..c003503ca8b 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -230,6 +230,14 @@ impl fmt::Display for AccessError { #[stable(feature = "thread_local_try_with", since = "1.26.0")] impl Error for AccessError {} +// This ensures the panicking code is outlined from `with` for `LocalKey`. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[track_caller] +#[cold] +fn panic_access_error(err: AccessError) -> ! { + panic!("cannot access a Thread Local Storage value during or after destruction: {err:?}") +} + impl<T: 'static> LocalKey<T> { #[doc(hidden)] #[unstable( @@ -269,10 +277,10 @@ impl<T: 'static> LocalKey<T> { where F: FnOnce(&T) -> R, { - self.try_with(f).expect( - "cannot access a Thread Local Storage value \ - during or after destruction", - ) + match self.try_with(f) { + Ok(r) => r, + Err(err) => panic_access_error(err), + } } /// Acquires a reference to the value in this TLS key. @@ -327,10 +335,10 @@ impl<T: 'static> LocalKey<T> { let mut init = Some(init); let reference = unsafe { - (self.inner)(Some(&mut init)).as_ref().expect( - "cannot access a Thread Local Storage value \ - during or after destruction", - ) + match (self.inner)(Some(&mut init)).as_ref() { + Some(r) => r, + None => panic_access_error(AccessError), + } }; f(init, reference) diff --git a/library/std/tests/pipe_subprocess.rs b/library/std/tests/pipe_subprocess.rs index df946cdcf2b..00d99a578d5 100644 --- a/library/std/tests/pipe_subprocess.rs +++ b/library/std/tests/pipe_subprocess.rs @@ -1,7 +1,7 @@ #![feature(anonymous_pipe)] fn main() { - #[cfg(all(not(miri), any(unix, windows)))] + #[cfg(all(not(miri), any(unix, windows), not(target_os = "emscripten")))] { use std::io::{Read, pipe}; use std::{env, process}; diff --git a/library/std/tests/process_spawning.rs b/library/std/tests/process_spawning.rs index 3e72e371ade..43b45cb2d2b 100644 --- a/library/std/tests/process_spawning.rs +++ b/library/std/tests/process_spawning.rs @@ -5,7 +5,8 @@ use std::{env, fs, process, str}; mod common; #[test] -#[cfg_attr(any(miri, target_os = "wasi"), ignore)] // Process spawning not supported by Miri and wasi +// Process spawning not supported by Miri, Emscripten and wasi +#[cfg_attr(any(miri, target_os = "emscripten", target_os = "wasi"), ignore)] fn issue_15149() { // If we're the parent, copy our own binary to a new directory. let my_path = env::current_exe().unwrap(); diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs index 4ccd825bf8d..ef6786f4316 100644 --- a/library/test/src/cli.rs +++ b/library/test/src/cli.rs @@ -1,7 +1,7 @@ //! Module converting command-line arguments into test configuration. use std::env; -use std::io::{self, IsTerminal}; +use std::io::{self, IsTerminal, Write}; use std::path::PathBuf; use super::options::{ColorConfig, Options, OutputFormat, RunIgnored}; @@ -44,7 +44,7 @@ impl TestOpts { } /// Result of parsing the options. -pub type OptRes = Result<TestOpts, String>; +pub(crate) type OptRes = Result<TestOpts, String>; /// Result of parsing the option part. type OptPartRes<T> = Result<T, String>; @@ -58,7 +58,7 @@ fn optgroups() -> getopts::Options { .optflag("", "bench", "Run benchmarks instead of tests") .optflag("", "list", "List all tests and benchmarks") .optflag("h", "help", "Display this message") - .optopt("", "logfile", "Write logs to the specified file", "PATH") + .optopt("", "logfile", "Write logs to the specified file (deprecated)", "PATH") .optflag( "", "nocapture", @@ -281,6 +281,10 @@ fn parse_opts_impl(matches: getopts::Matches) -> OptRes { let options = Options::new().display_output(matches.opt_present("show-output")); + if logfile.is_some() { + let _ = write!(io::stderr(), "warning: `--logfile` is deprecated"); + } + let test_opts = TestOpts { list, filters, diff --git a/library/test/src/console.rs b/library/test/src/console.rs index 4d4cdcf4d7b..024ef48fc51 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -20,7 +20,7 @@ use super::types::{NamePadding, TestDesc, TestDescAndFn}; use super::{filter_tests, run_tests, term}; /// Generic wrapper over stdout. -pub enum OutputLocation<T> { +pub(crate) enum OutputLocation<T> { Pretty(Box<term::StdoutTerminal>), Raw(T), } @@ -41,7 +41,7 @@ impl<T: Write> Write for OutputLocation<T> { } } -pub struct ConsoleTestDiscoveryState { +pub(crate) struct ConsoleTestDiscoveryState { pub log_out: Option<File>, pub tests: usize, pub benchmarks: usize, @@ -49,7 +49,7 @@ pub struct ConsoleTestDiscoveryState { } impl ConsoleTestDiscoveryState { - pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestDiscoveryState> { + pub(crate) fn new(opts: &TestOpts) -> io::Result<ConsoleTestDiscoveryState> { let log_out = match opts.logfile { Some(ref path) => Some(File::create(path)?), None => None, @@ -58,7 +58,7 @@ impl ConsoleTestDiscoveryState { Ok(ConsoleTestDiscoveryState { log_out, tests: 0, benchmarks: 0, ignored: 0 }) } - pub fn write_log<F, S>(&mut self, msg: F) -> io::Result<()> + pub(crate) fn write_log<F, S>(&mut self, msg: F) -> io::Result<()> where S: AsRef<str>, F: FnOnce() -> S, @@ -74,7 +74,7 @@ impl ConsoleTestDiscoveryState { } } -pub struct ConsoleTestState { +pub(crate) struct ConsoleTestState { pub log_out: Option<File>, pub total: usize, pub passed: usize, @@ -92,7 +92,7 @@ pub struct ConsoleTestState { } impl ConsoleTestState { - pub fn new(opts: &TestOpts) -> io::Result<ConsoleTestState> { + pub(crate) fn new(opts: &TestOpts) -> io::Result<ConsoleTestState> { let log_out = match opts.logfile { Some(ref path) => Some(File::create(path)?), None => None, @@ -116,7 +116,7 @@ impl ConsoleTestState { }) } - pub fn write_log<F, S>(&mut self, msg: F) -> io::Result<()> + pub(crate) fn write_log<F, S>(&mut self, msg: F) -> io::Result<()> where S: AsRef<str>, F: FnOnce() -> S, @@ -131,7 +131,7 @@ impl ConsoleTestState { } } - pub fn write_log_result( + pub(crate) fn write_log_result( &mut self, test: &TestDesc, result: &TestResult, @@ -170,7 +170,7 @@ impl ConsoleTestState { } // List the tests to console, and optionally to logfile. Filters are honored. -pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> { +pub(crate) fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Result<()> { let output = match term::stdout() { None => OutputLocation::Raw(io::stdout().lock()), Some(t) => OutputLocation::Pretty(t), diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index aa1c50641cb..92c1c0716f1 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -13,7 +13,7 @@ pub(crate) struct JsonFormatter<T> { } impl<T: Write> JsonFormatter<T> { - pub fn new(out: OutputLocation<T>) -> Self { + pub(crate) fn new(out: OutputLocation<T>) -> Self { Self { out } } diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index 96b43200840..57b1b0fecee 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -8,13 +8,13 @@ use crate::test_result::TestResult; use crate::time; use crate::types::{TestDesc, TestType}; -pub struct JunitFormatter<T> { +pub(crate) struct JunitFormatter<T> { out: OutputLocation<T>, results: Vec<(TestDesc, TestResult, Duration, Vec<u8>)>, } impl<T: Write> JunitFormatter<T> { - pub fn new(out: OutputLocation<T>) -> Self { + pub(crate) fn new(out: OutputLocation<T>) -> Self { Self { out, results: Vec::new() } } diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 7089eae4330..bf3fc40db41 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -20,7 +20,7 @@ pub(crate) struct PrettyFormatter<T> { } impl<T: Write> PrettyFormatter<T> { - pub fn new( + pub(crate) fn new( out: OutputLocation<T>, use_color: bool, max_name_len: usize, @@ -31,19 +31,19 @@ impl<T: Write> PrettyFormatter<T> { } #[cfg(test)] - pub fn output_location(&self) -> &OutputLocation<T> { + pub(crate) fn output_location(&self) -> &OutputLocation<T> { &self.out } - pub fn write_ok(&mut self) -> io::Result<()> { + pub(crate) fn write_ok(&mut self) -> io::Result<()> { self.write_short_result("ok", term::color::GREEN) } - pub fn write_failed(&mut self) -> io::Result<()> { + pub(crate) fn write_failed(&mut self) -> io::Result<()> { self.write_short_result("FAILED", term::color::RED) } - pub fn write_ignored(&mut self, message: Option<&'static str>) -> io::Result<()> { + pub(crate) fn write_ignored(&mut self, message: Option<&'static str>) -> io::Result<()> { if let Some(message) = message { self.write_short_result(&format!("ignored, {message}"), term::color::YELLOW) } else { @@ -51,15 +51,15 @@ impl<T: Write> PrettyFormatter<T> { } } - pub fn write_time_failed(&mut self) -> io::Result<()> { + pub(crate) fn write_time_failed(&mut self) -> io::Result<()> { self.write_short_result("FAILED (time limit exceeded)", term::color::RED) } - pub fn write_bench(&mut self) -> io::Result<()> { + pub(crate) fn write_bench(&mut self) -> io::Result<()> { self.write_pretty("bench", term::color::CYAN) } - pub fn write_short_result( + pub(crate) fn write_short_result( &mut self, result: &str, color: term::color::Color, @@ -67,7 +67,7 @@ impl<T: Write> PrettyFormatter<T> { self.write_pretty(result, color) } - pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> { + pub(crate) fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> { match self.out { OutputLocation::Pretty(ref mut term) => { if self.use_color { @@ -86,7 +86,7 @@ impl<T: Write> PrettyFormatter<T> { } } - pub fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> { + pub(crate) fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> { let s = s.as_ref(); self.out.write_all(s.as_bytes())?; self.out.flush() @@ -154,15 +154,15 @@ impl<T: Write> PrettyFormatter<T> { Ok(()) } - pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> { + pub(crate) fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> { self.write_results(&state.not_failures, "successes") } - pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { + pub(crate) fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { self.write_results(&state.failures, "failures") } - pub fn write_time_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { + pub(crate) fn write_time_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { self.write_results(&state.time_failures, "failures (time limit exceeded)") } diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index 534aa2f3311..b28120ab56e 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -25,7 +25,7 @@ pub(crate) struct TerseFormatter<T> { } impl<T: Write> TerseFormatter<T> { - pub fn new( + pub(crate) fn new( out: OutputLocation<T>, use_color: bool, max_name_len: usize, @@ -42,11 +42,11 @@ impl<T: Write> TerseFormatter<T> { } } - pub fn write_ok(&mut self) -> io::Result<()> { + pub(crate) fn write_ok(&mut self) -> io::Result<()> { self.write_short_result(".", term::color::GREEN) } - pub fn write_failed(&mut self, name: &str) -> io::Result<()> { + pub(crate) fn write_failed(&mut self, name: &str) -> io::Result<()> { // Put failed tests on their own line and include the test name, so that it's faster // to see which test failed without having to wait for them all to run. @@ -62,15 +62,15 @@ impl<T: Write> TerseFormatter<T> { self.write_plain("\n") } - pub fn write_ignored(&mut self) -> io::Result<()> { + pub(crate) fn write_ignored(&mut self) -> io::Result<()> { self.write_short_result("i", term::color::YELLOW) } - pub fn write_bench(&mut self) -> io::Result<()> { + pub(crate) fn write_bench(&mut self) -> io::Result<()> { self.write_pretty("bench", term::color::CYAN) } - pub fn write_short_result( + pub(crate) fn write_short_result( &mut self, result: &str, color: term::color::Color, @@ -95,7 +95,7 @@ impl<T: Write> TerseFormatter<T> { Ok(()) } - pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> { + pub(crate) fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> { match self.out { OutputLocation::Pretty(ref mut term) => { if self.use_color { @@ -114,13 +114,13 @@ impl<T: Write> TerseFormatter<T> { } } - pub fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> { + pub(crate) fn write_plain<S: AsRef<str>>(&mut self, s: S) -> io::Result<()> { let s = s.as_ref(); self.out.write_all(s.as_bytes())?; self.out.flush() } - pub fn write_outputs(&mut self, state: &ConsoleTestState) -> io::Result<()> { + pub(crate) fn write_outputs(&mut self, state: &ConsoleTestState) -> io::Result<()> { self.write_plain("\nsuccesses:\n")?; let mut successes = Vec::new(); let mut stdouts = String::new(); @@ -146,7 +146,7 @@ impl<T: Write> TerseFormatter<T> { Ok(()) } - pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { + pub(crate) fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { self.write_plain("\nfailures:\n")?; let mut failures = Vec::new(); let mut fail_out = String::new(); diff --git a/library/test/src/helpers/concurrency.rs b/library/test/src/helpers/concurrency.rs index b1545cbec43..6648b669125 100644 --- a/library/test/src/helpers/concurrency.rs +++ b/library/test/src/helpers/concurrency.rs @@ -4,7 +4,7 @@ use std::num::NonZero; use std::{env, thread}; -pub fn get_concurrency() -> usize { +pub(crate) fn get_concurrency() -> usize { if let Ok(value) = env::var("RUST_TEST_THREADS") { match value.parse::<NonZero<usize>>().ok() { Some(n) => n.get(), diff --git a/library/test/src/helpers/mod.rs b/library/test/src/helpers/mod.rs index 3c79b90b167..2fb29b4c7be 100644 --- a/library/test/src/helpers/mod.rs +++ b/library/test/src/helpers/mod.rs @@ -1,6 +1,6 @@ //! Module with common helpers not directly related to tests //! but used in `libtest`. -pub mod concurrency; -pub mod metrics; -pub mod shuffle; +pub(crate) mod concurrency; +pub(crate) mod metrics; +pub(crate) mod shuffle; diff --git a/library/test/src/helpers/shuffle.rs b/library/test/src/helpers/shuffle.rs index 14389eb0e37..53d1d0e42d4 100644 --- a/library/test/src/helpers/shuffle.rs +++ b/library/test/src/helpers/shuffle.rs @@ -4,7 +4,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use crate::cli::TestOpts; use crate::types::{TestDescAndFn, TestId, TestName}; -pub fn get_shuffle_seed(opts: &TestOpts) -> Option<u64> { +pub(crate) fn get_shuffle_seed(opts: &TestOpts) -> Option<u64> { opts.shuffle_seed.or_else(|| { if opts.shuffle { Some( @@ -19,7 +19,7 @@ pub fn get_shuffle_seed(opts: &TestOpts) -> Option<u64> { }) } -pub fn shuffle_tests(shuffle_seed: u64, tests: &mut [(TestId, TestDescAndFn)]) { +pub(crate) fn shuffle_tests(shuffle_seed: u64, tests: &mut [(TestId, TestDescAndFn)]) { let test_names: Vec<&TestName> = tests.iter().map(|test| &test.1.desc.name).collect(); let test_names_hash = calculate_hash(&test_names); let mut rng = Rng::new(shuffle_seed, test_names_hash); diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index 47407df909b..54f7e4ae79f 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -27,6 +27,7 @@ #![feature(thread_spawn_hook)] #![allow(internal_features)] #![warn(rustdoc::unescaped_backticks)] +#![warn(unreachable_pub)] pub use cli::TestOpts; diff --git a/library/test/src/options.rs b/library/test/src/options.rs index 3eaad59474a..7a5c55f4e24 100644 --- a/library/test/src/options.rs +++ b/library/test/src/options.rs @@ -2,7 +2,7 @@ /// Number of times to run a benchmarked function #[derive(Clone, PartialEq, Eq)] -pub enum BenchMode { +pub(crate) enum BenchMode { Auto, Single, } diff --git a/library/test/src/stats/tests.rs b/library/test/src/stats/tests.rs index 4b209dcf214..7804ddc9291 100644 --- a/library/test/src/stats/tests.rs +++ b/library/test/src/stats/tests.rs @@ -573,13 +573,13 @@ fn test_sum_f64_between_ints_that_sum_to_0() { } #[bench] -pub fn sum_three_items(b: &mut Bencher) { +fn sum_three_items(b: &mut Bencher) { b.iter(|| { [1e20f64, 1.5f64, -1e20f64].sum(); }) } #[bench] -pub fn sum_many_f64(b: &mut Bencher) { +fn sum_many_f64(b: &mut Bencher) { let nums = [-1e30f64, 1e60, 1e30, 1.0, -1e60]; let v = (0..500).map(|i| nums[i % 5]).collect::<Vec<_>>(); @@ -589,4 +589,4 @@ pub fn sum_many_f64(b: &mut Bencher) { } #[bench] -pub fn no_iter(_: &mut Bencher) {} +fn no_iter(_: &mut Bencher) {} diff --git a/library/test/src/term.rs b/library/test/src/term.rs index e736e85d469..d9880a77640 100644 --- a/library/test/src/term.rs +++ b/library/test/src/term.rs @@ -62,7 +62,7 @@ pub(crate) mod color { /// A terminal with similar capabilities to an ANSI Terminal /// (foreground/background colors etc). -pub trait Terminal: Write { +pub(crate) trait Terminal: Write { /// Sets the foreground color to the given color. /// /// If the color is a bright color, but the terminal only supports 8 colors, diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index 79fe07bc1ac..73dcc2e2a0c 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -12,7 +12,7 @@ use super::types::TestDesc; // Return code for secondary process. // Start somewhere other than 0 so we know the return code means what we think // it means. -pub const TR_OK: i32 = 50; +pub(crate) const TR_OK: i32 = 50; // On Windows we use __fastfail to abort, which is documented to use this // exception code. @@ -39,7 +39,7 @@ pub enum TestResult { /// Creates a `TestResult` depending on the raw result of test execution /// and associated data. -pub fn calc_result<'a>( +pub(crate) fn calc_result<'a>( desc: &TestDesc, task_result: Result<(), &'a (dyn Any + 'static + Send)>, time_opts: Option<&time::TestTimeOptions>, @@ -93,7 +93,7 @@ pub fn calc_result<'a>( } /// Creates a `TestResult` depending on the exit code of test subprocess. -pub fn get_result_from_exit_code( +pub(crate) fn get_result_from_exit_code( desc: &TestDesc, status: ExitStatus, time_opts: Option<&time::TestTimeOptions>, diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs index e85e61090a9..47f581fefae 100644 --- a/library/test/src/tests.rs +++ b/library/test/src/tests.rs @@ -78,7 +78,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> { } #[test] -pub fn do_not_run_ignored_tests() { +fn do_not_run_ignored_tests() { fn f() -> Result<(), String> { panic!(); } @@ -106,7 +106,7 @@ pub fn do_not_run_ignored_tests() { } #[test] -pub fn ignored_tests_result_in_ignored() { +fn ignored_tests_result_in_ignored() { fn f() -> Result<(), String> { Ok(()) } @@ -133,9 +133,7 @@ pub fn ignored_tests_result_in_ignored() { assert_eq!(result, TrIgnored); } -// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) #[test] -#[cfg(not(target_os = "emscripten"))] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_should_panic() { fn f() -> Result<(), String> { @@ -164,9 +162,7 @@ fn test_should_panic() { assert_eq!(result, TrOk); } -// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) #[test] -#[cfg(not(target_os = "emscripten"))] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_should_panic_good_message() { fn f() -> Result<(), String> { @@ -195,9 +191,7 @@ fn test_should_panic_good_message() { assert_eq!(result, TrOk); } -// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) #[test] -#[cfg(not(target_os = "emscripten"))] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_should_panic_bad_message() { use crate::tests::TrFailedMsg; @@ -231,9 +225,7 @@ fn test_should_panic_bad_message() { assert_eq!(result, TrFailedMsg(failed_msg.to_string())); } -// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) #[test] -#[cfg(not(target_os = "emscripten"))] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_should_panic_non_string_message_type() { use std::any::TypeId; @@ -272,9 +264,7 @@ fn test_should_panic_non_string_message_type() { assert_eq!(result, TrFailedMsg(failed_msg)); } -// FIXME: Re-enable emscripten once it can catch panics again (introduced by #65251) #[test] -#[cfg(not(target_os = "emscripten"))] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_should_panic_but_succeeds() { let should_panic_variants = [ShouldPanic::Yes, ShouldPanic::YesWithMessage("error message")]; @@ -479,7 +469,7 @@ fn parse_include_ignored_flag() { } #[test] -pub fn filter_for_ignored_option() { +fn filter_for_ignored_option() { // When we run ignored tests the test filter should filter out all the // unignored tests and flip the ignore flag on the rest to false @@ -496,7 +486,7 @@ pub fn filter_for_ignored_option() { } #[test] -pub fn run_include_ignored_option() { +fn run_include_ignored_option() { // When we "--include-ignored" tests, the ignore flag should be set to false on // all tests and no test filtered out @@ -513,7 +503,7 @@ pub fn run_include_ignored_option() { } #[test] -pub fn exclude_should_panic_option() { +fn exclude_should_panic_option() { let mut opts = TestOpts::new(); opts.run_tests = true; opts.exclude_should_panic = true; @@ -544,7 +534,7 @@ pub fn exclude_should_panic_option() { } #[test] -pub fn exact_filter_match() { +fn exact_filter_match() { fn tests() -> Vec<TestDescAndFn> { ["base", "base::test", "base::test1", "base::test2"] .into_iter() @@ -667,7 +657,7 @@ fn sample_tests() -> Vec<TestDescAndFn> { } #[test] -pub fn shuffle_tests() { +fn shuffle_tests() { let mut opts = TestOpts::new(); opts.shuffle = true; @@ -686,7 +676,7 @@ pub fn shuffle_tests() { } #[test] -pub fn shuffle_tests_with_seed() { +fn shuffle_tests_with_seed() { let mut opts = TestOpts::new(); opts.shuffle = true; @@ -704,7 +694,7 @@ pub fn shuffle_tests_with_seed() { } #[test] -pub fn order_depends_on_more_than_seed() { +fn order_depends_on_more_than_seed() { let mut opts = TestOpts::new(); opts.shuffle = true; @@ -732,7 +722,7 @@ pub fn order_depends_on_more_than_seed() { } #[test] -pub fn test_metricmap_compare() { +fn test_metricmap_compare() { let mut m1 = MetricMap::new(); let mut m2 = MetricMap::new(); m1.insert_metric("in-both-noise", 1000.0, 200.0); @@ -755,7 +745,7 @@ pub fn test_metricmap_compare() { } #[test] -pub fn test_bench_once_no_iter() { +fn test_bench_once_no_iter() { fn f(_: &mut Bencher) -> Result<(), String> { Ok(()) } @@ -763,7 +753,7 @@ pub fn test_bench_once_no_iter() { } #[test] -pub fn test_bench_once_iter() { +fn test_bench_once_iter() { fn f(b: &mut Bencher) -> Result<(), String> { b.iter(|| {}); Ok(()) @@ -772,7 +762,7 @@ pub fn test_bench_once_iter() { } #[test] -pub fn test_bench_no_iter() { +fn test_bench_no_iter() { fn f(_: &mut Bencher) -> Result<(), String> { Ok(()) } @@ -799,7 +789,7 @@ pub fn test_bench_no_iter() { } #[test] -pub fn test_bench_iter() { +fn test_bench_iter() { fn f(b: &mut Bencher) -> Result<(), String> { b.iter(|| {}); Ok(()) diff --git a/library/test/src/time.rs b/library/test/src/time.rs index 02ae050db55..f63b156b3dc 100644 --- a/library/test/src/time.rs +++ b/library/test/src/time.rs @@ -11,7 +11,7 @@ use std::{env, fmt}; use super::types::{TestDesc, TestType}; -pub const TEST_WARN_TIMEOUT_S: u64 = 60; +pub(crate) const TEST_WARN_TIMEOUT_S: u64 = 60; /// This small module contains constants used by `report-time` option. /// Those constants values will be used if corresponding environment variables are not set. @@ -22,42 +22,42 @@ pub const TEST_WARN_TIMEOUT_S: u64 = 60; /// /// Example of the expected format is `RUST_TEST_TIME_xxx=100,200`, where 100 means /// warn time, and 200 means critical time. -pub mod time_constants { +pub(crate) mod time_constants { use std::time::Duration; use super::TEST_WARN_TIMEOUT_S; /// Environment variable for overriding default threshold for unit-tests. - pub const UNIT_ENV_NAME: &str = "RUST_TEST_TIME_UNIT"; + pub(crate) const UNIT_ENV_NAME: &str = "RUST_TEST_TIME_UNIT"; // Unit tests are supposed to be really quick. - pub const UNIT_WARN: Duration = Duration::from_millis(50); - pub const UNIT_CRITICAL: Duration = Duration::from_millis(100); + pub(crate) const UNIT_WARN: Duration = Duration::from_millis(50); + pub(crate) const UNIT_CRITICAL: Duration = Duration::from_millis(100); /// Environment variable for overriding default threshold for unit-tests. - pub const INTEGRATION_ENV_NAME: &str = "RUST_TEST_TIME_INTEGRATION"; + pub(crate) const INTEGRATION_ENV_NAME: &str = "RUST_TEST_TIME_INTEGRATION"; // Integration tests may have a lot of work, so they can take longer to execute. - pub const INTEGRATION_WARN: Duration = Duration::from_millis(500); - pub const INTEGRATION_CRITICAL: Duration = Duration::from_millis(1000); + pub(crate) const INTEGRATION_WARN: Duration = Duration::from_millis(500); + pub(crate) const INTEGRATION_CRITICAL: Duration = Duration::from_millis(1000); /// Environment variable for overriding default threshold for unit-tests. - pub const DOCTEST_ENV_NAME: &str = "RUST_TEST_TIME_DOCTEST"; + pub(crate) const DOCTEST_ENV_NAME: &str = "RUST_TEST_TIME_DOCTEST"; // Doctests are similar to integration tests, because they can include a lot of // initialization code. - pub const DOCTEST_WARN: Duration = INTEGRATION_WARN; - pub const DOCTEST_CRITICAL: Duration = INTEGRATION_CRITICAL; + pub(crate) const DOCTEST_WARN: Duration = INTEGRATION_WARN; + pub(crate) const DOCTEST_CRITICAL: Duration = INTEGRATION_CRITICAL; // Do not suppose anything about unknown tests, base limits on the // `TEST_WARN_TIMEOUT_S` constant. - pub const UNKNOWN_WARN: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S); - pub const UNKNOWN_CRITICAL: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S * 2); + pub(crate) const UNKNOWN_WARN: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S); + pub(crate) const UNKNOWN_CRITICAL: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S * 2); } /// Returns an `Instance` object denoting when the test should be considered /// timed out. -pub fn get_default_test_timeout() -> Instant { +pub(crate) fn get_default_test_timeout() -> Instant { Instant::now() + Duration::from_secs(TEST_WARN_TIMEOUT_S) } @@ -73,7 +73,7 @@ impl fmt::Display for TestExecTime { /// The measured execution time of the whole test suite. #[derive(Debug, Clone, Default, PartialEq)] -pub struct TestSuiteExecTime(pub Duration); +pub(crate) struct TestSuiteExecTime(pub Duration); impl fmt::Display for TestSuiteExecTime { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index c46aae2ded1..d2f3c7f36ca 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -62,7 +62,7 @@ dependencies = [ "tracing-subscriber", "tracing-tree", "walkdir", - "windows 0.52.0", + "windows", "xz2", ] @@ -663,7 +663,7 @@ dependencies = [ "libc", "memchr", "ntapi", - "windows 0.57.0", + "windows", ] [[package]] @@ -845,30 +845,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core 0.52.0", - "windows-targets", -] - -[[package]] -name = "windows" version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" dependencies = [ - "windows-core 0.57.0", - "windows-targets", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ + "windows-core", "windows-targets", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 71c56c4e85e..d7afcc7f27d 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -74,7 +74,7 @@ tracing-tree = { version = "0.4.0", optional = true } version = "1.0.0" [target.'cfg(windows)'.dependencies.windows] -version = "0.52" +version = "0.57" features = [ "Win32_Foundation", "Win32_Security", diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 76ee40c6f45..01a9792f1b3 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1268,6 +1268,11 @@ def bootstrap(args): config_toml = "" profile = RustBuild.get_toml_static(config_toml, "profile") + is_non_git_source = not os.path.exists(os.path.join(rust_root, ".git")) + + if profile is None and is_non_git_source: + profile = "dist" + if profile is not None: # Allows creating alias for profile names, allowing # profiles to be renamed while maintaining back compatibility @@ -1305,9 +1310,6 @@ def bootstrap(args): args = [build.bootstrap_binary()] args.extend(sys.argv[1:]) env = os.environ.copy() - # The Python process ID is used when creating a Windows job object - # (see src\bootstrap\src\utils\job.rs) - env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) env["BOOTSTRAP_PYTHON"] = sys.executable run(args, env=env, verbose=build.verbose, is_bootstrap=True) diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml index a737de3bd08..269b90106e3 100644 --- a/src/bootstrap/defaults/config.compiler.toml +++ b/src/bootstrap/defaults/config.compiler.toml @@ -8,6 +8,8 @@ compiler-docs = true # where adding `debug!()` appears to do nothing. # However, it makes running the compiler slightly slower. debug-logging = true +# Enables debug assertions, which guard from many mistakes when working on the compiler. +debug-assertions = true # Get actually-useful information from backtraces, profiling, etc. with minimal added bytes debuginfo-level = "line-tables-only" # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 082b7431440..7e6a39a236e 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -55,14 +55,14 @@ check-aux: $(BOOTSTRAP_ARGS) # Run standard library tests in Miri. $(Q)$(BOOTSTRAP) miri --stage 2 \ - library/core \ + library/coretests \ library/alloc \ $(BOOTSTRAP_ARGS) \ --no-doc # Some doctests use file system operations to demonstrate dealing with `Result`. $(Q)MIRIFLAGS="-Zmiri-disable-isolation" \ $(BOOTSTRAP) miri --stage 2 \ - library/core \ + library/coretests \ library/alloc \ $(BOOTSTRAP_ARGS) \ --doc @@ -106,14 +106,10 @@ STAGE_2_TEST_SET2 := test --stage 2 --skip=tests --skip=coverage-map --skip=cove # this intentionally doesn't use `$(BOOTSTRAP)` so we can test the shebang on Windows ci-msvc-py: - $(Q)$(CFG_SRC_DIR)/x.py test --stage 2 tidy -ci-msvc-ps1: - $(Q)$(CFG_SRC_DIR)/x.ps1 test --stage 2 --skip tidy -ci-msvc: ci-msvc-py ci-msvc-ps1 -ci-msvc-py-set1: $(Q)$(CFG_SRC_DIR)/x.py $(STAGE_2_TEST_SET1) -ci-msvc-ps1-set2: +ci-msvc-ps1: $(Q)$(CFG_SRC_DIR)/x.ps1 $(STAGE_2_TEST_SET2) +ci-msvc: ci-msvc-py ci-msvc-ps1 ## MingW native builders diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index b6552774195..5fcf7eda8df 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -16,11 +16,7 @@ use bootstrap::{ }; use build_helper::ci::CiEnv; #[cfg(feature = "tracing")] -use tracing::*; -#[cfg(feature = "tracing")] -use tracing_subscriber::EnvFilter; -#[cfg(feature = "tracing")] -use tracing_subscriber::prelude::*; +use tracing::{debug, instrument}; #[cfg_attr(feature = "tracing", instrument(level = "trace", name = "main"))] fn main() { @@ -33,7 +29,11 @@ fn main() { return; } + #[cfg(feature = "tracing")] + debug!("parsing flags"); let flags = Flags::parse(&args); + #[cfg(feature = "tracing")] + debug!("parsing config based on flags"); let config = Config::parse(flags); let mut build_lock; @@ -57,7 +57,9 @@ fn main() { } err => { drop(err); - if let Ok(pid) = pid { + // #135972: We can reach this point when the lock has been taken, + // but the locker has not yet written its PID to the file + if let Some(pid) = pid.ok().filter(|pid| !pid.is_empty()) { println!("WARNING: build directory locked by process {pid}, waiting for lock"); } else { println!("WARNING: build directory locked, waiting for lock"); @@ -93,6 +95,8 @@ fn main() { let dump_bootstrap_shims = config.dump_bootstrap_shims; let out_dir = config.out.clone(); + #[cfg(feature = "tracing")] + debug!("creating new build based on config"); Build::new(config).build(); if suggest_setup { @@ -209,16 +213,14 @@ fn check_version(config: &Config) -> Option<String> { // "tracing", instrument(..))]`. #[cfg(feature = "tracing")] fn setup_tracing() { + use tracing_subscriber::EnvFilter; + use tracing_subscriber::layer::SubscriberExt; + let filter = EnvFilter::from_env("BOOTSTRAP_TRACING"); - let layer = tracing_tree::HierarchicalLayer::default() - .with_writer(std::io::stderr) - .with_ansi(true) - .with_targets(true) - .with_bracketed_fields(true) - .with_indent_amount(2) - .with_indent_lines(true); - let subscriber = tracing_subscriber::registry().with(filter).with(layer); - - tracing::subscriber::set_global_default(subscriber).unwrap(); - trace!("tracing subscriber setup"); + // cf. <https://docs.rs/tracing-tree/latest/tracing_tree/struct.HierarchicalLayer.html>. + let layer = tracing_tree::HierarchicalLayer::default().with_targets(true).with_indent_amount(2); + + let registry = tracing_subscriber::registry().with(filter).with(layer); + + tracing::subscriber::set_global_default(registry).unwrap(); } diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index d8d862caf6a..f4a86e26396 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -45,7 +45,7 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.crate_or_deps("sysroot").path("library") + run.crate_or_deps("sysroot").crate_or_deps("coretests").path("library") } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 470e400243f..18f920b85ee 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1015,7 +1015,18 @@ impl Step for PlainSourceTarball { ]; let src_dirs = ["src", "compiler", "library", "tests", "LICENSES"]; - copy_src_dirs(builder, &builder.src, &src_dirs, &[], plain_dst_src); + copy_src_dirs( + builder, + &builder.src, + &src_dirs, + &[ + // We don't currently use the GCC source code for building any official components, + // it is very big, and has unclear licensing implications due to being GPL licensed. + // We thus exclude it from the source tarball from now. + "src/gcc", + ], + plain_dst_src, + ); // Copy the files normally for item in &src_files { diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index 563b715fa64..98b8635132b 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -12,6 +12,8 @@ use std::fs; use std::path::PathBuf; use std::sync::OnceLock; +use build_helper::ci::CiEnv; + use crate::Kind; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; @@ -112,16 +114,60 @@ impl Step for Gcc { return true; } - command(root.join("contrib/download_prerequisites")).current_dir(&root).run(builder); - command(root.join("configure")) + // GCC creates files (e.g. symlinks to the downloaded dependencies) + // in the source directory, which does not work with our CI setup, where we mount + // source directories as read-only on Linux. + // Therefore, as a part of the build in CI, we first copy the whole source directory + // to the build directory, and perform the build from there. + let src_dir = if CiEnv::is_ci() { + let src_dir = builder.gcc_out(target).join("src"); + if src_dir.exists() { + builder.remove_dir(&src_dir); + } + builder.create_dir(&src_dir); + builder.cp_link_r(&root, &src_dir); + src_dir + } else { + root + }; + + command(src_dir.join("contrib/download_prerequisites")).current_dir(&src_dir).run(builder); + let mut configure_cmd = command(src_dir.join("configure")); + configure_cmd .current_dir(&out_dir) + // On CI, we compile GCC with Clang. + // The -Wno-everything flag is needed to make GCC compile with Clang 19. + // `-g -O2` are the default flags that are otherwise used by Make. + // FIXME(kobzol): change the flags once we have [gcc] configuration in config.toml. + .env("CXXFLAGS", "-Wno-everything -g -O2") + .env("CFLAGS", "-Wno-everything -g -O2") .arg("--enable-host-shared") .arg("--enable-languages=jit") .arg("--enable-checking=release") .arg("--disable-bootstrap") .arg("--disable-multilib") - .arg(format!("--prefix={}", install_dir.display())) - .run(builder); + .arg(format!("--prefix={}", install_dir.display())); + let cc = builder.build.cc(target).display().to_string(); + let cc = builder + .build + .config + .ccache + .as_ref() + .map_or_else(|| cc.clone(), |ccache| format!("{ccache} {cc}")); + configure_cmd.env("CC", cc); + + if let Ok(ref cxx) = builder.build.cxx(target) { + let cxx = cxx.display().to_string(); + let cxx = builder + .build + .config + .ccache + .as_ref() + .map_or_else(|| cxx.clone(), |ccache| format!("{ccache} {cxx}")); + configure_cmd.env("CXX", cxx); + } + configure_cmd.run(builder); + command("make").current_dir(&out_dir).arg(format!("-j{}", builder.jobs())).run(builder); command("make").current_dir(&out_dir).arg("install").run(builder); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index cf55fff4078..3cf25373b89 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1338,7 +1338,7 @@ impl Step for CrtBeginEnd { .file(crtbegin_src) .file(crtend_src); - // Those flags are defined in src/llvm-project/compiler-rt/lib/crt/CMakeLists.txt + // Those flags are defined in src/llvm-project/compiler-rt/lib/builtins/CMakeLists.txt // Currently only consumer of those objects is musl, which use .init_array/.fini_array // instead of .ctors/.dtors cfg.flag("-std=c11") diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 9f3e4d9cc89..5e250d18ce6 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -87,7 +87,7 @@ impl Step for CrateBootstrap { &[], ); let crate_name = path.rsplit_once('/').unwrap().1; - run_cargo_test(cargo, &[], &[], crate_name, crate_name, compiler, bootstrap_host, builder); + run_cargo_test(cargo, &[], &[], crate_name, crate_name, bootstrap_host, builder); } } @@ -143,7 +143,6 @@ You can skip linkcheck with --skip src/tools/linkchecker" &[], "linkchecker", "linkchecker self tests", - compiler, bootstrap_host, builder, ); @@ -312,7 +311,7 @@ impl Step for Cargo { ); // NOTE: can't use `run_cargo_test` because we need to overwrite `PATH` - let mut cargo = prepare_cargo_test(cargo, &[], &[], "cargo", compiler, self.host, builder); + let mut cargo = prepare_cargo_test(cargo, &[], &[], "cargo", self.host, builder); // Don't run cross-compile tests, we may not have cross-compiled libstd libs // available. @@ -397,7 +396,7 @@ impl Step for RustAnalyzer { cargo.env("SKIP_SLOW_TESTS", "1"); cargo.add_rustc_lib_path(builder); - run_cargo_test(cargo, &[], &[], "rust-analyzer", "rust-analyzer", compiler, host, builder); + run_cargo_test(cargo, &[], &[], "rust-analyzer", "rust-analyzer", host, builder); } } @@ -445,7 +444,7 @@ impl Step for Rustfmt { cargo.add_rustc_lib_path(builder); - run_cargo_test(cargo, &[], &[], "rustfmt", "rustfmt", compiler, host, builder); + run_cargo_test(cargo, &[], &[], "rustfmt", "rustfmt", host, builder); } } @@ -565,7 +564,7 @@ impl Step for Miri { // We can NOT use `run_cargo_test` since Miri's integration tests do not use the usual test // harness and therefore do not understand the flags added by `add_flags_and_try_run_test`. - let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", host_compiler, host, builder); + let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", host, builder); // miri tests need to know about the stage sysroot cargo.env("MIRI_SYSROOT", &miri_sysroot); @@ -713,16 +712,7 @@ impl Step for CompiletestTest { &[], ); cargo.allow_features("test"); - run_cargo_test( - cargo, - &[], - &[], - "compiletest", - "compiletest self test", - compiler, - host, - builder, - ); + run_cargo_test(cargo, &[], &[], "compiletest", "compiletest self test", host, builder); } } @@ -769,7 +759,7 @@ impl Step for Clippy { cargo.env("HOST_LIBS", host_libs); cargo.add_rustc_lib_path(builder); - let cargo = prepare_cargo_test(cargo, &[], &[], "clippy", compiler, host, builder); + let cargo = prepare_cargo_test(cargo, &[], &[], "clippy", host, builder); let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host); @@ -1294,7 +1284,6 @@ impl Step for CrateRunMakeSupport { &[], "run-make-support", "run-make-support self test", - compiler, host, builder, ); @@ -1334,16 +1323,7 @@ impl Step for CrateBuildHelper { &[], ); cargo.allow_features("test"); - run_cargo_test( - cargo, - &[], - &[], - "build_helper", - "build_helper self test", - compiler, - host, - builder, - ); + run_cargo_test(cargo, &[], &[], "build_helper", "build_helper self test", host, builder); } } @@ -1862,12 +1842,19 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the let mut hostflags = flags.clone(); hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display())); hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No)); - for flag in hostflags { - cmd.arg("--host-rustcflags").arg(flag); - } let mut targetflags = flags; targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display())); + + // FIXME: on macOS, we get linker warnings about duplicate `-lm` flags. We should investigate why this happens. + if suite == "ui-fulldeps" && target.ends_with("darwin") { + hostflags.push("-Alinker_messages".into()); + targetflags.push("-Alinker_messages".into()); + } + + for flag in hostflags { + cmd.arg("--host-rustcflags").arg(flag); + } for flag in targetflags { cmd.arg("--target-rustcflags").arg(flag); } @@ -2540,19 +2527,17 @@ impl Step for CrateLibrustc { /// Given a `cargo test` subcommand, add the appropriate flags and run it. /// /// Returns whether the test succeeded. -#[allow(clippy::too_many_arguments)] // FIXME: reduce the number of args and remove this. fn run_cargo_test<'a>( - cargo: impl Into<BootstrapCommand>, + cargo: builder::Cargo, libtest_args: &[&str], crates: &[String], primary_crate: &str, description: impl Into<Option<&'a str>>, - compiler: Compiler, target: TargetSelection, builder: &Builder<'_>, ) -> bool { - let mut cargo = - prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder); + let compiler = cargo.compiler(); + let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, primary_crate, target, builder); let _time = helpers::timeit(builder); let _group = description.into().and_then(|what| { builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target) @@ -2573,15 +2558,15 @@ fn run_cargo_test<'a>( /// Given a `cargo test` subcommand, pass it the appropriate test flags given a `builder`. fn prepare_cargo_test( - cargo: impl Into<BootstrapCommand>, + cargo: builder::Cargo, libtest_args: &[&str], crates: &[String], primary_crate: &str, - compiler: Compiler, target: TargetSelection, builder: &Builder<'_>, ) -> BootstrapCommand { - let mut cargo = cargo.into(); + let compiler = cargo.compiler(); + let mut cargo: BootstrapCommand = cargo.into(); // Propagate `--bless` if it has not already been set/unset // Any tools that want to use this should bless if `RUSTC_BLESS` is set to @@ -2673,7 +2658,7 @@ impl Step for Crate { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.crate_or_deps("sysroot") + run.crate_or_deps("sysroot").crate_or_deps("coretests") } fn make_run(run: RunConfig<'_>) { @@ -2793,7 +2778,6 @@ impl Step for Crate { &self.crates, &self.crates[0], &*crate_description(&self.crates), - compiler, target, builder, ); @@ -2895,7 +2879,6 @@ impl Step for CrateRustdoc { &["rustdoc:0.0.0".to_string()], "rustdoc", "rustdoc", - compiler, target, builder, ); @@ -2956,7 +2939,6 @@ impl Step for CrateRustdocJsonTypes { &["rustdoc-json-types".to_string()], "rustdoc-json-types", "rustdoc-json-types", - compiler, target, builder, ); @@ -3113,23 +3095,25 @@ impl Step for Bootstrap { // Use `python -m unittest` manually if you want to pass arguments. check_bootstrap.delay_failure().run(builder); - let mut cmd = command(&builder.initial_cargo); - cmd.arg("test") - .current_dir(builder.src.join("src/bootstrap")) - .env("RUSTFLAGS", "--cfg test -Cdebuginfo=2") + let mut cargo = tool::prepare_tool_cargo( + builder, + compiler, + Mode::ToolBootstrap, + host, + Kind::Test, + "src/bootstrap", + SourceType::InTree, + &[], + ); + + cargo + .rustflag("-Cdebuginfo=2") .env("CARGO_TARGET_DIR", builder.out.join("bootstrap")) - .env("RUSTC_BOOTSTRAP", "1") - .env("RUSTDOC", builder.rustdoc(compiler)) - .env("RUSTC", &builder.initial_rustc); - if let Some(flags) = option_env!("RUSTFLAGS") { - // Use the same rustc flags for testing as for "normal" compilation, - // so that Cargo doesn’t recompile the entire dependency graph every time: - // https://github.com/rust-lang/rust/issues/49215 - cmd.env("RUSTFLAGS", flags); - } + .env("RUSTC_BOOTSTRAP", "1"); + // bootstrap tests are racy on directory creation so just run them one at a time. // Since there's not many this shouldn't be a problem. - run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", None, compiler, host, builder); + run_cargo_test(cargo, &["--test-threads=1"], &[], "bootstrap", None, host, builder); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -3254,7 +3238,7 @@ impl Step for RustInstaller { bootstrap_host, bootstrap_host, ); - run_cargo_test(cargo, &[], &[], "installer", None, compiler, bootstrap_host, builder); + run_cargo_test(cargo, &[], &[], "installer", None, bootstrap_host, builder); // We currently don't support running the test.sh script outside linux(?) environments. // Eventually this should likely migrate to #[test]s in rust-installer proper rather than a @@ -3577,6 +3561,8 @@ impl Step for CodegenGCC { let mut cargo = build_cargo(); cargo + // cg_gcc's build system ignores RUSTFLAGS. pass some flags through CG_RUSTFLAGS instead. + .env("CG_RUSTFLAGS", "-Alinker-messages") .arg("--") .arg("test") .arg("--use-system-gcc") @@ -3639,16 +3625,7 @@ impl Step for TestFloatParse { &[], ); - run_cargo_test( - cargo_test, - &[], - &[], - crate_name, - crate_name, - compiler, - bootstrap_host, - builder, - ); + run_cargo_test(cargo_test, &[], &[], crate_name, crate_name, bootstrap_host, builder); // Run the actual parse tests. let mut cargo_run = tool::prepare_tool_cargo( diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index f9fb19ddb09..d418237a568 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -121,6 +121,10 @@ impl Cargo { cargo } + pub fn compiler(&self) -> Compiler { + self.compiler + } + pub fn into_cmd(self) -> BootstrapCommand { self.into() } @@ -269,6 +273,13 @@ impl Cargo { self.rustflags.arg("-Clink-arg=-gz"); } + // Ignore linker warnings for now. These are complicated to fix and don't affect the build. + // FIXME: we should really investigate these... + // cfg(bootstrap) + if compiler.stage != 0 { + self.rustflags.arg("-Alinker-messages"); + } + // Throughout the build Cargo can execute a number of build scripts // compiling C/C++ code and we need to pass compilers, archivers, flags, etc // obtained previously to those build scripts. diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 1c49063ef5c..98490118f7d 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -18,6 +18,8 @@ use build_helper::exit; use build_helper::git::{GitConfig, get_closest_merge_commit, output_result}; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; +#[cfg(feature = "tracing")] +use tracing::{instrument, span}; use crate::core::build_steps::compile::CODEGEN_BACKEND_PREFIX; use crate::core::build_steps::llvm; @@ -1227,7 +1229,14 @@ define_config! { } impl Config { + #[cfg_attr( + feature = "tracing", + instrument(target = "CONFIG_HANDLING", level = "trace", name = "Config::default_opts") + )] pub fn default_opts() -> Config { + #[cfg(feature = "tracing")] + span!(target: "CONFIG_HANDLING", tracing::Level::TRACE, "constructing default config"); + Config { bypass_bootstrap_lock: false, llvm_optimize: true, @@ -1311,10 +1320,23 @@ impl Config { }) } + #[cfg_attr( + feature = "tracing", + instrument(target = "CONFIG_HANDLING", level = "trace", name = "Config::parse", skip_all) + )] pub fn parse(flags: Flags) -> Config { Self::parse_inner(flags, Self::get_toml) } + #[cfg_attr( + feature = "tracing", + instrument( + target = "CONFIG_HANDLING", + level = "trace", + name = "Config::parse_inner", + skip_all + ) + )] pub(crate) fn parse_inner( mut flags: Flags, get_toml: impl Fn(&Path) -> Result<TomlConfig, toml::de::Error>, @@ -1323,6 +1345,17 @@ impl Config { // Set flags. config.paths = std::mem::take(&mut flags.paths); + + #[cfg(feature = "tracing")] + span!( + target: "CONFIG_HANDLING", + tracing::Level::TRACE, + "collecting paths and path exclusions", + "flags.paths" = ?flags.paths, + "flags.skip" = ?flags.skip, + "flags.exclude" = ?flags.exclude + ); + config.skip = flags .skip .into_iter() @@ -1339,6 +1372,14 @@ impl Config { }) .collect(); + #[cfg(feature = "tracing")] + span!( + target: "CONFIG_HANDLING", + tracing::Level::TRACE, + "normalizing and combining `flag.skip`/`flag.exclude` paths", + "config.skip" = ?config.skip, + ); + config.include_default_paths = flags.include_default_paths; config.rustc_error_format = flags.rustc_error_format; config.json_output = flags.json_output; @@ -1418,7 +1459,11 @@ impl Config { config.stage0_metadata = build_helper::stage0_parser::parse_stage0_file(); - // Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, then `config.toml` in the root directory. + // Find configuration file, with the following cascading fallback (first match wins): + // - `--config <path>` + // - `RUST_BOOTSTRAP_CONFIG` + // - `./config.toml` + // - `config.toml` in the root directory. let toml_path = flags .config .clone() @@ -2875,21 +2920,26 @@ impl Config { allowed_paths.push(":!library"); } - // Look for a version to compare to based on the current commit. - // Only commits merged by bors will have CI artifacts. - let commit = match self.last_modified_commit(&allowed_paths, "download-rustc", if_unchanged) - { - Some(commit) => commit, - None => { - if if_unchanged { - return None; + let commit = if self.rust_info.is_managed_git_subrepository() { + // Look for a version to compare to based on the current commit. + // Only commits merged by bors will have CI artifacts. + match self.last_modified_commit(&allowed_paths, "download-rustc", if_unchanged) { + Some(commit) => commit, + None => { + if if_unchanged { + return None; + } + println!("ERROR: could not find commit hash for downloading rustc"); + println!("HELP: maybe your repository history is too shallow?"); + println!("HELP: consider setting `rust.download-rustc=false` in config.toml"); + println!("HELP: or fetch enough history to include one upstream commit"); + crate::exit!(1); } - println!("ERROR: could not find commit hash for downloading rustc"); - println!("HELP: maybe your repository history is too shallow?"); - println!("HELP: consider setting `rust.download-rustc=false` in config.toml"); - println!("HELP: or fetch enough history to include one upstream commit"); - crate::exit!(1); } + } else { + channel::read_commit_info_file(&self.src) + .map(|info| info.sha.trim().to_owned()) + .expect("git-commit-info is missing in the project root") }; if CiEnv::is_ci() && { @@ -2926,10 +2976,8 @@ impl Config { let if_unchanged = || { if self.rust_info.is_from_tarball() { // Git is needed for running "if-unchanged" logic. - println!( - "WARNING: 'if-unchanged' has no effect on tarball sources; ignoring `download-ci-llvm`." - ); - return false; + println!("ERROR: 'if-unchanged' is only compatible with Git managed sources."); + crate::exit!(1); } // Fetching the LLVM submodule is unnecessary for self-tests. @@ -2971,6 +3019,11 @@ impl Config { option_name: &str, if_unchanged: bool, ) -> Option<String> { + assert!( + self.rust_info.is_managed_git_subrepository(), + "Can't run `Config::last_modified_commit` on a non-git source." + ); + // Look for a version to compare to based on the current commit. // Only commits merged by bors will have CI artifacts. let commit = get_closest_merge_commit(Some(&self.src), &self.git_config(), &[]).unwrap(); diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs index f17103f97dc..27fb00cb06e 100644 --- a/src/bootstrap/src/core/config/flags.rs +++ b/src/bootstrap/src/core/config/flags.rs @@ -6,6 +6,8 @@ use std::path::{Path, PathBuf}; use clap::{CommandFactory, Parser, ValueEnum}; +#[cfg(feature = "tracing")] +use tracing::instrument; use crate::core::build_steps::setup::Profile; use crate::core::builder::{Builder, Kind}; @@ -211,6 +213,10 @@ impl Flags { } } + #[cfg_attr( + feature = "tracing", + instrument(level = "trace", name = "Flags::parse", skip_all, fields(args = ?args)) + )] pub fn parse(args: &[String]) -> Self { Flags::parse_from(normalize_args(args)) } diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index c5e578ff351..f0a185ee3a7 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -92,7 +92,7 @@ fn detect_src_and_out() { // `{build-dir}/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804` // `{build-dir}` can be anywhere, not just in the rust project directory. let dep = Path::new(args.first().unwrap()); - let expected_out = dep.ancestors().nth(4).unwrap(); + let expected_out = dep.ancestors().nth(5).unwrap(); assert_eq!(&cfg.out, expected_out); } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index ed0155622c2..6c8cda18548 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -34,6 +34,10 @@ pub struct Finder { // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined + "aarch64-unknown-nto-qnx710_iosock", + "x86_64-pc-nto-qnx710_iosock", + "x86_64-pc-nto-qnx800", + "aarch64-unknown-nto-qnx800", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 482e23cd04c..d56f35f866c 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -28,6 +28,8 @@ use std::{env, fs, io, str}; use build_helper::ci::gha; use build_helper::exit; use termcolor::{ColorChoice, StandardStream, WriteColor}; +#[cfg(feature = "tracing")] +use tracing::{debug, instrument, span, trace}; use utils::build_stamp::BuildStamp; use utils::channel::GitInfo; @@ -537,14 +539,25 @@ impl Build { } /// Executes the entire build, as configured by the flags and configuration. + #[cfg_attr(feature = "tracing", instrument(level = "debug", name = "Build::build", skip_all))] pub fn build(&mut self) { + #[cfg(feature = "tracing")] + trace!("setting up job management"); unsafe { crate::utils::job::setup(self); } + #[cfg(feature = "tracing")] + trace!("downloading rustfmt early"); + // Download rustfmt early so that it can be used in rust-analyzer configs. let _ = &builder::Builder::new(self).initial_rustfmt(); + #[cfg(feature = "tracing")] + let hardcoded_span = + span!(tracing::Level::DEBUG, "handling hardcoded subcommands (Format, Suggest, Perf)") + .entered(); + // hardcoded subcommands match &self.config.cmd { Subcommand::Format { check, all } => { @@ -561,25 +574,50 @@ impl Build { Subcommand::Perf { .. } => { return core::build_steps::perf::perf(&builder::Builder::new(self)); } - _ => (), + _cmd => { + #[cfg(feature = "tracing")] + debug!(cmd = ?_cmd, "not a hardcoded subcommand; returning to normal handling"); + } } + #[cfg(feature = "tracing")] + drop(hardcoded_span); + #[cfg(feature = "tracing")] + debug!("handling subcommand normally"); + if !self.config.dry_run() { + #[cfg(feature = "tracing")] + let _real_run_span = span!(tracing::Level::DEBUG, "executing real run").entered(); + { + #[cfg(feature = "tracing")] + let _sanity_check_span = + span!(tracing::Level::DEBUG, "(1) executing dry-run sanity-check").entered(); + // We first do a dry-run. This is a sanity-check to ensure that // steps don't do anything expensive in the dry-run. self.config.dry_run = DryRun::SelfCheck; let builder = builder::Builder::new(self); builder.execute_cli(); } + + #[cfg(feature = "tracing")] + let _actual_run_span = + span!(tracing::Level::DEBUG, "(2) executing actual run").entered(); self.config.dry_run = DryRun::Disabled; let builder = builder::Builder::new(self); builder.execute_cli(); } else { + #[cfg(feature = "tracing")] + let _dry_run_span = span!(tracing::Level::DEBUG, "executing dry run").entered(); + let builder = builder::Builder::new(self); builder.execute_cli(); } + #[cfg(feature = "tracing")] + debug!("checking for postponed test failures from `test --no-fail-fast`"); + // Check for postponed failures from `test --no-fail-fast`. let failures = self.delayed_failures.borrow(); if failures.len() > 0 { diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 85d17c8fa50..a3eb781f147 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -335,4 +335,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "Some stamp names in the build artifacts may have changed slightly (e.g., from `llvm-finished-building` to `.llvm-stamp`).", }, + ChangeInfo { + change_id: 135729, + severity: ChangeSeverity::Info, + summary: "Change the compiler profile to default to rust.debug-assertions = true", + }, ]; diff --git a/src/bootstrap/src/utils/job.rs b/src/bootstrap/src/utils/job.rs index fb69d331d27..10efed130d6 100644 --- a/src/bootstrap/src/utils/job.rs +++ b/src/bootstrap/src/utils/job.rs @@ -42,9 +42,9 @@ pub unsafe fn setup(build: &mut crate::Build) { #[cfg(windows)] mod for_windows { use std::ffi::c_void; - use std::{env, io, mem}; + use std::{io, mem}; - use windows::Win32::Foundation::{CloseHandle, DUPLICATE_SAME_ACCESS, DuplicateHandle, HANDLE}; + use windows::Win32::Foundation::CloseHandle; use windows::Win32::System::Diagnostics::Debug::{ SEM_NOGPFAULTERRORBOX, SetErrorMode, THREAD_ERROR_MODE, }; @@ -53,9 +53,7 @@ mod for_windows { JOB_OBJECT_LIMIT_PRIORITY_CLASS, JOBOBJECT_EXTENDED_LIMIT_INFORMATION, JobObjectExtendedLimitInformation, SetInformationJobObject, }; - use windows::Win32::System::Threading::{ - BELOW_NORMAL_PRIORITY_CLASS, GetCurrentProcess, OpenProcess, PROCESS_DUP_HANDLE, - }; + use windows::Win32::System::Threading::{BELOW_NORMAL_PRIORITY_CLASS, GetCurrentProcess}; use windows::core::PCWSTR; use crate::Build; @@ -95,49 +93,8 @@ mod for_windows { return; } - // If we've got a parent process (e.g., the python script that called us) - // then move ownership of this job object up to them. That way if the python - // script is killed (e.g., via ctrl-c) then we'll all be torn down. - // - // If we don't have a parent (e.g., this was run directly) then we - // intentionally leak the job object handle. When our process exits + // Note: we intentionally leak the job object handle. When our process exits // (normally or abnormally) it will close the handle implicitly, causing all // processes in the job to be cleaned up. - let pid = match env::var("BOOTSTRAP_PARENT_ID") { - Ok(s) => s, - Err(..) => return, - }; - - let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() { - Some(parent) => parent, - _ => { - // If we get a null parent pointer here, it is possible that either - // we have an invalid pid or the parent process has been closed. - // Since the first case rarely happens - // (only when wrongly setting the environmental variable), - // it might be better to improve the experience of the second case - // when users have interrupted the parent process and we haven't finish - // duplicating the handle yet. - return; - } - }; - - let mut parent_handle = HANDLE::default(); - // If this fails, well at least we tried! An example of DuplicateHandle - // failing in the past has been when the wrong python2 package spawned this - // build system (e.g., the `python2` package in MSYS instead of - // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure - // mode" here is that we only clean everything up when the build system - // dies, not when the python parent does, so not too bad. - let _ = DuplicateHandle( - GetCurrentProcess(), - job, - parent, - &mut parent_handle, - 0, - false, - DUPLICATE_SAME_ACCESS, - ); - CloseHandle(parent).ok(); } } diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs index 2d0c66a8f33..538c33e9b15 100644 --- a/src/build_helper/src/metrics.rs +++ b/src/build_helper/src/metrics.rs @@ -16,6 +16,7 @@ pub struct JsonInvocation { // // This is necessary to easily correlate this invocation with logs or other data. pub start_time: u64, + #[serde(deserialize_with = "null_as_f64_nan")] pub duration_including_children_sec: f64, pub children: Vec<JsonNode>, } @@ -28,6 +29,7 @@ pub enum JsonNode { type_: String, debug_repr: String, + #[serde(deserialize_with = "null_as_f64_nan")] duration_excluding_children_sec: f64, system_stats: JsonStepSystemStats, @@ -88,5 +90,11 @@ pub struct JsonInvocationSystemStats { #[derive(Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub struct JsonStepSystemStats { + #[serde(deserialize_with = "null_as_f64_nan")] pub cpu_utilization_percent: f64, } + +fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result<f64, D::Error> { + use serde::Deserialize as _; + Option::<f64>::deserialize(d).map(|f| f.unwrap_or(f64::NAN)) +} diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index 03ec77f507e..6c9071b4191 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -56,9 +56,9 @@ ENV \ CFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ CXX_x86_64_fortanix_unknown_sgx=clang++-11 \ CXXFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \ - AR_i686_unknown_freebsd=i686-unknown-freebsd12-ar \ - CC_i686_unknown_freebsd=i686-unknown-freebsd12-clang \ - CXX_i686_unknown_freebsd=i686-unknown-freebsd12-clang++ \ + AR_i686_unknown_freebsd=i686-unknown-freebsd13-ar \ + CC_i686_unknown_freebsd=i686-unknown-freebsd13-clang \ + CXX_i686_unknown_freebsd=i686-unknown-freebsd13-clang++ \ CC_aarch64_unknown_uefi=clang-11 \ CXX_aarch64_unknown_uefi=clang++-11 \ CC_i686_unknown_uefi=clang-11 \ diff --git a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile index f42e6f770eb..fd0f5da8c49 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile @@ -29,9 +29,9 @@ COPY scripts/cmake.sh /scripts/ RUN /scripts/cmake.sh ENV \ - AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-ar \ - CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-clang \ - CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-clang++ + AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-ar \ + CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-clang \ + CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-clang++ ENV HOSTS=x86_64-unknown-freebsd diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index dde6fe7f6d0..3a396230582 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -34,6 +34,7 @@ RUN yum upgrade -y && \ python3 \ unzip \ wget \ + flex \ xz \ zlib-devel.i686 \ zlib-devel.x86_64 \ diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index d1bc0519bc1..d2697ac27ab 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -123,6 +123,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then build_args+=("--build-arg" "SCRIPT_ARG=${DOCKER_SCRIPT}") fi + GHCR_BUILDKIT_IMAGE="ghcr.io/rust-lang/buildkit:buildx-stable-1" # On non-CI jobs, we try to download a pre-built image from the rust-lang-ci # ghcr.io registry. If it is not possible, we fall back to building the image # locally. @@ -140,7 +141,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then elif [[ "$PR_CI_JOB" == "1" ]]; then # Enable a new Docker driver so that --cache-from works with a registry backend - docker buildx create --use --driver docker-container + # Use a custom image to avoid DockerHub rate limits + docker buildx create --use --driver docker-container \ + --driver-opt image=${GHCR_BUILDKIT_IMAGE} # Build the image using registry caching backend retry docker \ @@ -156,7 +159,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then --password-stdin # Enable a new Docker driver so that --cache-from/to works with a registry backend - docker buildx create --use --driver docker-container + # Use a custom image to avoid DockerHub rate limits + docker buildx create --use --driver docker-container \ + --driver-opt image=${GHCR_BUILDKIT_IMAGE} # Build the image using registry caching backend retry docker \ diff --git a/src/ci/docker/scripts/build-zstd.sh b/src/ci/docker/scripts/build-zstd.sh index a3d37ccc311..cffa7151e38 100755 --- a/src/ci/docker/scripts/build-zstd.sh +++ b/src/ci/docker/scripts/build-zstd.sh @@ -25,5 +25,11 @@ cd zstd-$ZSTD CFLAGS=-fPIC hide_output make -j$(nproc) VERBOSE=1 hide_output make install +# It doesn't seem to be possible to move destination directory +# of the `make install` above. We thus copy the built artifacts +# manually to our custom rustroot, so that it can be found through +# LD_LIBRARY_PATH. +cp /usr/local/lib/libzstd* /rustroot/lib64 + cd .. rm -rf zstd-$ZSTD diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh index 0d02636db91..b927658b4fd 100755 --- a/src/ci/docker/scripts/freebsd-toolchain.sh +++ b/src/ci/docker/scripts/freebsd-toolchain.sh @@ -5,8 +5,8 @@ set -eux arch=$1 binutils_version=2.40 -freebsd_version=12.3 -triple=$arch-unknown-freebsd12 +freebsd_version=13.4 +triple=$arch-unknown-freebsd13 sysroot=/usr/local/$triple hide_output() { @@ -59,7 +59,7 @@ done # Originally downloaded from: # URL=https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz -URL=https://ci-mirrors.rust-lang.org/rustc/2022-05-06-freebsd-${freebsd_version}-${freebsd_arch}-base.txz +URL=https://ci-mirrors.rust-lang.org/rustc/2024-09-13-freebsd-${freebsd_version}-${freebsd_arch}-base.txz curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}" # Clang can do cross-builds out of the box, if we give it the right diff --git a/src/ci/github-actions/ci.py b/src/ci/github-actions/ci.py index b7dac412dbe..c93766ef33a 100755 --- a/src/ci/github-actions/ci.py +++ b/src/ci/github-actions/ci.py @@ -249,7 +249,7 @@ def run_workflow_locally(job_data: Dict[str, Any], job_name: str, pr_jobs: bool) env = os.environ.copy() env.update(custom_env) - subprocess.run(args, env=env) + subprocess.run(args, env=env, check=True) def calculate_job_matrix(job_data: Dict[str, Any]): diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 799ea3e9ad2..7730d29d28f 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -35,6 +35,10 @@ runners: os: windows-2022 <<: *base-job + - &job-windows-25 + os: windows-2025 + <<: *base-job + - &job-windows-8c os: windows-2022-8core-32gb <<: *base-job @@ -44,8 +48,12 @@ runners: <<: *base-job - &job-aarch64-linux + # Free some disk space to avoid running out of space during the build. + free_disk: true os: ubuntu-22.04-arm + - &job-aarch64-linux-8c + os: ubuntu-22.04-arm64-8core-32gb envs: env-x86_64-apple-tests: &env-x86_64-apple-tests SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact @@ -138,7 +146,7 @@ auto: - name: dist-aarch64-linux env: CODEGEN_BACKENDS: llvm,cranelift - <<: *job-aarch64-linux + <<: *job-aarch64-linux-8c - name: dist-android <<: *job-linux-4c @@ -442,23 +450,29 @@ auto: # Windows Builders # ###################### - - name: x86_64-msvc + - name: x86_64-msvc-1 env: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler - SCRIPT: make ci-msvc - <<: *job-windows-8c + SCRIPT: make ci-msvc-py + <<: *job-windows-25 + + - name: x86_64-msvc-2 + env: + RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler + SCRIPT: make ci-msvc-ps1 + <<: *job-windows-25 # i686-msvc is split into two jobs to run tests in parallel. - name: i686-msvc-1 env: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-msvc-py-set1 + SCRIPT: make ci-msvc-py <<: *job-windows - name: i686-msvc-2 env: RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc - SCRIPT: make ci-msvc-ps1-set2 + SCRIPT: make ci-msvc-ps1 <<: *job-windows # x86_64-msvc-ext is split into multiple jobs to run tests in parallel. diff --git a/src/ci/scripts/free-disk-space.sh b/src/ci/scripts/free-disk-space.sh new file mode 100755 index 00000000000..4a7dad0090b --- /dev/null +++ b/src/ci/scripts/free-disk-space.sh @@ -0,0 +1,142 @@ +#!/bin/bash + +# Free disk space on Linux GitHub action runners +# Script inspired by https://github.com/jlumbroso/free-disk-space + +# print a line of the specified character +printSeparationLine() { + for ((i = 0; i < 80; i++)); do + printf "%s" "$1" + done + printf "\n" +} + +# compute available space +# REF: https://unix.stackexchange.com/a/42049/60849 +# REF: https://stackoverflow.com/a/450821/408734 +getAvailableSpace() { echo $(df -a | awk 'NR > 1 {avail+=$4} END {print avail}'); } + +# make Kb human readable (assume the input is Kb) +# REF: https://unix.stackexchange.com/a/44087/60849 +formatByteCount() { echo $(numfmt --to=iec-i --suffix=B --padding=7 $1'000'); } + +# macro to output saved space +printSavedSpace() { + # Disk space before the operation + local before=${1} + local title=${2:-} + + local after + after=$(getAvailableSpace) + local saved=$((after - before)) + + echo "" + printSeparationLine "*" + if [ -n "${title}" ]; then + echo "=> ${title}: Saved $(formatByteCount "$saved")" + else + echo "=> Saved $(formatByteCount "$saved")" + fi + printSeparationLine "*" + echo "" +} + +# macro to print output of df with caption +printDF() { + local caption=${1} + + printSeparationLine "=" + echo "${caption}" + echo "" + echo "$ df -h" + echo "" + df -h + printSeparationLine "=" +} + +removeDir() { + dir=${1} + + local before + before=$(getAvailableSpace) + + sudo rm -rf "$dir" || true + + printSavedSpace "$before" "$dir" +} + +execAndMeasureSpaceChange() { + local operation=${1} # Function to execute + local title=${2} + + local before + before=$(getAvailableSpace) + $operation + + printSavedSpace "$before" "$title" +} + +# Remove large packages +# REF: https://github.com/apache/flink/blob/master/tools/azure-pipelines/free_disk_space.sh +cleanPackages() { + sudo apt-get -qq remove -y --fix-missing \ + '^aspnetcore-.*' \ + '^dotnet-.*' \ + '^llvm-.*' \ + 'php.*' \ + '^mongodb-.*' \ + '^mysql-.*' \ + 'azure-cli' \ + 'google-chrome-stable' \ + 'firefox' \ + 'powershell' \ + 'mono-devel' \ + 'libgl1-mesa-dri' \ + 'google-cloud-sdk' \ + 'google-cloud-cli' + + sudo apt-get autoremove -y || echo "::warning::The command [sudo apt-get autoremove -y] failed" + sudo apt-get clean || echo "::warning::The command [sudo apt-get clean] failed failed" +} + +# Remove Docker images +cleanDocker() { + echo "Removing the following docker images:" + sudo docker image ls + echo "Removing docker images..." + sudo docker image prune --all --force || true +} + +# Remove Swap storage +cleanSwap() { + sudo swapoff -a || true + sudo rm -rf /mnt/swapfile || true + free -h +} + +# Display initial disk space stats + +AVAILABLE_INITIAL=$(getAvailableSpace) + +printDF "BEFORE CLEAN-UP:" +echo "" + +removeDir /usr/local/lib/android +removeDir /usr/share/dotnet + +# Haskell runtime +removeDir /opt/ghc +removeDir /usr/local/.ghcup + +execAndMeasureSpaceChange cleanPackages "Large misc. packages" +execAndMeasureSpaceChange cleanDocker "Docker images" +execAndMeasureSpaceChange cleanSwap "Swap storage" + +# Output saved space statistic +echo "" +printDF "AFTER CLEAN-UP:" + +echo "" +echo "" + +printSavedSpace "$AVAILABLE_INITIAL" "Total saved" diff --git a/src/doc/book b/src/doc/book -Subproject 8a0eee28f769387e543882352b12d956aa1b7c3 +Subproject 82a4a49789bc96db1a1b2a210b4c5ed7c9ef0c0 diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index 576bbcea965..8983915d78a 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -18,8 +18,8 @@ use std::path::Path; use rustc_ast_pretty::pprust::item_to_string; use rustc_data_structures::sync::Lrc; -use rustc_driver::{Compilation, RunCompiler}; -use rustc_interface::interface::Compiler; +use rustc_driver::{Compilation, run_compiler}; +use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; struct MyFileLoader; @@ -51,6 +51,10 @@ fn main() { struct MyCallbacks; impl rustc_driver::Callbacks for MyCallbacks { + fn config(&mut self, config: &mut Config) { + config.file_loader = Some(Box::new(MyFileLoader)); + } + fn after_crate_root_parsing( &mut self, _compiler: &Compiler, @@ -83,10 +87,5 @@ impl rustc_driver::Callbacks for MyCallbacks { } fn main() { - match RunCompiler::new(&["main.rs".to_string()], &mut MyCallbacks) { - mut compiler => { - compiler.set_file_loader(Some(Box::new(MyFileLoader))); - compiler.run(); - } - } + run_compiler(&["main.rs".to_string()], &mut MyCallbacks); } diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index 90a85d5db21..c894b60444a 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -18,8 +18,8 @@ use std::path::Path; use rustc_ast_pretty::pprust::item_to_string; use rustc_data_structures::sync::Lrc; -use rustc_driver::{Compilation, RunCompiler}; -use rustc_interface::interface::Compiler; +use rustc_driver::{Compilation, run_compiler}; +use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; struct MyFileLoader; @@ -51,6 +51,10 @@ fn main() { struct MyCallbacks; impl rustc_driver::Callbacks for MyCallbacks { + fn config(&mut self, config: &mut Config) { + config.file_loader = Some(Box::new(MyFileLoader)); + } + fn after_crate_root_parsing( &mut self, _compiler: &Compiler, @@ -90,10 +94,5 @@ impl rustc_driver::Callbacks for MyCallbacks { } fn main() { - match RunCompiler::new(&["main.rs".to_string()], &mut MyCallbacks) { - mut compiler => { - compiler.set_file_loader(Some(Box::new(MyFileLoader))); - compiler.run(); - } - } + run_compiler(&["main.rs".to_string()], &mut MyCallbacks); } diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md index 972b4a8fb0e..3f907e85dd6 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap.md @@ -1,6 +1,6 @@ # Debugging bootstrap -> FIXME: this page could be expanded +> FIXME: this section should be expanded ## `tracing` in bootstrap @@ -10,21 +10,69 @@ Bootstrap has conditional [`tracing`][tracing] setup to provide structured loggi ### Enabling `tracing` output -Bootstrap will conditionally enable `tracing` output if the `BOOTSTRAP_TRACING` env var is set. +Bootstrap will conditionally build `tracing` support and enable `tracing` output if the `BOOTSTRAP_TRACING` env var is set. -Example usage: +#### Basic usage + +Example basic usage[^just-trace]: + +[^just-trace]: It is not recommend to use *just* `BOOTSTRAP_TRACING=TRACE` because that will dump *everything* at `TRACE` level, including logs intentionally gated behind custom targets as they are too verbose even for `TRACE` level by default. ```bash -$ BOOTSTRAP_TRACING=TRACE ./x build library --stage 1 +$ BOOTSTRAP_TRACING=bootstrap=TRACE ./x build library --stage 1 +``` + +Example output[^unstable]: + +``` +$ BOOTSTRAP_TRACING=bootstrap=TRACE ./x check src/bootstrap/ +Building bootstrap + Compiling bootstrap v0.0.0 (/home/joe/repos/rust/src/bootstrap) + Finished `dev` profile [unoptimized] target(s) in 2.74s + DEBUG bootstrap parsing flags + bootstrap::core::config::flags::Flags::parse args=["check", "src/bootstrap/"] + DEBUG bootstrap parsing config based on flags + DEBUG bootstrap creating new build based on config + bootstrap::Build::build + TRACE bootstrap setting up job management + TRACE bootstrap downloading rustfmt early + bootstrap::handling hardcoded subcommands (Format, Suggest, Perf) + DEBUG bootstrap not a hardcoded subcommand; returning to normal handling, cmd=Check { all_targets: false } + DEBUG bootstrap handling subcommand normally + bootstrap::executing real run + bootstrap::(1) executing dry-run sanity-check + bootstrap::(2) executing actual run +Checking stage0 library artifacts (x86_64-unknown-linux-gnu) + Finished `release` profile [optimized + debuginfo] target(s) in 0.04s +Checking stage0 compiler artifacts {rustc-main, rustc_abi, rustc_arena, rustc_ast, rustc_ast_ir, rustc_ast_lowering, rustc_ast_passes, rustc_ast_pretty, rustc_attr_data_structures, rustc_attr_parsing, rustc_baked_icu_data, rustc_borrowck, rustc_builtin_macros, rustc_codegen_llvm, rustc_codegen_ssa, rustc_const_eval, rustc_data_structures, rustc_driver, rustc_driver_impl, rustc_error_codes, rustc_error_messages, rustc_errors, rustc_expand, rustc_feature, rustc_fluent_macro, rustc_fs_util, rustc_graphviz, rustc_hir, rustc_hir_analysis, rustc_hir_pretty, rustc_hir_typeck, rustc_incremental, rustc_index, rustc_index_macros, rustc_infer, rustc_interface, rustc_lexer, rustc_lint, rustc_lint_defs, rustc_llvm, rustc_log, rustc_macros, rustc_metadata, rustc_middle, rustc_mir_build, rustc_mir_dataflow, rustc_mir_transform, rustc_monomorphize, rustc_next_trait_solver, rustc_parse, rustc_parse_format, rustc_passes, rustc_pattern_analysis, rustc_privacy, rustc_query_impl, rustc_query_system, rustc_resolve, rustc_sanitizers, rustc_serialize, rustc_session, rustc_smir, rustc_span, rustc_symbol_mangling, rustc_target, rustc_trait_selection, rustc_traits, rustc_transmute, rustc_ty_utils, rustc_type_ir, rustc_type_ir_macros, stable_mir} (x86_64-unknown-linux-gnu) + Finished `release` profile [optimized + debuginfo] target(s) in 0.23s +Checking stage0 bootstrap artifacts (x86_64-unknown-linux-gnu) + Checking bootstrap v0.0.0 (/home/joe/repos/rust/src/bootstrap) + Finished `release` profile [optimized + debuginfo] target(s) in 0.64s + DEBUG bootstrap checking for postponed test failures from `test --no-fail-fast` +Build completed successfully in 0:00:08 ``` -Example output[^experimental]: +#### Controlling log output + +The env var `BOOTSTRAP_TRACING` accepts a [`tracing` env-filter][tracing-env-filter]. + +There are two orthogonal ways to control which kind of logs you want: - +1. You can specify the log **level**, e.g. `DEBUG` or `TRACE`. +2. You can also control the log **target**, e.g. `bootstrap` or `bootstrap::core::config` vs custom targets like `CONFIG_HANDLING`. + - Custom targets are used to limit what is output when `BOOTSTRAP_TRACING=bootstrap=TRACE` is used, as they can be too verbose even for `TRACE` level by default. Currently used custom targets: + - `CONFIG_HANDLING` -[^experimental]: This shows what's *possible* with the infra in an experimental implementation. +The `TRACE` filter will enable *all* `trace` level or less verbose level tracing output. -The env var `BOOTSTRAP_TRACING` accepts a [`tracing` env-filter][tracing-env-filter]. The `TRACE` filter will enable *all* `trace` level or less verbose level tracing output. +You can of course combine them (custom target logs are typically gated behind `TRACE` log level additionally): + +```bash +$ BOOTSTRAP_TRACING=CONFIG_HANDLING=TRACE ./x build library --stage 1 +``` + +[^unstable]: This output is always subject to further changes. [tracing-env-filter]: https://docs.rs/tracing-subscriber/0.3.19/tracing_subscriber/filter/struct.EnvFilter.html @@ -73,28 +121,6 @@ For `#[instrument]`, it's recommended to: - Explicitly pick an instrumentation name via `name = ".."` to distinguish between e.g. `run` of different steps. - Take care to not cause diverging behavior via tracing, e.g. building extra things only when tracing infra is enabled. -### Enabling `tracing` bootstrap feature in rust-analyzer +### rust-analyzer integration? -You can adjust your `settings.json`'s `rust-analyzer.check.overrideCommand` and `rust-analyzer.cargo.buildScripts.overrideCommand` if you want to also enable `logging` cargo feature by default in your editor. This is mostly useful if you want proper r-a completions and such when working on bootstrap itself. - -```json -"rust-analyzer.check.overrideCommand": [ - "BOOTSTRAP_TRACING=1", // <- BOOTSTRAP_TRACING=1 won't enable tracing filter, but it will activate bootstrap's `tracing` feature - "python3", - "x.py", - "check", - "--json-output", - "--build-dir=build-rust-analyzer" -], -``` - -```json -"rust-analyzer.cargo.buildScripts.overrideCommand": [ - "BOOTSTRAP_TRACING=1", // <- note this - "python3", - "x.py", - "check", - "--json-output", - "--build-dir=build-rust-analyzer" -], -``` +Unfortunately, because bootstrap is a `rust-analyzer.linkedProjects`, you can't ask r-a to check/build bootstrap itself with `tracing` feature enabled to get relevant completions, due to lack of support as described in <https://github.com/rust-lang/rust-analyzer/issues/8521>. diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap/tracing-output-example.png b/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap/tracing-output-example.png deleted file mode 100644 index 745aec50d4a..00000000000 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/debugging-bootstrap/tracing-output-example.png +++ /dev/null Binary files differdiff --git a/src/doc/rustc-dev-guide/src/conventions.md b/src/doc/rustc-dev-guide/src/conventions.md index 37af8121cd1..4010e90821f 100644 --- a/src/doc/rustc-dev-guide/src/conventions.md +++ b/src/doc/rustc-dev-guide/src/conventions.md @@ -1,4 +1,4 @@ -This file offers some tips on the coding conventions for rustc. This +This file offers some tips on the coding conventions for rustc. This chapter covers [formatting](#formatting), [coding for correctness](#cc), [using crates from crates.io](#cio), and some tips on [structuring your PR for easy review](#er). @@ -25,6 +25,7 @@ pass the <!-- date-check: nov 2022 --> `--edition=2021` argument yourself when c `rustfmt` directly. [fmt]: https://github.com/rust-dev-tools/fmt-rfcs + [`rustfmt`]:https://github.com/rust-lang/rustfmt ## Formatting C++ code @@ -40,6 +41,26 @@ When modifying that code, use this command to format it: This uses a pinned version of `clang-format`, to avoid relying on the local environment. +## Formatting and linting Python code + +The Rust repository contains quite a lof of Python code. We try to keep +it both linted and formatted by the [ruff][ruff] tool. + +When modifying Python code, use this command to format it: +```sh +./x test tidy --extra-checks=py:fmt --bless +``` + +and the following command to run lints: +```sh +./x test tidy --extra-checks=py:lint +``` + +This uses a pinned version of `ruff`, to avoid relying on the local +environment. + +[ruff]: https://github.com/astral-sh/ruff + <a id="copyright"></a> <!-- REUSE-IgnoreStart --> @@ -84,7 +105,7 @@ Using `_` in a match is convenient, but it means that when new variants are added to the enum, they may not get handled correctly. Ask yourself: if a new variant were added to this enum, what's the chance that it would want to use the `_` code, versus having some -other treatment? Unless the answer is "low", then prefer an +other treatment? Unless the answer is "low", then prefer an exhaustive match. (The same advice applies to `if let` and `while let`, which are effectively tests for a single variant.) @@ -124,7 +145,7 @@ See the [crates.io dependencies][crates] section. # How to structure your PR How you prepare the commits in your PR can make a big difference for the -reviewer. Here are some tips. +reviewer. Here are some tips. **Isolate "pure refactorings" into their own commit.** For example, if you rename a method, then put that rename into its own commit, along @@ -165,4 +186,5 @@ to the compiler. crate-related, often the spelling is changed to `krate`. [tcx]: ./ty.md + [crates]: ./crates-io.md diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md index a6234dc129f..40500e6bc7a 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md @@ -6,7 +6,7 @@ The [`rustc_driver`] is essentially `rustc`'s `main` function. It acts as the glue for running the various phases of the compiler in the correct order, using the interface defined in the [`rustc_interface`] crate. Where possible, using [`rustc_driver`] rather than [`rustc_interface`] is recommended. -The main entry point of [`rustc_driver`] is [`rustc_driver::RunCompiler`][rd_rc]. +The main entry point of [`rustc_driver`] is [`rustc_driver::run_compiler`][rd_rc]. This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`][cb] and a couple of other optional options. [`Callbacks`][cb] is a `trait` that allows for custom compiler configuration, as well as allowing custom code to run after different phases of the compilation. @@ -40,7 +40,7 @@ specifically [`rustc_driver_impl::run_compiler`][rdi_rc] [cb]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html [example]: https://github.com/rust-lang/rustc-dev-guide/blob/master/examples/rustc-interface-example.rs [i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html -[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/struct.RunCompiler.html +[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html [rdi_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html [stupid-stats]: https://github.com/nrc/stupid-stats [`nightly-rustc`]: https://doc.rust-lang.org/nightly/nightly-rustc/ diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md index 1bfe911c900..230925252ba 100644 --- a/src/doc/rustc-dev-guide/src/stability.md +++ b/src/doc/rustc-dev-guide/src/stability.md @@ -34,7 +34,8 @@ Previously, due to a [rustc bug], stable items inside unstable modules were available to stable code in that location. As of <!-- date-check --> September 2024, items with [accidentally stabilized paths] are marked with the `#[rustc_allowed_through_unstable_modules]` attribute -to prevent code dependent on those paths from breaking. +to prevent code dependent on those paths from breaking. Do *not* add this attribute +to any more items unless that is needed to avoid breaking changes. The `unstable` attribute may also have the `soft` value, which makes it a future-incompatible deny-by-default lint instead of a hard error. This is used diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 33304962a39..9e0f8f9c279 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -94,7 +94,7 @@ for more details. | Directive | Explanation | Supported test suites | Possible values | |-----------------------------------|--------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|-----------------------------------------------------------------------------------------| | `check-run-results` | Check run test binary `run-{pass,fail}` output snapshot | `ui`, `crashes`, `incremental` if `run-pass` | N/A | -| `error-pattern` | Check that output contains a specific string | `ui`, `crashes`, `incremental` if `run-pass` | String | +| `error-pattern` | Check that output contains a specific string | `ui`, `crashes`, `incremental` if `run-pass` | String | | `regex-error-pattern` | Check that output contains a regex pattern | `ui`, `crashes`, `incremental` if `run-pass` | Regex | | `check-stdout` | Check `stdout` against `error-pattern`s from running test binary[^check_stdout] | `ui`, `crashes`, `incremental` | N/A | | `normalize-stderr-32bit` | Normalize actual stderr (for 32-bit platforms) with a rule `"<raw>" -> "<normalized>"` before comparing against snapshot | `ui`, `incremental` | `"<RAW>" -> "<NORMALIZED>"`, `<RAW>`/`<NORMALIZED>` is regex capture and replace syntax | @@ -152,6 +152,8 @@ Some examples of `X` in `ignore-X` or `only-X`: `compare-mode-split-dwarf`, `compare-mode-split-dwarf-single` - The two different test modes used by coverage tests: `ignore-coverage-map`, `ignore-coverage-run` +- When testing a dist toolchain: `dist` + - This needs to be enabled with `COMPILETEST_ENABLE_DIST_TESTS=1` The following directives will check rustc build settings and target settings: @@ -174,6 +176,7 @@ settings: - `needs-rust-lld` — ignores if the rust lld support is not enabled (`rust.lld = true` in `config.toml`) - `needs-threads` — ignores if the target does not have threading support +- `needs-subprocess` — ignores if the target does not have subprocess support - `needs-symlink` — ignores if the target does not support symlinks. This can be the case on Windows if the developer did not enable privileged symlink permissions. diff --git a/src/doc/rustc/src/check-cfg/cargo-specifics.md b/src/doc/rustc/src/check-cfg/cargo-specifics.md index bd4bebbc874..371bbd26e94 100644 --- a/src/doc/rustc/src/check-cfg/cargo-specifics.md +++ b/src/doc/rustc/src/check-cfg/cargo-specifics.md @@ -13,6 +13,8 @@ the `unexpected_cfgs` lint and `--check-cfg` flag. It is not intended to provide individual details, for that refer to the [`--check-cfg` documentation](../check-cfg.md) and to the [Cargo book](../../cargo/index.html). +> The full list of well known cfgs (aka builtins) can be found under [Checking conditional configurations / Well known names and values](../check-cfg.md#well-known-names-and-values). + ## Cargo feature *See the [`[features]` section in the Cargo book][cargo-features] for more details.* diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index deeabd810d3..8227dfa043e 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -259,7 +259,10 @@ target | std | host | notes `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) [`aarch64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD [`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS | -[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS | +[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | +[`aarch64-unknown-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS with new network stack (io-sock) | +[`aarch64-unknown-nto-qnx800`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 8.0 RTOS | +[`aarch64-unknown-nuttx`](platform-support/nuttx.md) | ✓ | | ARM64 with NuttX [`aarch64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | ARM64 OpenBSD [`aarch64-unknown-redox`](platform-support/redox.md) | ✓ | | ARM64 Redox OS [`aarch64-unknown-teeos`](platform-support/aarch64-unknown-teeos.md) | ? | | ARM64 TEEOS | @@ -295,6 +298,8 @@ target | std | host | notes [`armv7k-apple-watchos`](platform-support/apple-watchos.md) | ✓ | | Armv7-A Apple WatchOS [`armv7s-apple-ios`](platform-support/apple-ios.md) | ✓ | | Armv7-A Apple-A6 Apple iOS [`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare Armv8-R, hardfloat +[`armv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX +[`armv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX, hardfloat `avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) @@ -364,21 +369,21 @@ target | std | host | notes [`riscv32im-risc0-zkvm-elf`](platform-support/riscv32im-risc0-zkvm-elf.md) | ? | | RISC Zero's zero-knowledge Virtual Machine (RV32IM ISA) [`riscv32ima-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32IMA ISA) [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF -[`riscv32imac-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 32bit with NuttX +[`riscv32imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 32bit with NuttX [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? | | RISC-V Xous (RV32IMAC ISA) [`riscv32imafc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF -[`riscv32imafc-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 32bit with NuttX +[`riscv32imafc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 32bit with NuttX [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF -[`riscv32imc-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 32bit with NuttX +[`riscv32imc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 32bit with NuttX [`riscv64-linux-android`](platform-support/android.md) | ? | | RISC-V 64-bit Android [`riscv64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | `riscv64gc-unknown-freebsd` | ? | | RISC-V FreeBSD `riscv64gc-unknown-fuchsia` | ? | | RISC-V Fuchsia [`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD -[`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 64bit with NuttX +[`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 -[`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 64bit with NuttX +[`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX [`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | ✓ | | S390x Linux (kernel 3.2, musl 1.2.3) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | | Bare 32-bit SPARC V7+ @@ -386,20 +391,24 @@ target | std | host | notes [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64 [`thumbv4t-none-eabi`](platform-support/armv4t-none-eabi.md) | * | | Thumb-mode Bare Armv4T [`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare Armv5TE -[`thumbv6m-nuttx-eabi`](platform-support/nuttx.md) | * | | ARMv6M with NuttX +[`thumbv6m-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv6M with NuttX `thumbv7a-pc-windows-msvc` | | | [`thumbv7a-uwp-windows-msvc`](platform-support/uwp-windows-msvc.md) | | | -[`thumbv7em-nuttx-eabi`](platform-support/nuttx.md) | * | | ARMv7EM with NuttX -[`thumbv7em-nuttx-eabihf`](platform-support/nuttx.md) | * | | ARMv7EM with NuttX, hardfloat -[`thumbv7m-nuttx-eabi`](platform-support/nuttx.md) | * | | ARMv7M with NuttX +[`thumbv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX +[`thumbv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX, hardfloat +[`thumbv7em-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7EM with NuttX +[`thumbv7em-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7EM with NuttX, hardfloat +[`thumbv7m-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7M with NuttX `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.3 -[`thumbv8m.base-nuttx-eabi`](platform-support/nuttx.md) | * | | ARMv8M Baseline with NuttX -[`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | * | | ARMv8M Mainline with NuttX -[`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | * | | ARMv8M Mainline with NuttX, hardfloat +[`thumbv8m.base-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Baseline with NuttX +[`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX +[`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX, hardfloat [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ | | x86 64-bit tvOS [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator -[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS | +[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with default network stack (io-pkt) | +[`x86_64-pc-nto-qnx710_iosock`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS with new network stack (io-sock) | +[`x86_64-pc-nto-qnx800`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 8.0 RTOS | [`x86_64-unikraft-linux-musl`](platform-support/unikraft-linux-musl.md) | ✓ | | 64-bit Unikraft with musl 1.2.3 `x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku diff --git a/src/doc/rustc/src/platform-support/nto-qnx.md b/src/doc/rustc/src/platform-support/nto-qnx.md index 1c240d1255a..339741f1472 100644 --- a/src/doc/rustc/src/platform-support/nto-qnx.md +++ b/src/doc/rustc/src/platform-support/nto-qnx.md @@ -2,11 +2,13 @@ **Tier: 3** -[QNX®][BlackBerry] Neutrino (nto) Real-time operating system. -The support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit] -and [Blackberry QNX][BlackBerry]. +The [QNX®][qnx.com] Neutrino (nto) Real-time operating system. Known as QNX OS +from version 8 onwards. -[BlackBerry]: https://blackberry.qnx.com +This support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit] +and [QNX][qnx.com]. + +[qnx.com]: https://blackberry.qnx.com [Elektrobit]: https://www.elektrobit.com ## Target maintainers @@ -18,21 +20,29 @@ and [Blackberry QNX][BlackBerry]. ## Requirements -Currently, the following QNX Neutrino versions and compilation targets are supported: +Currently, the following QNX versions and compilation targets are supported: + +| Target Tuple | QNX Version | Target Architecture | Full support | `no_std` support | +| ----------------------------------- | ----------------------------- | ------------------- | :----------: | :--------------: | +| `aarch64-unknown-nto-qnx800` | QNX OS 8.0 | AArch64 | ? | ✓ | +| `x86_64-pc-nto-qnx800` | QNX OS 8.0 | x86_64 | ? | ✓ | +| `aarch64-unknown-nto-qnx710` | QNX Neutrino 7.1 with io-pkt | AArch64 | ✓ | ✓ | +| `x86_64-pc-nto-qnx710` | QNX Neutrino 7.1 with io-pkt | x86_64 | ✓ | ✓ | +| `aarch64-unknown-nto-qnx710_iosock` | QNX Neutrino 7.1 with io-sock | AArch64 | ? | ✓ | +| `x86_64-pc-nto-qnx710_iosock` | QNX Neutrino 7.1 with io-sock | x86_64 | ? | ✓ | +| `aarch64-unknown-nto-qnx700` | QNX Neutrino 7.0 | AArch64 | ? | ✓ | +| `i586-pc-nto-qnx700` | QNX Neutrino 7.0 | x86 | | ✓ | -| QNX Neutrino Version | Target Architecture | Full support | `no_std` support | -|----------------------|---------------------|:------------:|:----------------:| -| 7.1 | AArch64 | ✓ | ✓ | -| 7.1 | x86_64 | ✓ | ✓ | -| 7.0 | AArch64 | ? | ✓ | -| 7.0 | x86 | | ✓ | +On QNX Neutrino 7.0 and 7.1, `io-pkt` is used as network stack by default. +QNX Neutrino 7.1 includes the optional network stack `io-sock`. +QNX OS 8.0 always uses `io-sock`. QNX OS 8.0 support is currently work in progress. -Adding other architectures that are supported by QNX Neutrino is possible. +Adding other architectures that are supported by QNX is possible. -In the table above, 'full support' indicates support for building Rust applications with the full standard library. -'`no_std` support' indicates that only `core` and `alloc` are available. +In the table above, 'full support' indicates support for building Rust applications with the full standard library. A '?' means that support is in-progress. +'`no_std` support' is for building `#![no_std]` applications where only `core` and `alloc` are available. -For building or using the Rust toolchain for QNX Neutrino, the +For building or using the Rust toolchain for QNX, the [QNX Software Development Platform (SDP)](https://blackberry.qnx.com/en/products/foundation-software/qnx-software-development-platform) must be installed and initialized. Initialization is usually done by sourcing `qnxsdp-env.sh` (this will be installed as part of the SDP, see also installation instruction provided with the SDP). @@ -78,7 +88,7 @@ extern "C" { } #[no_mangle] -pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { const HELLO: &'static str = "Hello World, the answer is %d\n\0"; unsafe { printf(HELLO.as_ptr() as *const _, 42); @@ -98,52 +108,73 @@ fn panic(_panic: &PanicInfo<'_>) -> ! { pub extern "C" fn rust_eh_personality() {} ``` -The QNX Neutrino support of Rust has been tested with QNX Neutrino 7.0 and 7.1. +The QNX support in Rust has been tested with QNX Neutrino 7.0 and 7.1. Support for QNX OS 8.0 is a work in progress. There are no further known requirements. ## Conditional compilation -For conditional compilation, following QNX Neutrino specific attributes are defined: +For conditional compilation, following QNX specific attributes are defined: - `target_os` = `"nto"` -- `target_env` = `"nto71"` (for QNX Neutrino 7.1) +- `target_env` = `"nto71"` (for QNX Neutrino 7.1 with "classic" network stack "io_pkt") +- `target_env` = `"nto71_iosock"` (for QNX Neutrino 7.1 with network stack "io_sock") - `target_env` = `"nto70"` (for QNX Neutrino 7.0) +- `target_env` = `"nto80"` (for QNX OS 8.0) ## Building the target 1. Create a `config.toml` -Example content: + Example content: -```toml -profile = "compiler" -change-id = 115898 -``` + ```toml + profile = "compiler" + change-id = 999999 + ``` -2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets) +2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host -Compiling the Rust toolchain requires the same environment variables used for compiling C binaries. -Refer to the [QNX developer manual](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.prog/topic/devel_OS_version.html). + Compiling the Rust toolchain requires the same environment variables used for compiling C binaries. + Refer to the [QNX developer manual](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.prog/topic/devel_OS_version.html). -To compile for QNX Neutrino (aarch64 and x86_64) and Linux (x86_64): + To compile for QNX, environment variables must be set to use the correct tools and compiler switches: -```bash -export build_env=' - CC_aarch64-unknown-nto-qnx710=qcc - CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx - CXX_aarch64-unknown-nto-qnx710=qcc - AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar - CC_x86_64-pc-nto-qnx710=qcc - CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx - CXX_x86_64-pc-nto-qnx710=qcc - AR_x86_64_pc_nto_qnx710=ntox86_64-ar' + - `CC_<target>=qcc` + - `CFLAGS_<target>=<nto_cflag>` + - `CXX_<target>=qcc` + - `AR_<target>=<nto_ar>` -env $build_env \ - ./x.py build \ - --target aarch64-unknown-nto-qnx710,x86_64-pc-nto-qnx710,x86_64-unknown-linux-gnu \ - rustc library/core library/alloc library/std -``` + With: + + - `<target>` target triplet using underscores instead of hyphens, e.g. `aarch64_unknown_nto_qnx710` + - `<nto_cflag>` + + - `-Vgcc_ntox86_cxx` for x86 (32 bit) + - `-Vgcc_ntox86_64_cxx` for x86_64 (64 bit) + - `-Vgcc_ntoaarch64le_cxx` for Aarch64 (64 bit) + + - `<nto_ar>` + + - `ntox86-ar` for x86 (32 bit) + - `ntox86_64-ar` for x86_64 (64 bit) + - `ntoaarch64-ar` for Aarch64 (64 bit) + + Example to build the Rust toolchain including a standard library for x86_64-linux-gnu and Aarch64-QNX-7.1: + + ```bash + export build_env=' + CC_aarch64_unknown_nto_qnx710=qcc + CFLAGS_aarch64_unknown_nto_qnx710=-Vgcc_ntoaarch64le_cxx + CXX_aarch64_unknown_nto_qnx710=qcc + AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar + ' + + env $build_env \ + ./x.py build \ + --target x86_64-unknown-linux-gnu,aarch64-unknown-nto-qnx710 \ + rustc library/core library/alloc library/std + ``` ## Running the Rust test suite @@ -153,19 +184,11 @@ addition of the TEST_DEVICE_ADDR environment variable. The TEST_DEVICE_ADDR variable controls the remote runner and should point to the target, despite localhost being shown in the following example. Note that some tests are failing which is why they are currently excluded by the target maintainers which can be seen in the following example. -To run all tests on a x86_64 QNX Neutrino target: +To run all tests on a x86_64 QNX Neutrino 7.1 target: ```bash export TEST_DEVICE_ADDR="localhost:12345" # must address the test target, can be a SSH tunnel -export build_env=' - CC_aarch64-unknown-nto-qnx710=qcc - CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx - CXX_aarch64-unknown-nto-qnx710=qcc - AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar - CC_x86_64-pc-nto-qnx710=qcc - CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx - CXX_x86_64-pc-nto-qnx710=qcc - AR_x86_64_pc_nto_qnx710=ntox86_64-ar' +export build_env=<see above> # Disable tests that only work on the host or don't make sense for this target. # See also: @@ -195,7 +218,7 @@ or build your own copy of `core` by using `build-std` or similar. ## Testing -Compiled executables can run directly on QNX Neutrino. +Compiled executables can run directly on QNX. ### Rust std library test suite diff --git a/src/doc/rustc/src/platform-support/nuttx.md b/src/doc/rustc/src/platform-support/nuttx.md index 433a092aab2..f76fe0887b5 100644 --- a/src/doc/rustc/src/platform-support/nuttx.md +++ b/src/doc/rustc/src/platform-support/nuttx.md @@ -20,8 +20,13 @@ The target name follow this format: `ARCH[-VENDOR]-nuttx-ABI`, where `ARCH` is t The following target names are defined: -- `thumbv6m-nuttx-eal` -- `thumbv7m-nuttx-eal` +- `aarch64-unknown-nuttx` +- `armv7a-nuttx-eabi` +- `armv7a-nuttx-eabihf` +- `thumbv6m-nuttx-eabi` +- `thumbv7a-nuttx-eabi` +- `thumbv7a-nuttx-eabihf` +- `thumbv7m-nuttx-eabi` - `thumbv7em-nuttx-eabi` - `thumbv7em-nuttx-eabihf` - `thumbv8m.base-nuttx-eabi` diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md index 7a9cd4b522b..d364852b1c1 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md @@ -118,7 +118,7 @@ This target is not extensively tested in CI for the rust-lang/rust repository. I can be tested locally, for example, with: ```sh -./x.py test --target wasm32-unknown-emscripten --skip src/tools/linkchecker +EMCC_CFLAGS="-s MAXIMUM_MEMORY=2GB" ./x.py test --target wasm32-unknown-emscripten --skip src/tools/linkchecker ``` To run these tests, both `emcc` and `node` need to be in your `$PATH`. You can diff --git a/src/doc/rustc/src/tests/index.md b/src/doc/rustc/src/tests/index.md index 32baed9c944..d2026513d2f 100644 --- a/src/doc/rustc/src/tests/index.md +++ b/src/doc/rustc/src/tests/index.md @@ -268,6 +268,8 @@ Controls the format of the output. Valid options: Writes the results of the tests to the given file. +This option is deprecated. + #### `--report-time` ⚠️ 🚧 This option is [unstable](#unstable-options), and requires the `-Z diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 32b882e763d..1122bbc5a87 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -46,14 +46,15 @@ allocation. A freestanding program that uses the `Box` sugar for dynamic allocations via `malloc` and `free`: ```rust,ignore (libc-is-finicky) -#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] +#![feature(lang_items, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)] #![allow(internal_features)] #![no_std] +#![no_main] extern crate libc; extern crate unwind; -use core::ffi::c_void; +use core::ffi::{c_int, c_void}; use core::intrinsics; use core::panic::PanicInfo; use core::ptr::NonNull; @@ -91,8 +92,8 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { p } -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int { let _x = Box::new(1); 0 diff --git a/src/doc/unstable-book/src/language-features/start.md b/src/doc/unstable-book/src/language-features/start.md deleted file mode 100644 index 09e4875a2e4..00000000000 --- a/src/doc/unstable-book/src/language-features/start.md +++ /dev/null @@ -1,59 +0,0 @@ -# `start` - -The tracking issue for this feature is: [#29633] - -[#29633]: https://github.com/rust-lang/rust/issues/29633 - ------------------------- - -Allows you to mark a function as the entry point of the executable, which is -necessary in `#![no_std]` environments. - -The function marked `#[start]` is passed the command line parameters in the same -format as the C main function (aside from the integer types being used). -It has to be non-generic and have the following signature: - -```rust,ignore (only-for-syntax-highlight) -# let _: -fn(isize, *const *const u8) -> isize -# ; -``` - -This feature should not be confused with the `start` *lang item* which is -defined by the `std` crate and is written `#[lang = "start"]`. - -## Usage together with the `std` crate - -`#[start]` can be used in combination with the `std` crate, in which case the -normal `main` function (which would get called from the `std` crate) won't be -used as an entry point. -The initialization code in `std` will be skipped this way. - -Example: - -```rust -#![feature(start)] - -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - 0 -} -``` - -Unwinding the stack past the `#[start]` function is currently considered -Undefined Behavior (for any unwinding implementation): - -```rust,ignore (UB) -#![feature(start)] - -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - std::panic::catch_unwind(|| { - panic!(); // panic safely gets caught or safely aborts execution - }); - - panic!(); // UB! - - 0 -} -``` diff --git a/src/etc/dec2flt_table.py b/src/etc/dec2flt_table.py index 791186de9c1..ecfdacc1f31 100755 --- a/src/etc/dec2flt_table.py +++ b/src/etc/dec2flt_table.py @@ -43,10 +43,10 @@ def main(): print(HEADER.strip()) print() - print("pub const SMALLEST_POWER_OF_FIVE: i32 = {};".format(min_exp)) - print("pub const LARGEST_POWER_OF_FIVE: i32 = {};".format(max_exp)) - print("pub const N_POWERS_OF_FIVE: usize = ", end="") - print("(LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;") + print("pub(super) const SMALLEST_POWER_OF_FIVE: i32 = {};".format(min_exp)) + print("pub(super) const LARGEST_POWER_OF_FIVE: i32 = {};".format(max_exp)) + print("pub(super) const N_POWERS_OF_FIVE: usize =") + print(" (LARGEST_POWER_OF_FIVE - SMALLEST_POWER_OF_FIVE + 1) as usize;") print() print_proper_powers(min_exp, max_exp, bias) @@ -97,7 +97,7 @@ def print_proper_powers(min_exp, max_exp, bias): print(STATIC_WARNING.strip()) print("#[rustfmt::skip]") typ = "[(u64, u64); N_POWERS_OF_FIVE]" - print("pub static POWER_OF_FIVE_128: {} = [".format(typ)) + print("pub(super) static POWER_OF_FIVE_128: {} = [".format(typ)) for c, exp in powers: hi = "0x{:x}".format(c // (1 << 64)) lo = "0x{:x}".format(c % (1 << 64)) diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index 34bb5c39909..c8f4a32cb17 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -71,7 +71,7 @@ class StdOsStringProvider(printer_base): self._valobj = valobj buf = self._valobj["inner"]["inner"] is_windows = "Wtf8Buf" in buf.type.name - vec = buf[ZERO_FIELD] if is_windows else buf + vec = buf["bytes"] if is_windows else buf self._length = int(vec["len"]) self._data_ptr = unwrap_unique_or_non_null(vec["buf"]["inner"]["ptr"]) diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index bfa789b1f39..bdd44b4a993 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -389,6 +389,49 @@ fn write_with_opt_paren<T: fmt::Display>( Ok(()) } +impl Display<'_> { + fn display_sub_cfgs( + &self, + fmt: &mut fmt::Formatter<'_>, + sub_cfgs: &[Cfg], + separator: &str, + ) -> fmt::Result { + let short_longhand = self.1.is_long() && { + let all_crate_features = + sub_cfgs.iter().all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_)))); + let all_target_features = sub_cfgs + .iter() + .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_)))); + + if all_crate_features { + fmt.write_str("crate features ")?; + true + } else if all_target_features { + fmt.write_str("target features ")?; + true + } else { + false + } + }; + + for (i, sub_cfg) in sub_cfgs.iter().enumerate() { + if i != 0 { + fmt.write_str(separator)?; + } + if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { + if self.1.is_html() { + write!(fmt, "<code>{feat}</code>")?; + } else { + write!(fmt, "`{feat}`")?; + } + } else { + write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; + } + } + Ok(()) + } +} + impl fmt::Display for Display<'_> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.0 { @@ -408,79 +451,9 @@ impl fmt::Display for Display<'_> { Cfg::Any(ref sub_cfgs) => { let separator = if sub_cfgs.iter().all(Cfg::is_simple) { " or " } else { ", or " }; - - let short_longhand = self.1.is_long() && { - let all_crate_features = sub_cfgs - .iter() - .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_)))); - let all_target_features = sub_cfgs - .iter() - .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_)))); - - if all_crate_features { - fmt.write_str("crate features ")?; - true - } else if all_target_features { - fmt.write_str("target features ")?; - true - } else { - false - } - }; - - for (i, sub_cfg) in sub_cfgs.iter().enumerate() { - if i != 0 { - fmt.write_str(separator)?; - } - if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { - if self.1.is_html() { - write!(fmt, "<code>{feat}</code>")?; - } else { - write!(fmt, "`{feat}`")?; - } - } else { - write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; - } - } - Ok(()) - } - - Cfg::All(ref sub_cfgs) => { - let short_longhand = self.1.is_long() && { - let all_crate_features = sub_cfgs - .iter() - .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_)))); - let all_target_features = sub_cfgs - .iter() - .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_)))); - - if all_crate_features { - fmt.write_str("crate features ")?; - true - } else if all_target_features { - fmt.write_str("target features ")?; - true - } else { - false - } - }; - - for (i, sub_cfg) in sub_cfgs.iter().enumerate() { - if i != 0 { - fmt.write_str(" and ")?; - } - if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { - if self.1.is_html() { - write!(fmt, "<code>{feat}</code>")?; - } else { - write!(fmt, "`{feat}`")?; - } - } else { - write_with_opt_paren(fmt, !sub_cfg.is_simple(), Display(sub_cfg, self.1))?; - } - } - Ok(()) + self.display_sub_cfgs(fmt, sub_cfgs, separator) } + Cfg::All(ref sub_cfgs) => self.display_sub_cfgs(fmt, sub_cfgs, " and "), Cfg::True => fmt.write_str("everywhere"), Cfg::False => fmt.write_str("nowhere"), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fbd934bf718..7853e311a04 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1747,9 +1747,9 @@ fn maybe_expand_private_type_alias<'tcx>( }; let hir::ItemKind::TyAlias(ty, generics) = alias else { return None }; - let provided_params = &path.segments.last().expect("segments were empty"); + let final_seg = &path.segments.last().expect("segments were empty"); let mut args = DefIdMap::default(); - let generic_args = provided_params.args(); + let generic_args = final_seg.args(); let mut indices: hir::GenericParamCount = Default::default(); for param in generics.params.iter() { @@ -1781,7 +1781,7 @@ fn maybe_expand_private_type_alias<'tcx>( let type_ = generic_args.args.iter().find_map(|arg| match arg { hir::GenericArg::Type(ty) => { if indices.types == j { - return Some(*ty); + return Some(ty.as_unambig_ty()); } j += 1; None @@ -1843,10 +1843,13 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T ImplTrait(ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect()) } TyKind::Path(_) => clean_qpath(ty, cx), - TyKind::TraitObject(bounds, lifetime, _) => { + TyKind::TraitObject(bounds, lifetime) => { let bounds = bounds.iter().map(|bound| clean_poly_trait_ref(bound, cx)).collect(); - let lifetime = - if !lifetime.is_elided() { Some(clean_lifetime(lifetime, cx)) } else { None }; + let lifetime = if !lifetime.is_elided() { + Some(clean_lifetime(lifetime.pointer(), cx)) + } else { + None + }; DynTrait(bounds, lifetime) } TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), @@ -1854,7 +1857,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T UnsafeBinder(Box::new(clean_unsafe_binder_ty(unsafe_binder_ty, cx))) } // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. - TyKind::Infer + TyKind::Infer(()) | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) @@ -2533,8 +2536,10 @@ fn clean_generic_args<'tcx>( GenericArg::Lifetime(clean_lifetime(lt, cx)) } hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()), - hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)), - hir::GenericArg::Const(ct) => GenericArg::Const(Box::new(clean_const(ct, cx))), + hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty.as_unambig_ty(), cx)), + hir::GenericArg::Const(ct) => { + GenericArg::Const(Box::new(clean_const(ct.as_unambig_ct(), cx))) + } hir::GenericArg::Infer(_inf) => GenericArg::Infer, }) .collect::<Vec<_>>() diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0dda3466a71..0437ebb5857 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,10 +1,10 @@ -use std::sync::atomic::AtomicBool; -use std::sync::{Arc, LazyLock}; +use std::sync::LazyLock; use std::{io, mem}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unord::UnordSet; +use rustc_driver::USING_INTERNAL_FEATURES; use rustc_errors::TerminalUrl; use rustc_errors::codes::*; use rustc_errors::emitter::{ @@ -178,7 +178,7 @@ pub(crate) fn new_dcx( Box::new( JsonEmitter::new( Box::new(io::BufWriter::new(io::stderr())), - source_map, + Some(source_map), fallback_bundle, pretty, json_rendered, @@ -221,7 +221,6 @@ pub(crate) fn create_config( .. }: RustdocOptions, RenderOptions { document_private, .. }: &RenderOptions, - using_internal_features: Arc<AtomicBool>, ) -> rustc_interface::Config { // Add the doc cfg into the doc build. cfgs.push("doc".to_string()); @@ -316,7 +315,7 @@ pub(crate) fn create_config( make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, - using_internal_features, + using_internal_features: &USING_INTERNAL_FEATURES, expanded_args, } } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 009e9662933..8c3e28ecec3 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -193,7 +193,7 @@ pub(crate) fn run(dcx: DiagCtxtHandle<'_>, input: Input, options: RustdocOptions make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), ice_file: None, - using_internal_features: Arc::default(), + using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES, expanded_args: options.expanded_args.clone(), }; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 92935c72b47..20a8dc72491 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -150,8 +150,9 @@ pub(crate) fn comma_sep<T: Display>( items: impl Iterator<Item = T>, space_after_comma: bool, ) -> impl Display { - display_fn(move |f| { - for (i, item) in items.enumerate() { + let items = Cell::new(Some(items)); + fmt::from_fn(move |f| { + for (i, item) in items.take().unwrap().enumerate() { if i != 0 { write!(f, ",{}", if space_after_comma { " " } else { "" })?; } @@ -165,7 +166,7 @@ pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>( bounds: &'a [clean::GenericBound], cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let mut bounds_dup = FxHashSet::default(); for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(*b)).enumerate() { @@ -183,7 +184,7 @@ impl clean::GenericParamDef { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| match &self.kind { + fmt::from_fn(move |f| match &self.kind { clean::GenericParamDefKind::Lifetime { outlives } => { write!(f, "{}", self.name)?; @@ -238,7 +239,7 @@ impl clean::Generics { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let mut real_params = self.params.iter().filter(|p| !p.is_synthetic_param()).peekable(); if real_params.peek().is_none() { return Ok(()); @@ -268,12 +269,12 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>( indent: usize, ending: Ending, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let mut where_predicates = gens .where_predicates .iter() .map(|pred| { - display_fn(move |f| { + fmt::from_fn(move |f| { if f.alternate() { f.write_str(" ")?; } else { @@ -376,17 +377,15 @@ impl clean::Lifetime { impl clean::ConstantKind { pub(crate) fn print(&self, tcx: TyCtxt<'_>) -> impl Display + '_ { let expr = self.expr(tcx); - display_fn( - move |f| { - if f.alternate() { f.write_str(&expr) } else { write!(f, "{}", Escape(&expr)) } - }, - ) + fmt::from_fn(move |f| { + if f.alternate() { f.write_str(&expr) } else { write!(f, "{}", Escape(&expr)) } + }) } } impl clean::PolyTrait { fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { print_higher_ranked_params_with_space(&self.generic_params, cx, "for").fmt(f)?; self.trait_.print(cx).fmt(f) }) @@ -398,7 +397,7 @@ impl clean::GenericBound { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| match self { + fmt::from_fn(move |f| match self { clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()), clean::GenericBound::TraitBound(ty, modifiers) => { // `const` and `~const` trait bounds are experimental; don't render them. @@ -430,7 +429,7 @@ impl clean::GenericBound { impl clean::GenericArgs { fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { match self { clean::GenericArgs::AngleBracketed { args, constraints } => { if !args.is_empty() || !constraints.is_empty() { @@ -950,7 +949,7 @@ fn tybounds<'a, 'tcx: 'a>( lt: &'a Option<clean::Lifetime>, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { for (i, bound) in bounds.iter().enumerate() { if i > 0 { write!(f, " + ")?; @@ -971,7 +970,7 @@ fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>( cx: &'a Context<'tcx>, keyword: &'static str, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { if !params.is_empty() { f.write_str(keyword)?; f.write_str(if f.alternate() { "<" } else { "<" })?; @@ -982,13 +981,13 @@ fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>( }) } -pub(crate) fn anchor<'a, 'cx: 'a>( +pub(crate) fn anchor<'a: 'cx, 'cx>( did: DefId, text: Symbol, - cx: &'cx Context<'_>, -) -> impl Display + 'a { - let parts = href(did, cx); - display_fn(move |f| { + cx: &'cx Context<'a>, +) -> impl Display + Captures<'a> + 'cx { + fmt::from_fn(move |f| { + let parts = href(did, cx); if let Ok((url, short_ty, fqp)) = parts { write!( f, @@ -1150,7 +1149,7 @@ fn fmt_type( } } clean::BorrowedRef { lifetime: ref l, mutability, type_: ref ty } => { - let lt = display_fn(|f| match l { + let lt = fmt::from_fn(|f| match l { Some(l) => write!(f, "{} ", l.print()), _ => Ok(()), }); @@ -1270,7 +1269,7 @@ impl clean::Type { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'b + Captures<'tcx> { - display_fn(move |f| fmt_type(self, f, false, cx)) + fmt::from_fn(move |f| fmt_type(self, f, false, cx)) } } @@ -1279,7 +1278,7 @@ impl clean::Path { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'b + Captures<'tcx> { - display_fn(move |f| resolved_path(f, self.def_id(), self, false, false, cx)) + fmt::from_fn(move |f| resolved_path(f, self.def_id(), self, false, false, cx)) } } @@ -1289,7 +1288,7 @@ impl clean::Impl { use_absolute: bool, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { f.write_str("impl")?; self.generics.print(cx).fmt(f)?; f.write_str(" ")?; @@ -1407,7 +1406,7 @@ impl clean::Arguments { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { for (i, input) in self.values.iter().enumerate() { write!(f, "{}: ", input.name)?; input.type_.print(cx).fmt(f)?; @@ -1447,7 +1446,7 @@ impl clean::FnDecl { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'b + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let ellipsis = if self.c_variadic { ", ..." } else { "" }; if f.alternate() { write!( @@ -1481,10 +1480,10 @@ impl clean::FnDecl { indent: usize, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { // First, generate the text form of the declaration, with no line wrapping, and count the bytes. let mut counter = WriteCounter(0); - write!(&mut counter, "{:#}", display_fn(|f| { self.inner_full_print(None, f, cx) })) + write!(&mut counter, "{:#}", fmt::from_fn(|f| { self.inner_full_print(None, f, cx) })) .unwrap(); // If the text form was over 80 characters wide, we will line-wrap our output. let line_wrapping_indent = @@ -1566,7 +1565,7 @@ impl clean::FnDecl { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| match &self.output { + fmt::from_fn(move |f| match &self.output { clean::Tuple(tys) if tys.is_empty() => Ok(()), ty if f.alternate() => { write!(f, " -> {:#}", ty.print(cx)) @@ -1618,7 +1617,7 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>( }; let is_doc_hidden = item.is_doc_hidden(); - display_fn(move |f| { + fmt::from_fn(move |f| { if is_doc_hidden { f.write_str("#[doc(hidden)] ")?; } @@ -1692,7 +1691,7 @@ impl clean::Import { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| match self.kind { + fmt::from_fn(move |f| match self.kind { clean::ImportKind::Simple(name) => { if name == self.source.path.last() { write!(f, "use {};", self.source.print(cx)) @@ -1716,7 +1715,7 @@ impl clean::ImportSource { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| match self.did { + fmt::from_fn(move |f| match self.did { Some(did) => resolved_path(f, did, &self.path, true, false, cx), _ => { for seg in &self.path.segments[..self.path.segments.len() - 1] { @@ -1744,7 +1743,7 @@ impl clean::AssocItemConstraint { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { f.write_str(self.assoc.name.as_str())?; self.assoc.args.print(cx).fmt(f)?; match self.kind { @@ -1765,7 +1764,7 @@ impl clean::AssocItemConstraint { } pub(crate) fn print_abi_with_space(abi: ExternAbi) -> impl Display { - display_fn(move |f| { + fmt::from_fn(move |f| { let quot = if f.alternate() { "\"" } else { """ }; match abi { ExternAbi::Rust => Ok(()), @@ -1783,7 +1782,7 @@ impl clean::GenericArg { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| match self { + fmt::from_fn(move |f| match self { clean::GenericArg::Lifetime(lt) => lt.print().fmt(f), clean::GenericArg::Type(ty) => ty.print(cx).fmt(f), clean::GenericArg::Const(ct) => ct.print(cx.tcx()).fmt(f), @@ -1797,24 +1796,9 @@ impl clean::Term { &'a self, cx: &'a Context<'tcx>, ) -> impl Display + 'a + Captures<'tcx> { - display_fn(move |f| match self { + fmt::from_fn(move |f| match self { clean::Term::Type(ty) => ty.print(cx).fmt(f), clean::Term::Constant(ct) => ct.print(cx.tcx()).fmt(f), }) } } - -pub(crate) fn display_fn(f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl Display { - struct WithFormatter<F>(Cell<Option<F>>); - - impl<F> Display for WithFormatter<F> - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (self.0.take()).unwrap()(f) - } - } - - WithFormatter(Cell::new(Some(f))) -} diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 62cf2b63f7f..7b2aee4b4a5 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -233,7 +233,7 @@ pub(super) fn write_code( out: &mut impl Write, src: &str, href_context: Option<HrefContext<'_, '_>>, - decoration_info: Option<DecorationInfo>, + decoration_info: Option<&DecorationInfo>, ) { // This replace allows to fix how the code source with DOS backline characters is displayed. let src = src.replace("\r\n", "\n"); @@ -510,12 +510,12 @@ struct Decorations { } impl Decorations { - fn new(info: DecorationInfo) -> Self { + fn new(info: &DecorationInfo) -> Self { // Extract tuples (start, end, kind) into separate sequences of (start, kind) and (end). let (mut starts, mut ends): (Vec<_>, Vec<_>) = info .0 - .into_iter() - .flat_map(|(kind, ranges)| ranges.into_iter().map(move |(lo, hi)| ((lo, kind), hi))) + .iter() + .flat_map(|(&kind, ranges)| ranges.into_iter().map(move |&(lo, hi)| ((lo, kind), hi))) .unzip(); // Sort the sequences in document order. @@ -542,7 +542,7 @@ struct Classifier<'src> { impl<'src> Classifier<'src> { /// Takes as argument the source code to HTML-ify, the rust edition to use and the source code /// file span which will be used later on by the `span_correspondence_map`. - fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> { + fn new(src: &'src str, file_span: Span, decoration_info: Option<&DecorationInfo>) -> Self { let tokens = PeekIter::new(TokenIter { src, cursor: Cursor::new(src) }); let decorations = decoration_info.map(Decorations::new); Classifier { diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs index fd5275189d6..fccbb98f80f 100644 --- a/src/librustdoc/html/highlight/tests.rs +++ b/src/librustdoc/html/highlight/tests.rs @@ -78,7 +78,7 @@ let a = 4;"; decorations.insert("example2", vec![(22, 32)]); let mut html = Buffer::new(); - write_code(&mut html, src, None, Some(DecorationInfo(decorations))); + write_code(&mut html, src, None, Some(&DecorationInfo(decorations))); expect_file!["fixtures/decorations.html"].assert_eq(&html.into_inner()); }); } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 9a9ce31caaa..a27a9d202eb 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -69,9 +69,9 @@ use crate::formats::cache::Cache; use crate::formats::item_type::ItemType; use crate::html::escape::Escape; use crate::html::format::{ - Buffer, Ending, HrefError, PrintWithSpace, display_fn, href, join_with_double_colon, - print_abi_with_space, print_constness_with_space, print_default_space, print_generic_bounds, - print_where_clause, visibility_print_with_space, + Buffer, Ending, HrefError, PrintWithSpace, href, join_with_double_colon, print_abi_with_space, + print_constness_with_space, print_default_space, print_generic_bounds, print_where_clause, + visibility_print_with_space, }; use crate::html::markdown::{ HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, @@ -82,13 +82,14 @@ use crate::scrape_examples::{CallData, CallLocation}; use crate::{DOC_RUST_LANG_ORG_CHANNEL, try_none}; pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ { - crate::html::format::display_fn(move |f| { + fmt::from_fn(move |f| { if !v.ends_with('/') && !v.is_empty() { write!(f, "{v}/") } else { f.write_str(v) } }) } /// Specifies whether rendering directly implemented trait items or ones from a certain Deref /// impl. +#[derive(Copy, Clone)] pub(crate) enum AssocItemRender<'a> { All, DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, @@ -309,9 +310,7 @@ impl ItemEntry { impl ItemEntry { pub(crate) fn print(&self) -> impl fmt::Display + '_ { - crate::html::format::display_fn(move |f| { - write!(f, "<a href=\"{}\">{}</a>", self.url, Escape(&self.name)) - }) + fmt::from_fn(move |f| write!(f, "<a href=\"{}\">{}</a>", self.url, Escape(&self.name))) } } @@ -513,7 +512,7 @@ fn document<'a, 'cx: 'a>( info!("Documenting {name}"); } - display_fn(move |f| { + fmt::from_fn(move |f| { document_item_info(cx, item, parent).render_into(f).unwrap(); if parent.is_none() { write!(f, "{}", document_full_collapsible(item, cx, heading_offset)) @@ -530,7 +529,7 @@ fn render_markdown<'a, 'cx: 'a>( links: Vec<RenderedLink>, heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { write!( f, "<div class=\"docblock\">{}</div>", @@ -557,7 +556,7 @@ fn document_short<'a, 'cx: 'a>( parent: &'a clean::Item, show_def_docs: bool, ) -> impl fmt::Display + 'a + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { document_item_info(cx, item, Some(parent)).render_into(f).unwrap(); if !show_def_docs { return Ok(()); @@ -605,7 +604,7 @@ fn document_full_inner<'a, 'cx: 'a>( is_collapsible: bool, heading_offset: HeadingOffset, ) -> impl fmt::Display + 'a + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { if let Some(s) = item.opt_doc_value() { debug!("Doc block: =====\n{s}\n====="); if is_collapsible { @@ -1159,7 +1158,7 @@ fn render_attributes_in_pre<'a, 'tcx: 'a>( prefix: &'a str, cx: &'a Context<'tcx>, ) -> impl fmt::Display + Captures<'a> + Captures<'tcx> { - crate::html::format::display_fn(move |f| { + fmt::from_fn(move |f| { for a in it.attributes(cx.tcx(), cx.cache(), false) { writeln!(f, "{prefix}{a}")?; } @@ -1256,9 +1255,9 @@ fn render_assoc_items<'a, 'cx: 'a>( it: DefId, what: AssocItemRender<'a>, ) -> impl fmt::Display + 'a + Captures<'cx> { - let mut derefs = DefIdSet::default(); - derefs.insert(it); - display_fn(move |f| { + fmt::from_fn(move |f| { + let mut derefs = DefIdSet::default(); + derefs.insert(it); render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs); Ok(()) }) @@ -2577,7 +2576,7 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &Context<'_>, item: &clean file_span, cx, &cx.root_path(), - highlight::DecorationInfo(decoration_info), + &highlight::DecorationInfo(decoration_info), sources::SourceContext::Embedded(sources::ScrapedInfo { needs_expansion, offset: line_min, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 76a51cc64a8..37fea09ace3 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -30,7 +30,7 @@ use crate::formats::Impl; use crate::formats::item_type::ItemType; use crate::html::escape::{Escape, EscapeBodyTextWithWbr}; use crate::html::format::{ - Buffer, Ending, PrintWithSpace, display_fn, join_with_double_colon, print_abi_with_space, + Buffer, Ending, PrintWithSpace, join_with_double_colon, print_abi_with_space, print_constness_with_space, print_where_clause, visibility_print_with_space, }; use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; @@ -92,7 +92,7 @@ macro_rules! item_template_methods { () => {}; (document $($rest:tt)*) => { fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let (item, cx) = self.item_and_cx(); let v = document(cx, item, None, HeadingOffset::H2); write!(f, "{v}") @@ -102,7 +102,7 @@ macro_rules! item_template_methods { }; (document_type_layout $($rest:tt)*) => { fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let (item, cx) = self.item_and_cx(); let def_id = item.item_id.expect_def_id(); let v = document_type_layout(cx, def_id); @@ -113,7 +113,7 @@ macro_rules! item_template_methods { }; (render_attributes_in_pre $($rest:tt)*) => { fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let (item, cx) = self.item_and_cx(); let v = render_attributes_in_pre(item, "", cx); write!(f, "{v}") @@ -123,7 +123,7 @@ macro_rules! item_template_methods { }; (render_assoc_items $($rest:tt)*) => { fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let (item, cx) = self.item_and_cx(); let def_id = item.item_id.expect_def_id(); let v = render_assoc_items(cx, item, def_id, AssocItemRender::All); @@ -520,13 +520,13 @@ fn extra_info_tags<'a, 'tcx: 'a>( parent: &'a clean::Item, import_def_id: Option<DefId>, ) -> impl fmt::Display + 'a + Captures<'tcx> { - display_fn(move |f| { + fmt::from_fn(move |f| { fn tag_html<'a>( class: &'a str, title: &'a str, contents: &'a str, ) -> impl fmt::Display + 'a { - display_fn(move |f| { + fmt::from_fn(move |f| { write!( f, r#"<wbr><span class="stab {class}" title="{title}">{contents}</span>"#, @@ -914,7 +914,6 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra let mut extern_crates = FxIndexSet::default(); if !t.is_dyn_compatible(cx.tcx()) { - // FIXME(dyn_compat_renaming): Update the URL once the Reference is updated. write_section_heading( w, "Dyn Compatibility", @@ -922,7 +921,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra None, format!( "<div class=\"dyn-compatibility-info\"><p>This trait is <b>not</b> \ - <a href=\"{base}/reference/items/traits.html#object-safety\">dyn compatible</a>.</p>\ + <a href=\"{base}/reference/items/traits.html#dyn-compatibility\">dyn compatible</a>.</p>\ <p><i>In older versions of Rust, dyn compatibility was called \"object safety\", \ so this trait is not object safe.</i></p></div>", base = crate::clean::utils::DOC_RUST_LANG_ORG_CHANNEL @@ -1376,7 +1375,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx); write!(f, "{v}") }) @@ -1386,7 +1385,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni &'b self, field: &'a clean::Item, ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let v = document(self.cx, field, Some(self.it), HeadingOffset::H3); write!(f, "{v}") }) @@ -1400,7 +1399,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni &'b self, ty: &'a clean::Type, ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { let v = ty.print(self.cx); write!(f, "{v}") }) @@ -1427,7 +1426,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>( cx: &'a Context<'cx>, s: &'a [clean::Item], ) -> impl fmt::Display + 'a + Captures<'cx> { - display_fn(|f| { + fmt::from_fn(|f| { if !s.is_empty() && s.iter().all(|field| { matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..))) @@ -2152,7 +2151,7 @@ fn render_union<'a, 'cx: 'a>( fields: &'a [clean::Item], cx: &'a Context<'cx>, ) -> impl fmt::Display + 'a + Captures<'cx> { - display_fn(move |mut f| { + fmt::from_fn(move |mut f| { write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?; let where_displayed = g @@ -2332,7 +2331,7 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str { } fn document_non_exhaustive(item: &clean::Item) -> impl fmt::Display + '_ { - display_fn(|f| { + fmt::from_fn(|f| { if item.is_non_exhaustive() { write!( f, diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 881df8b0050..23ac568fdf8 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -100,18 +100,17 @@ impl<'a> Link<'a> { } pub(crate) mod filters { - use std::fmt::Display; + use std::fmt::{self, Display}; use rinja::filters::Safe; use crate::html::escape::EscapeBodyTextWithWbr; - use crate::html::render::display_fn; pub(crate) fn wrapped<T>(v: T) -> rinja::Result<Safe<impl Display>> where T: Display, { let string = v.to_string(); - Ok(Safe(display_fn(move |f| EscapeBodyTextWithWbr(&string).fmt(f)))) + Ok(Safe(fmt::from_fn(move |f| EscapeBodyTextWithWbr(&string).fmt(f)))) } } diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs index 9317844956d..0f01db5f6bc 100644 --- a/src/librustdoc/html/render/type_layout.rs +++ b/src/librustdoc/html/render/type_layout.rs @@ -9,7 +9,6 @@ use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self}; use rustc_span::symbol::Symbol; -use crate::html::format::display_fn; use crate::html::render::Context; #[derive(Template)] @@ -31,7 +30,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( cx: &'a Context<'cx>, ty_def_id: DefId, ) -> impl fmt::Display + 'a + Captures<'cx> { - display_fn(move |f| { + fmt::from_fn(move |f| { if !cx.shared.show_type_layout { return Ok(()); } diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 9827f97d28d..1ac0c10c612 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -17,7 +17,7 @@ use crate::clean::utils::has_doc_flag; use crate::docfs::PathError; use crate::error::Error; use crate::html::render::Context; -use crate::html::{format, highlight, layout}; +use crate::html::{highlight, layout}; use crate::visit::DocVisitor; pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> { @@ -249,7 +249,7 @@ impl SourceCollector<'_, '_> { file_span, self.cx, &root_path, - highlight::DecorationInfo::default(), + &highlight::DecorationInfo::default(), SourceContext::Standalone { file_path }, ) }, @@ -328,13 +328,13 @@ pub(crate) fn print_src( file_span: rustc_span::Span, context: &Context<'_>, root_path: &str, - decoration_info: highlight::DecorationInfo, + decoration_info: &highlight::DecorationInfo, source_context: SourceContext<'_>, ) { - let current_href = context - .href_from_span(clean::Span::new(file_span), false) - .expect("only local crates should have sources emitted"); - let code = format::display_fn(move |fmt| { + let code = fmt::from_fn(move |fmt| { + let current_href = context + .href_from_span(clean::Span::new(file_span), false) + .expect("only local crates should have sources emitted"); highlight::write_code( fmt, s, diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b994a43868c..f487d66edac 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -192,15 +192,12 @@ h1, h2, h3, h4 { .rustdoc-breadcrumbs { grid-area: main-heading-breadcrumbs; line-height: 1.25; - display: flex; - flex-wrap: wrap; - align-items: end; padding-top: 5px; + position: relative; + z-index: 1; } .rustdoc-breadcrumbs a { - padding: 4px 0; - margin: -4px 0; - z-index: 1; + padding: 5px 0 7px; } /* The only headings that get underlines are: Markdown-generated headings within the top-doc @@ -2166,7 +2163,8 @@ details.toggle > summary:not(.hideme)::before { top: 4px; } -.impl-items > details.toggle > summary:not(.hideme)::before { +.impl-items > details.toggle > summary:not(.hideme)::before, +#main-content > .methods > details.toggle > summary:not(.hideme)::before { position: absolute; left: -24px; } @@ -2176,7 +2174,9 @@ details.toggle > summary:not(.hideme)::before { .impl-items > *:not(.item-info), /* We also indent the first top doc comment the same to still keep an indent on the doc block while aligning it with the impl block items. */ -.implementors-toggle > .docblock { +.implementors-toggle > .docblock, +/* We indent trait items as well. */ +#main-content > .methods > :not(.item-info) { margin-left: var(--impl-items-indent); } @@ -2508,7 +2508,8 @@ in src-script.js and main.js margin-left: 10px; } - .impl-items > details.toggle > summary:not(.hideme)::before { + .impl-items > details.toggle > summary:not(.hideme)::before, + #main-content > .methods > details.toggle > summary:not(.hideme)::before { left: -20px; } diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html index 9fd575b2751..62954dbb023 100644 --- a/src/librustdoc/html/templates/print_item.html +++ b/src/librustdoc/html/templates/print_item.html @@ -1,13 +1,13 @@ <div class="main-heading"> {% if !path_components.is_empty() %} - <span class="rustdoc-breadcrumbs"> + <div class="rustdoc-breadcrumbs"> {% for (i, component) in path_components.iter().enumerate() %} {% if i != 0 %} ::<wbr> {% endif %} <a href="{{component.path|safe}}index.html">{{component.name}}</a> {% endfor %} - </span> + </div> {% endif %} <h1> {{typ}} diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index aee96fb8c41..9c62826ccc2 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -28,13 +28,11 @@ {% endfor %} </ul> {% endif %} - {# This kind of layout error can occur with valid code, e.g. if you try to - get the layout of a generic type such as `Vec<T>`. #} + {# This kind of layout error can occur with valid code, for example + if there are trivial bounds: `struct Foo(str, str) where str: Sized;`. #} {% when Err(LayoutError::Unknown(_)) %} <p> {# #} - <strong>Note:</strong> Unable to compute type layout, {#+ #} - possibly due to this type having generic parameters. {#+ #} - Layout can only be computed for concrete, fully-instantiated types. {# #} + <strong>Note:</strong> Unable to compute type layout. {# #} </p> {# This kind of error probably can't happen with valid code, but we don't want to panic and prevent the docs from building, so we just let the @@ -44,6 +42,14 @@ <strong>Note:</strong> Encountered an error during type layout; {#+ #} the type was too big. {# #} </p> + {# This kind of layout error can occur with valid code, e.g. if you try to + get the layout of a generic type such as `Vec<T>`. #} + {% when Err(LayoutError::TooGeneric(_)) %} + <p> {# #} + <strong>Note:</strong> Unable to compute type layout, {#+ #} + possibly due to this type having generic parameters. {#+ #} + Layout can only be computed for concrete, fully-instantiated types. {# #} + </p> {% when Err(LayoutError::ReferencesError(_)) %} <p> {# #} <strong>Note:</strong> Encountered an error during type layout; {#+ #} diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 33166a39574..afe81937495 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -622,7 +622,7 @@ impl FromClean<clean::Type> for Type { impl FromClean<clean::Path> for Path { fn from_clean(path: clean::Path, renderer: &JsonRenderer<'_>) -> Path { Path { - name: path.last_opt().map_or(String::from(""), |s| String::from(s.as_str())), + path: path.whole_name(), id: renderer.id_from_item_default(path.def_id().into()), args: path.segments.last().map(|args| Box::new(args.clone().args.into_json(renderer))), } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ba620b6cb6b..bb954a31891 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -5,6 +5,7 @@ #![feature(rustc_private)] #![feature(assert_matches)] #![feature(box_patterns)] +#![feature(debug_closure_helpers)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(impl_trait_in_assoc_type)] @@ -73,8 +74,6 @@ extern crate tikv_jemalloc_sys as jemalloc_sys; use std::env::{self, VarError}; use std::io::{self, IsTerminal}; use std::process; -use std::sync::Arc; -use std::sync::atomic::AtomicBool; use rustc_errors::DiagCtxtHandle; use rustc_interface::interface; @@ -158,7 +157,7 @@ pub fn main() { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); - let using_internal_features = rustc_driver::install_ice_hook( + rustc_driver::install_ice_hook( "https://github.com/rust-lang/rust/issues/new\ ?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md", |_| (), @@ -179,7 +178,7 @@ pub fn main() { let exit_code = rustc_driver::catch_with_exit_code(|| { let at_args = rustc_driver::args::raw_args(&early_dcx)?; - main_args(&mut early_dcx, &at_args, using_internal_features); + main_args(&mut early_dcx, &at_args); Ok(()) }); process::exit(exit_code); @@ -768,11 +767,7 @@ fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> { Ok(()) } -fn main_args( - early_dcx: &mut EarlyDiagCtxt, - at_args: &[String], - using_internal_features: Arc<AtomicBool>, -) { +fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { // Throw away the first argument, the name of the binary. // In case of at_args being empty, as might be the case by // passing empty argument array to execve under some platforms, @@ -825,8 +820,7 @@ fn main_args( (false, Some(md_input)) => { let md_input = md_input.to_owned(); let edition = options.edition; - let config = - core::create_config(input, options, &render_options, using_internal_features); + let config = core::create_config(input, options, &render_options); // `markdown::render` can invoke `doctest::make_test`, which // requires session globals and a thread pool, so we use @@ -859,7 +853,7 @@ fn main_args( let scrape_examples_options = options.scrape_examples_options.clone(); let bin_crate = options.bin_crate; - let config = core::create_config(input, options, &render_options, using_internal_features); + let config = core::create_config(input, options, &render_options); let registered_lints = config.register_lints.is_some(); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index d46b0dee36c..e4628e4f837 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -598,8 +598,13 @@ impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { // Unneeded. } - fn visit_infer(&mut self, _: &hir::InferArg) { - // Unneeded. + fn visit_infer( + &mut self, + _inf_id: hir::HirId, + _inf_span: Span, + _kind: hir::intravisit::InferKind<'tcx>, + ) -> Self::Result { + // Unneeded } fn visit_lifetime(&mut self, _: &hir::Lifetime) { diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 5a99977ded5..e67e17a73cb 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -30,7 +30,7 @@ pub type FxHashMap<K, V> = HashMap<K, V>; // re-export for use in src/librustdoc /// This integer is incremented with every breaking change to the API, /// and is returned along with the JSON blob as [`Crate::format_version`]. /// Consuming code should assert that this value matches the format version(s) that it supports. -pub const FORMAT_VERSION: u32 = 38; +pub const FORMAT_VERSION: u32 = 39; /// The root of the emitted JSON blob. /// @@ -1036,16 +1036,20 @@ pub enum Type { /// A type that has a simple path to it. This is the kind of type of structs, unions, enums, etc. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Path { - /// The name of the type as declared, e.g. in + /// The path of the type. + /// + /// This will be the path that is *used* (not where it is defined), so + /// multiple `Path`s may have different values for this field even if + /// they all refer to the same item. e.g. /// /// ```rust - /// mod foo { - /// struct Bar; - /// } + /// pub type Vec1 = std::vec::Vec<i32>; // path: "std::vec::Vec" + /// pub type Vec2 = Vec<i32>; // path: "Vec" + /// pub type Vec3 = std::prelude::v1::Vec<i32>; // path: "std::prelude::v1::Vec" /// ``` - /// - /// for `foo::Bar`, this field will be `Bar`. - pub name: String, + // + // Example tested in ./tests/rustdoc-json/path_name.rs + pub path: String, /// The ID of the type. pub id: Id, /// Generic arguments to the type. @@ -1099,8 +1103,7 @@ pub struct Trait { pub is_auto: bool, /// Whether the trait is marked as `unsafe`. pub is_unsafe: bool, - // FIXME(dyn_compat_renaming): Update the URL once the Reference is updated and hits stable. - /// Whether the trait is [dyn compatible](https://doc.rust-lang.org/reference/items/traits.html#object-safety)[^1]. + /// Whether the trait is [dyn compatible](https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility)[^1]. /// /// [^1]: Formerly known as "object safe". pub is_dyn_compatible: bool, diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 045bf21b36a2e1f3ed85e38278d1c3cc4305e13 +Subproject cecde95c119a456c30e57d3e4b31fff5a7d83df diff --git a/src/tools/clippy/.github/driver.sh b/src/tools/clippy/.github/driver.sh index 09202b1878b..701be6bd76d 100755 --- a/src/tools/clippy/.github/driver.sh +++ b/src/tools/clippy/.github/driver.sh @@ -47,9 +47,9 @@ unset CARGO_MANIFEST_DIR # Run a lint and make sure it produces the expected output. It's also expected to exit with code 1 # FIXME: How to match the clippy invocation in compile-test.rs? -./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1 -sed -e "/= help: for/d" double_neg.stderr > normalized.stderr -diff -u normalized.stderr tests/ui/double_neg.stderr +./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/box_default.rs 2>box_default.stderr && exit 1 +sed -e "/= help: for/d" box_default.stderr > normalized.stderr +diff -u normalized.stderr tests/ui/box_default.stderr # make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same SYSROOT=$(rustc --print sysroot) diff --git a/src/tools/clippy/book/src/usage.md b/src/tools/clippy/book/src/usage.md index 7a0be6994fe..23edf6c2aba 100644 --- a/src/tools/clippy/book/src/usage.md +++ b/src/tools/clippy/book/src/usage.md @@ -33,7 +33,7 @@ You can configure lint levels on the command line by adding `-A/W/D clippy::lint_name` like this: ```bash -cargo clippy -- -Aclippy::style -Wclippy::double_neg -Dclippy::perf +cargo clippy -- -Aclippy::style -Wclippy::box_default -Dclippy::perf ``` For [CI] all warnings can be elevated to errors which will in turn fail @@ -101,11 +101,10 @@ You can configure lint levels in source code the same way you can configure ```rust,ignore #![allow(clippy::style)] -#[warn(clippy::double_neg)] +#[warn(clippy::box_default)] fn main() { - let x = 1; - let y = --x; - // ^^ warning: double negation + let _ = Box::<String>::new(Default::default()); + // ^ warning: `Box::new(_)` of default value } ``` diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs index 24d1a53266a..35dd986ff61 100644 --- a/src/tools/clippy/clippy_dev/src/new_lint.rs +++ b/src/tools/clippy/clippy_dev/src/new_lint.rs @@ -455,7 +455,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> }); // Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl - while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token == TokenKind::Ident) { + while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token_kind == TokenKind::Ident) { let mut iter = iter .by_ref() .filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. })); @@ -465,7 +465,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str> // matches `!{` match_tokens!(iter, Bang OpenBrace); if let Some(LintDeclSearchResult { range, .. }) = - iter.find(|result| result.token == TokenKind::CloseBrace) + iter.find(|result| result.token_kind == TokenKind::CloseBrace) { last_decl_curly_offset = Some(range.end); } diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs index a1ca23e65ff..79fd6ffe46c 100644 --- a/src/tools/clippy/clippy_lints/src/box_default.rs +++ b/src/tools/clippy/clippy_lints/src/box_default.rs @@ -4,12 +4,12 @@ use clippy_utils::ty::expr_sig; use clippy_utils::{is_default_equivalent, path_def_id}; use rustc_errors::Applicability; use rustc_hir::def::Res; -use rustc_hir::intravisit::{Visitor, walk_ty}; -use rustc_hir::{Block, Expr, ExprKind, LetStmt, Node, QPath, Ty, TyKind}; +use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty}; +use rustc_hir::{AmbigArg, Block, Expr, ExprKind, HirId, LetStmt, Node, QPath, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_session::declare_lint_pass; -use rustc_span::sym; +use rustc_span::{Span, sym}; declare_clippy_lint! { /// ### What it does @@ -92,8 +92,13 @@ fn is_local_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>, ref_expr: &Expr<'_>) struct InferVisitor(bool); impl Visitor<'_> for InferVisitor { - fn visit_ty(&mut self, t: &Ty<'_>) { - self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..)); + fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, _kind: InferKind<'_>) -> Self::Result { + self.0 = true; + self.visit_id(inf_id); + } + + fn visit_ty(&mut self, t: &Ty<'_, AmbigArg>) { + self.0 |= matches!(t.kind, TyKind::OpaqueDef(..) | TyKind::TraitObject(..)); if !self.0 { walk_ty(self, t); } @@ -104,7 +109,7 @@ fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match cx.tcx.parent_hir_node(expr.hir_id) { Node::LetStmt(LetStmt { ty: Some(ty), .. }) => { let mut v = InferVisitor::default(); - v.visit_ty(ty); + v.visit_ty_unambig(ty); !v.0 }, Node::Expr(Expr { diff --git a/src/tools/clippy/clippy_lints/src/casts/as_pointer_underscore.rs b/src/tools/clippy/clippy_lints/src/casts/as_pointer_underscore.rs index 536126fd02b..3ab6693756f 100644 --- a/src/tools/clippy/clippy_lints/src/casts/as_pointer_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/casts/as_pointer_underscore.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::Ty; pub fn check<'tcx>(cx: &LateContext<'tcx>, ty_into: Ty<'_>, cast_to_hir: &'tcx rustc_hir::Ty<'tcx>) { if let rustc_hir::TyKind::Ptr(rustc_hir::MutTy { ty, .. }) = cast_to_hir.kind - && matches!(ty.kind, rustc_hir::TyKind::Infer) + && matches!(ty.kind, rustc_hir::TyKind::Infer(())) { clippy_utils::diagnostics::span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/casts/as_underscore.rs b/src/tools/clippy/clippy_lints/src/casts/as_underscore.rs index 56e894c6261..3ac486dd63f 100644 --- a/src/tools/clippy/clippy_lints/src/casts/as_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/casts/as_underscore.rs @@ -7,7 +7,7 @@ use rustc_middle::ty; use super::AS_UNDERSCORE; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ty: &'tcx Ty<'_>) { - if matches!(ty.kind, TyKind::Infer) { + if matches!(ty.kind, TyKind::Infer(())) { span_lint_and_then(cx, AS_UNDERSCORE, expr.span, "using `as _` conversion", |diag| { let ty_resolved = cx.typeck_results().expr_ty(expr); if let ty::Error(_) = ty_resolved.kind() { diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs index 4ad39d9160d..c326a0d935c 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs @@ -38,7 +38,7 @@ pub(super) fn check( return; }; match cast_to_hir.kind { - TyKind::Infer => { + TyKind::Infer(()) => { diag.span_suggestion_verbose( expr.span, "use `Into::into` instead", diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs index 205357afd84..e4c0db5d9ef 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs @@ -24,7 +24,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { && let Some(generic_args) = method_path.args && let [GenericArg::Type(cast_to)] = generic_args.args // There probably is no obvious reason to do this, just to be consistent with `as` cases. - && !is_hir_ty_cfg_dependant(cx, cast_to) + && !is_hir_ty_cfg_dependant(cx, cast_to.as_unambig_ty()) { let (cast_from, cast_to) = (cx.typeck_results().expr_ty(self_arg), cx.typeck_results().expr_ty(expr)); lint_cast_ptr_alignment(cx, expr, cast_from, cast_to); diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs index a138ade54aa..bdc389d39dd 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs @@ -43,9 +43,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) { { let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir_ty.kind { - TyKind::Infer => String::new(), + TyKind::Infer(()) => String::new(), TyKind::Ptr(mut_ty) => { - if matches!(mut_ty.ty.kind, TyKind::Infer) { + if matches!(mut_ty.ty.kind, TyKind::Infer(())) { String::new() } else { format!( diff --git a/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs index f699bba20ed..592c820a25e 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs @@ -34,9 +34,9 @@ pub(super) fn check<'tcx>( let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir_ty.kind { - TyKind::Infer => String::new(), + TyKind::Infer(()) => String::new(), TyKind::Ptr(mut_ty) => { - if matches!(mut_ty.ty.kind, TyKind::Infer) { + if matches!(mut_ty.ty.kind, TyKind::Infer(())) { String::new() } else { format!( diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index 332e897def7..9e1876e40f9 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -43,7 +43,7 @@ pub(super) fn check<'tcx>( } }, // Ignore `p as *const _` - TyKind::Infer => return false, + TyKind::Infer(()) => return false, _ => {}, } diff --git a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs index c5c4a28646d..a34af6bc226 100644 --- a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs @@ -18,7 +18,7 @@ pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_> Mutability::Not => ("`0 as *const _` detected", "ptr::null"), }; - let sugg = if let TyKind::Infer = mut_ty.ty.kind { + let sugg = if let TyKind::Infer(()) = mut_ty.ty.kind { format!("{std_or_core}::{sugg_fn}()") } else if let Some(mut_ty_snip) = mut_ty.ty.span.get_source_text(cx) { format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 3ff10d850f8..87e546fbf01 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -507,7 +507,6 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::misc::USED_UNDERSCORE_BINDING_INFO, crate::misc::USED_UNDERSCORE_ITEMS_INFO, crate::misc_early::BUILTIN_TYPE_SHADOW_INFO, - crate::misc_early::DOUBLE_NEG_INFO, crate::misc_early::DUPLICATE_UNDERSCORE_ARGUMENT_INFO, crate::misc_early::MIXED_CASE_HEX_LITERALS_INFO, crate::misc_early::REDUNDANT_AT_REST_PATTERN_INFO, diff --git a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs index 3ea792d8b83..5604172d6f3 100644 --- a/src/tools/clippy/clippy_lints/src/deprecated_lints.rs +++ b/src/tools/clippy/clippy_lints/src/deprecated_lints.rs @@ -129,6 +129,8 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[ ("clippy::clone_double_ref", "suspicious_double_ref_op"), #[clippy::version = ""] ("clippy::cmp_nan", "invalid_nan_comparisons"), + #[clippy::version = "1.86.0"] + ("clippy::double_neg", "double_negations"), #[clippy::version = ""] ("clippy::drop_bounds", "drop_bounds"), #[clippy::version = ""] diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 653726872c6..f5589d8f8e2 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -11,10 +11,10 @@ use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{Visitor, walk_ty}; +use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty}; use rustc_hir::{ - self as hir, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, Pat, - PatKind, Path, QPath, TyKind, UnOp, + self as hir, AmbigArg, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, MatchSource, Mutability, Node, + Pat, PatKind, Path, QPath, TyKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; @@ -796,7 +796,7 @@ impl TyCoercionStability { if let Some(args) = path.args && args.args.iter().any(|arg| match arg { hir::GenericArg::Infer(_) => true, - hir::GenericArg::Type(ty) => ty_contains_infer(ty), + hir::GenericArg::Type(ty) => ty_contains_infer(ty.as_unambig_ty()), _ => false, }) { @@ -815,7 +815,7 @@ impl TyCoercionStability { | TyKind::Path(_) => Self::Deref, TyKind::OpaqueDef(..) | TyKind::TraitAscription(..) - | TyKind::Infer + | TyKind::Infer(()) | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::InferDelegation(..) @@ -889,29 +889,23 @@ impl TyCoercionStability { fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool { struct V(bool); impl Visitor<'_> for V { - fn visit_ty(&mut self, ty: &hir::Ty<'_>) { - if self.0 - || matches!( - ty.kind, - TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(_) | TyKind::Err(_) - ) - { + fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, kind: InferKind<'_>) -> Self::Result { + if let InferKind::Ty(_) | InferKind::Ambig(_) = kind { self.0 = true; - } else { - walk_ty(self, ty); } + self.visit_id(inf_id); } - fn visit_generic_arg(&mut self, arg: &hir::GenericArg<'_>) { - if self.0 || matches!(arg, hir::GenericArg::Infer(_)) { + fn visit_ty(&mut self, ty: &hir::Ty<'_, AmbigArg>) { + if self.0 || matches!(ty.kind, TyKind::OpaqueDef(..) | TyKind::Typeof(_) | TyKind::Err(_)) { self.0 = true; - } else if let hir::GenericArg::Type(ty) = arg { - self.visit_ty(ty); + } else { + walk_ty(self, ty); } } } let mut v = V(false); - v.visit_ty(ty); + v.visit_ty_unambig(ty); v.0 } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs index a78c392e208..4e8853821c3 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::Diag; use rustc_hir::def_id::DefIdMap; use rustc_hir::{ - Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty, + AmbigArg, Expr, ExprKind, ForeignItem, HirId, ImplItem, Item, ItemKind, OwnerId, Pat, Path, Stmt, TraitItem, Ty, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; @@ -140,7 +140,7 @@ impl LateLintPass<'_> for DisallowedMacros { self.check(cx, stmt.span, None); } - fn check_ty(&mut self, cx: &LateContext<'_>, ty: &Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &Ty<'_, AmbigArg>) { self.check(cx, ty.span, None); } diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs index 3265404f2b2..947677e14bd 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdMap; -use rustc_hir::{Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind}; +use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::TyCtxt; use rustc_session::impl_lint_pass; @@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes { } } - fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) { if let TyKind::Path(path) = &ty.kind { self.check_res_emit(cx, &cx.qpath_res(path, ty.hir_id), ty.span); } diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index c0b4743fd71..57a30de7ad1 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -76,22 +76,22 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) { if let ExprKind::MethodCall(_method, receiver, args, _) = expr.kind { for arg in args { - check_clousure(cx, Some(receiver), arg); + check_closure(cx, Some(receiver), arg); } } if let ExprKind::Call(func, args) = expr.kind { - check_clousure(cx, None, func); + check_closure(cx, None, func); for arg in args { - check_clousure(cx, None, arg); + check_closure(cx, None, arg); } } } } #[allow(clippy::too_many_lines)] -fn check_clousure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx>>, expr: &Expr<'tcx>) { +fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx>>, expr: &Expr<'tcx>) { let body = if let ExprKind::Closure(c) = expr.kind - && c.fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer)) + && c.fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer(()))) && matches!(c.fn_decl.output, FnRetTy::DefaultReturn(_)) && !expr.span.from_expansion() { diff --git a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs index d0159ab89e1..688979311c8 100644 --- a/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs +++ b/src/tools/clippy/clippy_lints/src/extra_unused_type_parameters.rs @@ -3,10 +3,10 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then}; use clippy_utils::{is_from_proc_macro, trait_ref_of_method}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; -use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty}; +use rustc_hir::intravisit::{Visitor, walk_impl_item, walk_item, walk_param_bound, walk_ty, walk_unambig_ty}; use rustc_hir::{ - BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, ItemKind, - PredicateOrigin, Ty, WherePredicate, WherePredicateKind, + AmbigArg, BodyId, ExprKind, GenericBound, GenericParam, GenericParamKind, Generics, ImplItem, ImplItemKind, Item, + ItemKind, PredicateOrigin, Ty, WherePredicate, WherePredicateKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::hir::nested_filter; @@ -196,7 +196,7 @@ fn bound_to_trait_def_id(bound: &GenericBound<'_>) -> Option<LocalDefId> { impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> { type NestedFilter = nested_filter::OnlyBodies; - fn visit_ty(&mut self, t: &'tcx Ty<'tcx>) { + fn visit_ty(&mut self, t: &'tcx Ty<'tcx, AmbigArg>) { if let Some((def_id, _)) = t.peel_refs().as_generic_param() { self.ty_params.remove(&def_id); } else { @@ -234,7 +234,7 @@ impl<'tcx> Visitor<'tcx> for TypeWalker<'_, 'tcx> { // type, any params we find nested inside of it are being used as concrete types, // and can therefore can be considered used. So, we're fine to walk the left-hand // side of the where bound. - walk_ty(self, predicate.bounded_ty); + walk_unambig_ty(self, predicate.bounded_ty); } for bound in predicate.bounds { walk_param_bound(self, bound); diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs index e43c311eb85..9a73d0c0993 100644 --- a/src/tools/clippy/clippy_lints/src/from_over_into.rs +++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs @@ -103,7 +103,9 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto { "replace the `Into` implementation with `From<{}>`", middle_trait_ref.self_ty() ); - if let Some(suggestions) = convert_to_from(cx, into_trait_seg, target_ty, self_ty, impl_item_ref) { + if let Some(suggestions) = + convert_to_from(cx, into_trait_seg, target_ty.as_unambig_ty(), self_ty, impl_item_ref) + { diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable); } else { diag.help(message); diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index ad2da3c7fcd..47a5c19215b 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -2,9 +2,8 @@ use std::borrow::Cow; use std::collections::BTreeMap; use rustc_errors::{Applicability, Diag}; -use rustc_hir as hir; -use rustc_hir::intravisit::{Visitor, walk_body, walk_expr, walk_inf, walk_ty}; -use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind}; +use rustc_hir::intravisit::{Visitor, VisitorExt, walk_body, walk_expr, walk_ty}; +use rustc_hir::{self as hir, AmbigArg, Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind}; use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; @@ -112,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { match item.kind { ItemKind::Impl(impl_) => { let mut vis = ImplicitHasherTypeVisitor::new(cx); - vis.visit_ty(impl_.self_ty); + vis.visit_ty_unambig(impl_.self_ty); for target in &vis.found { if !item.span.eq_ctxt(target.span()) { @@ -159,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { for ty in sig.decl.inputs { let mut vis = ImplicitHasherTypeVisitor::new(cx); - vis.visit_ty(ty); + vis.visit_ty_unambig(ty); for target in &vis.found { if generics.span.from_expansion() { @@ -287,21 +286,13 @@ impl<'a, 'tcx> ImplicitHasherTypeVisitor<'a, 'tcx> { } impl<'tcx> Visitor<'tcx> for ImplicitHasherTypeVisitor<'_, 'tcx> { - fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) { - if let Some(target) = ImplicitHasherType::new(self.cx, t) { + fn visit_ty(&mut self, t: &'tcx hir::Ty<'_, AmbigArg>) { + if let Some(target) = ImplicitHasherType::new(self.cx, t.as_unambig_ty()) { self.found.push(target); } walk_ty(self, t); } - - fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { - if let Some(target) = ImplicitHasherType::new(self.cx, &inf.to_ty()) { - self.found.push(target); - } - - walk_inf(self, inf); - } } /// Looks for default-hasher-dependent constructors like `HashMap::new`. diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index ef272c305d3..d02d9b2102b 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -3,8 +3,8 @@ use clippy_utils::source::snippet; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_hir::def_id::DefId; use rustc_hir::{ - AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, TyKind, - WherePredicateKind, + AmbigArg, AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, + TyKind, WherePredicateKind, }; use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; @@ -146,7 +146,9 @@ fn try_resolve_type<'tcx>( index: usize, ) -> Option<Ty<'tcx>> { match args.get(index - 1) { - Some(GenericArg::Type(ty)) => Some(lower_ty(tcx, ty)), + // I don't think we care about `GenericArg::Infer` since this is all for stuff in type signatures + // which do not permit inference variables. + Some(GenericArg::Type(ty)) => Some(lower_ty(tcx, ty.as_unambig_ty())), Some(_) => None, None => Some(tcx.type_of(generics.own_params[index].def_id).skip_binder()), } @@ -335,7 +337,7 @@ impl<'tcx> LateLintPass<'tcx> for ImpliedBoundsInImpls { } } - fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &rustc_hir::Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &rustc_hir::Ty<'tcx, AmbigArg>) { if let TyKind::OpaqueDef(opaque_ty, ..) = ty.kind { check(cx, opaque_ty.bounds); } diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs index 5418acc105e..26bea8d633a 100644 --- a/src/tools/clippy/clippy_lints/src/len_zero.rs +++ b/src/tools/clippy/clippy_lints/src/len_zero.rs @@ -18,6 +18,7 @@ use rustc_session::declare_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; +use rustc_trait_selection::traits::supertrait_def_ids; declare_clippy_lint! { /// ### What it does @@ -270,7 +271,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items // fill the set with current and super traits fn fill_trait_set(traitt: DefId, set: &mut DefIdSet, cx: &LateContext<'_>) { if set.insert(traitt) { - for supertrait in cx.tcx.supertrait_def_ids(traitt) { + for supertrait in supertrait_def_ids(cx.tcx, traitt) { fill_trait_set(supertrait, set, cx); } } diff --git a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs index 5a11702d7ce..2d2438514cc 100644 --- a/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/let_with_type_underscore.rs @@ -28,7 +28,7 @@ declare_lint_pass!(UnderscoreTyped => [LET_WITH_TYPE_UNDERSCORE]); impl<'tcx> LateLintPass<'tcx> for UnderscoreTyped { fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) { if let Some(ty) = local.ty // Ensure that it has a type defined - && let TyKind::Infer = &ty.kind // that type is '_' + && let TyKind::Infer(()) = &ty.kind // that type is '_' && local.span.eq_ctxt(ty.span) && !in_external_macro(cx.tcx.sess, local.span) && !is_from_proc_macro(cx, ty) diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 239822f4085..e6761ea5c67 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -7,13 +7,13 @@ use rustc_errors::Applicability; use rustc_hir::FnRetTy::Return; use rustc_hir::intravisit::nested_filter::{self as hir_nested_filter, NestedFilter}; use rustc_hir::intravisit::{ - Visitor, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound, walk_poly_trait_ref, - walk_trait_ref, walk_ty, walk_where_predicate, + Visitor, VisitorExt, walk_fn_decl, walk_generic_args, walk_generics, walk_impl_item_ref, walk_param_bound, + walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_unambig_ty, walk_where_predicate, }; use rustc_hir::{ - BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, Generics, - HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, PolyTraitRef, - PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, + AmbigArg, BareFnTy, BodyId, FnDecl, FnSig, GenericArg, GenericArgs, GenericBound, GenericParam, GenericParamKind, + Generics, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, LifetimeParamKind, Node, + PolyTraitRef, PredicateOrigin, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereBoundPredicate, WherePredicate, WherePredicateKind, lang_items, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -232,11 +232,11 @@ fn could_use_elision<'tcx>( // extract lifetimes in input argument types for arg in func.inputs { - input_visitor.visit_ty(arg); + input_visitor.visit_ty_unambig(arg); } // extract lifetimes in output type if let Return(ty) = func.output { - output_visitor.visit_ty(ty); + output_visitor.visit_ty_unambig(ty); } for lt in named_generics { input_visitor.visit_generic_param(lt); @@ -340,7 +340,7 @@ fn explicit_self_type<'tcx>(cx: &LateContext<'tcx>, func: &FnDecl<'tcx>, ident: && let Some(self_ty) = func.inputs.first() { let mut visitor = RefVisitor::new(cx); - visitor.visit_ty(self_ty); + visitor.visit_ty_unambig(self_ty); !visitor.all_lts().is_empty() } else { @@ -426,14 +426,14 @@ impl<'tcx> Visitor<'tcx> for RefVisitor<'_, 'tcx> { } } - fn visit_ty(&mut self, ty: &'tcx Ty<'_>) { + fn visit_ty(&mut self, ty: &'tcx Ty<'_, AmbigArg>) { match ty.kind { TyKind::BareFn(&BareFnTy { decl, .. }) => { let mut sub_visitor = RefVisitor::new(self.cx); sub_visitor.visit_fn_decl(decl); self.nested_elision_site_lts.append(&mut sub_visitor.all_lts()); }, - TyKind::TraitObject(bounds, lt, _) => { + TyKind::TraitObject(bounds, lt) => { if !lt.is_elided() { self.unelided_trait_object_lifetime = true; } @@ -456,7 +456,7 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ // a predicate like F: Trait or F: for<'a> Trait<'a> let mut visitor = RefVisitor::new(cx); // walk the type F, it may not contain LT refs - walk_ty(&mut visitor, pred.bounded_ty); + walk_unambig_ty(&mut visitor, pred.bounded_ty); if !visitor.all_lts().is_empty() { return true; } @@ -477,8 +477,8 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ }, WherePredicateKind::EqPredicate(ref pred) => { let mut visitor = RefVisitor::new(cx); - walk_ty(&mut visitor, pred.lhs_ty); - walk_ty(&mut visitor, pred.rhs_ty); + walk_unambig_ty(&mut visitor, pred.lhs_ty); + walk_unambig_ty(&mut visitor, pred.rhs_ty); if !visitor.lts.is_empty() { return true; } @@ -541,7 +541,7 @@ where try_visit!(self.visit_id(hir_id)); self.bounded_ty_depth += 1; - try_visit!(self.visit_ty(bounded_ty)); + try_visit!(self.visit_ty_unambig(bounded_ty)); self.bounded_ty_depth -= 1; walk_list!(self, visit_param_bound, bounds); @@ -625,7 +625,7 @@ fn report_extra_impl_lifetimes<'tcx>(cx: &LateContext<'tcx>, impl_: &'tcx Impl<' if let Some(ref trait_ref) = impl_.of_trait { walk_trait_ref(&mut checker, trait_ref); } - walk_ty(&mut checker, impl_.self_ty); + walk_unambig_ty(&mut checker, impl_.self_ty); for item in impl_.items { walk_impl_item_ref(&mut checker, item); } diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 3c669d94d69..37412866539 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -3,7 +3,7 @@ use clippy_utils::source::snippet; use hir::def::{DefKind, Res}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir as hir; +use rustc_hir::{self as hir, AmbigArg}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::edition::Edition; @@ -123,7 +123,7 @@ impl LateLintPass<'_> for MacroUseImports { self.push_unique_macro_pat_ty(cx, pat.span); } } - fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'_>, ty: &hir::Ty<'_, AmbigArg>) { if ty.span.from_expansion() { self.push_unique_macro_pat_ty(cx, ty.span); } diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs index c31656f8a05..d2a2321dae8 100644 --- a/src/tools/clippy/clippy_lints/src/manual_bits.rs +++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs @@ -6,11 +6,11 @@ use clippy_utils::source::snippet_with_context; use rustc_ast::ast::LitKind; use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath}; +use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; -use rustc_span::sym; +use rustc_span::{Span, sym}; declare_clippy_lint! { /// ### What it does @@ -57,13 +57,13 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { && let ctxt = expr.span.ctxt() && left_expr.span.ctxt() == ctxt && right_expr.span.ctxt() == ctxt - && let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr) + && let Some((real_ty_span, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr) && matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_)) && let ExprKind::Lit(lit) = &other_expr.kind && let LitKind::Int(Pu128(8), _) = lit.node { let mut app = Applicability::MachineApplicable; - let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0; + let ty_snip = snippet_with_context(cx, real_ty_span, ctxt, "..", &mut app).0; let sugg = create_sugg(cx, expr, format!("{ty_snip}::BITS")); span_lint_and_sugg( @@ -85,21 +85,21 @@ fn get_one_size_of_ty<'tcx>( cx: &LateContext<'tcx>, expr1: &'tcx Expr<'_>, expr2: &'tcx Expr<'_>, -) -> Option<(&'tcx rustc_hir::Ty<'tcx>, Ty<'tcx>, &'tcx Expr<'tcx>)> { +) -> Option<(Span, Ty<'tcx>, &'tcx Expr<'tcx>)> { match (get_size_of_ty(cx, expr1), get_size_of_ty(cx, expr2)) { - (Some((real_ty, resolved_ty)), None) => Some((real_ty, resolved_ty, expr2)), - (None, Some((real_ty, resolved_ty))) => Some((real_ty, resolved_ty, expr1)), + (Some((real_ty_span, resolved_ty)), None) => Some((real_ty_span, resolved_ty, expr2)), + (None, Some((real_ty_span, resolved_ty))) => Some((real_ty_span, resolved_ty, expr1)), _ => None, } } -fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(&'tcx rustc_hir::Ty<'tcx>, Ty<'tcx>)> { +fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(Span, Ty<'tcx>)> { if let ExprKind::Call(count_func, []) = expr.kind && let ExprKind::Path(ref count_func_qpath) = count_func.kind && let QPath::Resolved(_, count_func_path) = count_func_qpath && let Some(segment_zero) = count_func_path.segments.first() && let Some(args) = segment_zero.args - && let Some(GenericArg::Type(real_ty)) = args.args.first() + && let Some(real_ty_span) = args.args.first().map(|arg| arg.span()) && let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id() && cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id) { @@ -107,7 +107,7 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option< .node_args(count_func.hir_id) .types() .next() - .map(|resolved_ty| (*real_ty, resolved_ty)) + .map(|resolved_ty| (real_ty_span, resolved_ty)) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs index 5e58054a986..ebfd946b07e 100644 --- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { Node::Param(..) => (), Node::LetStmt(local) => { let Some(ty) = local.ty else { return }; - if matches!(ty.kind, TyKind::Infer) { + if matches!(ty.kind, TyKind::Infer(())) { return; } }, diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index 4a5d3c516b8..4184f8b9e6e 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -3,7 +3,6 @@ use clippy_utils::diagnostics::span_lint_and_note; use core::cmp::Ordering; use rustc_hir::{Arm, Expr, PatKind, RangeEnd}; use rustc_lint::LateContext; -use rustc_middle::mir; use rustc_middle::ty::Ty; use rustc_span::Span; @@ -36,14 +35,12 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) let lhs_const = if let Some(lhs) = lhs { ConstEvalCtxt::new(cx).eval_pat_expr(lhs)? } else { - let min_val_const = ty.numeric_min_val(cx.tcx)?; - mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))? + mir_to_const(cx.tcx, ty.numeric_min_val(cx.tcx)?)? }; let rhs_const = if let Some(rhs) = rhs { ConstEvalCtxt::new(cx).eval_pat_expr(rhs)? } else { - let max_val_const = ty.numeric_max_val(cx.tcx)?; - mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))? + mir_to_const(cx.tcx, ty.numeric_max_val(cx.tcx)?)? }; let lhs_val = lhs_const.int_value(cx.tcx, ty)?; let rhs_val = rhs_const.int_value(cx.tcx, ty)?; diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs index b84594c0da1..1673a6f8b3a 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs @@ -49,7 +49,7 @@ pub(super) fn check<'tcx>( fn_decl.output, FnRetTy::DefaultReturn(_) | FnRetTy::Return(hir::Ty { - kind: hir::TyKind::Infer, + kind: hir::TyKind::Infer(()), .. }) ) { diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs index 6dc8adb42df..10112b62878 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_literal_unwrap.rs @@ -1,14 +1,14 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::{MaybePath, is_res_lang_ctor, last_path_segment, path_res}; use rustc_errors::Applicability; -use rustc_hir as hir; +use rustc_hir::{self as hir, AmbigArg}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_middle::ty::print::with_forced_trimmed_paths; use super::UNNECESSARY_LITERAL_UNWRAP; -fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -> Option<&'a hir::Ty<'a>> { +fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) -> Option<&'a hir::Ty<'a, AmbigArg>> { let args = args?; if args.len() <= index { @@ -16,10 +16,7 @@ fn get_ty_from_args<'a>(args: Option<&'a [hir::GenericArg<'a>]>, index: usize) - } match args[index] { - hir::GenericArg::Type(ty) => match ty.kind { - hir::TyKind::Infer => None, - _ => Some(ty), - }, + hir::GenericArg::Type(ty) => Some(ty), _ => None, } } diff --git a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs index 6c2ae9cc6bf..0aec26f1011 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unused_enumerate_index.rs @@ -130,7 +130,7 @@ pub(super) fn check(cx: &LateContext<'_>, call_expr: &Expr<'_>, recv: &Expr<'_>, fn find_elem_explicit_type_span(fn_decl: &FnDecl<'_>) -> Option<Span> { if let [tuple_ty] = fn_decl.inputs && let TyKind::Tup([_idx_ty, elem_ty]) = tuple_ty.kind - && !matches!(elem_ty.kind, TyKind::Err(..) | TyKind::Infer) + && !matches!(elem_ty.kind, TyKind::Err(..) | TyKind::Infer(())) { Some(elem_ty.span) } else { diff --git a/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs b/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs deleted file mode 100644 index 06ba968fa4e..00000000000 --- a/src/tools/clippy/clippy_lints/src/misc_early/double_neg.rs +++ /dev/null @@ -1,18 +0,0 @@ -use clippy_utils::diagnostics::span_lint; -use rustc_ast::ast::{Expr, ExprKind, UnOp}; -use rustc_lint::EarlyContext; - -use super::DOUBLE_NEG; - -pub(super) fn check(cx: &EarlyContext<'_>, expr: &Expr) { - if let ExprKind::Unary(UnOp::Neg, ref inner) = expr.kind { - if let ExprKind::Unary(UnOp::Neg, _) = inner.kind { - span_lint( - cx, - DOUBLE_NEG, - expr.span, - "`--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op", - ); - } - } -} diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs index 37d7427f9a5..637d6ed3ad2 100644 --- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs +++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs @@ -1,5 +1,4 @@ mod builtin_type_shadow; -mod double_neg; mod literal_suffix; mod mixed_case_hex_literals; mod redundant_at_rest_pattern; @@ -87,25 +86,6 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Detects expressions of the form `--x`. - /// - /// ### Why is this bad? - /// It can mislead C/C++ programmers to think `x` was - /// decremented. - /// - /// ### Example - /// ```no_run - /// let mut x = 3; - /// --x; - /// ``` - #[clippy::version = "pre 1.29.0"] - pub DOUBLE_NEG, - style, - "`--x`, which is a double negation of `x` and not a pre-decrement as in C/C++" -} - -declare_clippy_lint! { - /// ### What it does /// Warns on hexadecimal literals with mixed-case letter /// digits. /// @@ -352,7 +332,6 @@ declare_clippy_lint! { declare_lint_pass!(MiscEarlyLints => [ UNNEEDED_FIELD_PATTERN, DUPLICATE_UNDERSCORE_ARGUMENT, - DOUBLE_NEG, MIXED_CASE_HEX_LITERALS, UNSEPARATED_LITERAL_SUFFIX, SEPARATED_LITERAL_SUFFIX, @@ -415,7 +394,6 @@ impl EarlyLintPass for MiscEarlyLints { if let ExprKind::Lit(lit) = expr.kind { MiscEarlyLints::check_lit(cx, lit, expr.span); } - double_neg::check(cx, expr); } } diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index e2ab5e98504..0ee851a4cf9 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -1,7 +1,6 @@ use clippy_utils::diagnostics::{span_lint, span_lint_hir}; use clippy_utils::higher; -use rustc_hir as hir; -use rustc_hir::intravisit; +use rustc_hir::{self as hir, AmbigArg, intravisit}; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; @@ -34,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for MutMut { intravisit::walk_block(&mut MutVisitor { cx }, block); } - fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_, AmbigArg>) { if let hir::TyKind::Ref(_, mty) = ty.kind && mty.mutbl == hir::Mutability::Mut && let hir::TyKind::Ref(_, mty) = mty.ty.kind diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs index 82b9d10fbeb..c3c09946c27 100644 --- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs +++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs @@ -190,7 +190,8 @@ fn in_impl<'tcx>( && let Some(generic_args) = seg.args && let Some(GenericArg::Type(other_ty)) = generic_args.args.last() { - Some((item.self_ty, other_ty)) + // `_` is not permitted in impl headers + Some((item.self_ty, other_ty.as_unambig_ty())) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs index 7d59bf24d93..074345e7532 100644 --- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::last_path_segment; use clippy_utils::source::snippet; use rustc_errors::Applicability; -use rustc_hir::{GenericArg, GenericArgsParentheses, Mutability, Ty, TyKind}; +use rustc_hir::{AmbigArg, GenericArg, GenericArgsParentheses, Mutability, Ty, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; use rustc_span::symbol::sym; @@ -36,7 +36,7 @@ declare_clippy_lint! { declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]); impl<'tcx> LateLintPass<'tcx> for RefOptionRef { - fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) { if let TyKind::Ref(_, ref mut_ty) = ty.kind && mut_ty.mutbl == Mutability::Not && let TyKind::Path(qpath) = &mut_ty.ty.kind diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 99844beb8f0..790e0965198 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -10,8 +10,8 @@ use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::{ - BoundPolarity, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath, - TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicateKind, + AmbigArg, BoundPolarity, GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, + PredicateOrigin, QPath, TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicateKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; @@ -171,7 +171,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { } } - fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) { if let TyKind::Ref(.., mut_ty) = &ty.kind && let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind && bounds.len() > 2 diff --git a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs index b2892d136fa..531422798a6 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/missing_transmute_annotations.rs @@ -52,7 +52,6 @@ pub(super) fn check<'tcx>( let missing_generic = match args { Some(args) if !args.args.is_empty() => args.args.iter().any(|arg| match arg { GenericArg::Infer(_) => true, - GenericArg::Type(ty) => matches!(ty.kind, TyKind::Infer), _ => false, }), _ => true, @@ -65,7 +64,7 @@ pub(super) fn check<'tcx>( // ... which does have type annotations. if let Some(ty) = local.ty // If this is a `let x: _ =`, we should lint. - && !matches!(ty.kind, TyKind::Infer) + && !matches!(ty.kind, TyKind::Infer(())) { return false; } diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index bde88ab61ad..1a5fdf0cd64 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -25,7 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m _ => None, }) { - if is_any_trait(cx, inner) { + if is_any_trait(cx, inner.as_unambig_ty()) { // Ignore `Box<Any>` types; see issue #1884 for details. return false; } @@ -47,7 +47,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m // Originally reported as the issue #3128. let inner_snippet = snippet(cx, inner.span, ".."); let suggestion = match &inner.kind { - TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => { + TyKind::TraitObject(bounds, lt_bound) if bounds.len() > 1 || !lt_bound.is_elided() => { format!("&{ltopt}({inner_snippet})") }, TyKind::Path(qpath) diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 43cce625c64..391c36df492 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -560,7 +560,7 @@ impl Types { _ => None, }) }) { - self.check_ty(cx, ty, context); + self.check_ty(cx, ty.as_unambig_ty(), context); } }, QPath::Resolved(None, p) => { @@ -574,7 +574,7 @@ impl Types { _ => None, }) }) { - self.check_ty(cx, ty, context); + self.check_ty(cx, ty.as_unambig_ty(), context); } }, QPath::TypeRelative(ty, seg) => { @@ -585,7 +585,7 @@ impl Types { GenericArg::Type(ty) => Some(ty), _ => None, }) { - self.check_ty(cx, ty, context); + self.check_ty(cx, ty.as_unambig_ty(), context); } } }, diff --git a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs index b89bd6a8d05..7f51660293b 100644 --- a/src/tools/clippy/clippy_lints/src/types/type_complexity.rs +++ b/src/tools/clippy/clippy_lints/src/types/type_complexity.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint; -use rustc_hir as hir; -use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty}; -use rustc_hir::{GenericParamKind, TyKind}; +use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty}; +use rustc_hir::{self as hir, AmbigArg, GenericParamKind, TyKind}; use rustc_lint::LateContext; +use rustc_span::Span; use rustc_target::spec::abi::Abi; use super::TYPE_COMPLEXITY; @@ -10,7 +10,7 @@ use super::TYPE_COMPLEXITY; pub(super) fn check(cx: &LateContext<'_>, ty: &hir::Ty<'_>, type_complexity_threshold: u64) -> bool { let score = { let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 }; - visitor.visit_ty(ty); + visitor.visit_ty_unambig(ty); visitor.score }; @@ -36,15 +36,15 @@ struct TypeComplexityVisitor { } impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { - fn visit_infer(&mut self, inf: &'tcx hir::InferArg) { + fn visit_infer(&mut self, inf_id: hir::HirId, _inf_span: Span, _kind: InferKind<'tcx>) -> Self::Result { self.score += 1; - walk_inf(self, inf); + self.visit_id(inf_id); } - fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_>) { + fn visit_ty(&mut self, ty: &'tcx hir::Ty<'_, AmbigArg>) { let (add_score, sub_nest) = match ty.kind { - // _, &x and *x have only small overhead; don't mess with nesting level - TyKind::Infer | TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0), + // &x and *x have only small overhead; don't mess with nesting level + TyKind::Ptr(..) | TyKind::Ref(..) => (1, 0), // the "normal" components of a type: named types, arrays/tuples TyKind::Path(..) | TyKind::Slice(..) | TyKind::Tup(..) | TyKind::Array(..) => (10 * self.nest, 1), @@ -52,7 +52,7 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor { // function types bring a lot of overhead TyKind::BareFn(bare) if bare.abi == Abi::Rust => (50 * self.nest, 1), - TyKind::TraitObject(param_bounds, _, _) => { + TyKind::TraitObject(param_bounds, _) => { let has_lifetime_parameters = param_bounds.iter().any(|bound| { bound .bound_generic_params diff --git a/src/tools/clippy/clippy_lints/src/types/vec_box.rs b/src/tools/clippy/clippy_lints/src/types/vec_box.rs index 9b236d3bda5..769244c675e 100644 --- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs @@ -35,7 +35,8 @@ pub(super) fn check<'tcx>( && let Some(GenericArg::Type(boxed_ty)) = last.args.first() // extract allocator from the Box for later && let boxed_alloc_ty = last.args.get(1) - && let ty_ty = lower_ty(cx.tcx, boxed_ty) + // we don't expect to encounter `_` here so ignore `GenericArg::Infer` is okay + && let ty_ty = lower_ty(cx.tcx, boxed_ty.as_unambig_ty()) && !ty_ty.has_escaping_bound_vars() && ty_ty.is_sized(cx.tcx, cx.typing_env()) && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes()) @@ -55,7 +56,8 @@ pub(super) fn check<'tcx>( } }, (Some(GenericArg::Type(l)), Some(GenericArg::Type(r))) => - lower_ty(cx.tcx, l) == lower_ty(cx.tcx, r), + // we don't expect to encounter `_` here so ignore `GenericArg::Infer` is okay + lower_ty(cx.tcx, l.as_unambig_ty()) == lower_ty(cx.tcx, r.as_unambig_ty()), _ => false } { diff --git a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs index d2727968c0c..660bdb9e2be 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/let_unit_value.rs @@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, local: &'tcx LetStmt<'_>) { return; } - if (local.ty.is_some_and(|ty| !matches!(ty.kind, TyKind::Infer)) + if (local.ty.is_some_and(|ty| !matches!(ty.kind, TyKind::Infer(()))) || matches!(local.pat.kind, PatKind::Tuple([], ddpos) if ddpos.as_opt_usize().is_none())) && expr_needs_inferred_result(cx, init) { @@ -158,7 +158,7 @@ fn expr_needs_inferred_result<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) - } while let Some(id) = locals_to_check.pop() { if let Node::LetStmt(l) = cx.tcx.parent_hir_node(id) { - if !l.ty.is_none_or(|ty| matches!(ty.kind, TyKind::Infer)) { + if !l.ty.is_none_or(|ty| matches!(ty.kind, TyKind::Infer(()))) { return false; } if let Some(e) = l.init { diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 05c5be03002..84b6430294f 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -7,10 +7,10 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty}; +use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty}; use rustc_hir::{ - self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl, - ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, + self as hir, AmbigArg, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, + HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, }; use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; @@ -179,7 +179,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) { if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) { let mut visitor = SkipTyCollector::default(); - visitor.visit_ty(impl_hir_ty); + visitor.visit_ty_unambig(impl_hir_ty); types_to_skip.extend(visitor.types_to_skip); } } @@ -201,7 +201,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { } } - fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &Ty<'tcx>) { + fn check_ty(&mut self, cx: &LateContext<'tcx>, hir_ty: &Ty<'tcx, AmbigArg>) { if !hir_ty.span.from_expansion() && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && let Some(&StackItem::Check { @@ -218,7 +218,8 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf { && let ty = if in_body > 0 { cx.typeck_results().node_type(hir_ty.hir_id) } else { - lower_ty(cx.tcx, hir_ty) + // We don't care about ignoring infer vars here + lower_ty(cx.tcx, hir_ty.as_unambig_ty()) } && let impl_ty = cx.tcx.type_of(impl_id).instantiate_identity() && same_type_and_consts(ty, impl_ty) @@ -275,12 +276,14 @@ struct SkipTyCollector { } impl Visitor<'_> for SkipTyCollector { - fn visit_infer(&mut self, inf: &hir::InferArg) { - self.types_to_skip.push(inf.hir_id); - - walk_inf(self, inf); + fn visit_infer(&mut self, inf_id: HirId, _inf_span: Span, kind: InferKind<'_>) -> Self::Result { + // Conservatively assume ambiguously kinded inferred arguments are type arguments + if let InferKind::Ambig(_) | InferKind::Ty(_) = kind { + self.types_to_skip.push(inf_id); + } + self.visit_id(inf_id); } - fn visit_ty(&mut self, hir_ty: &Ty<'_>) { + fn visit_ty(&mut self, hir_ty: &Ty<'_, AmbigArg>) { self.types_to_skip.push(hir_ty.hir_id); walk_ty(self, hir_ty); diff --git a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs index e14480b8655..1221abec1ab 100644 --- a/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs +++ b/src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item}; -use rustc_hir::{self as hir, HirId, ItemKind, Node}; +use rustc_hir::{self as hir, AmbigArg, HirId, ItemKind, Node}; use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::layout::LayoutOf as _; @@ -44,10 +44,11 @@ declare_clippy_lint! { declare_lint_pass!(ZeroSizedMapValues => [ZERO_SIZED_MAP_VALUES]); impl LateLintPass<'_> for ZeroSizedMapValues { - fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx>) { + fn check_ty<'tcx>(&mut self, cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'tcx, AmbigArg>) { if !hir_ty.span.from_expansion() && !in_trait_impl(cx, hir_ty.hir_id) - && let ty = ty_from_hir_ty(cx, hir_ty) + // We don't care about infer vars + && let ty = ty_from_hir_ty(cx, hir_ty.as_unambig_ty()) && (is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap)) && let ty::Adt(_, args) = ty.kind() && let ty = args.type_at(1) diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index 68e7f807bf5..cd6290ced33 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -399,8 +399,8 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { TyKind::Tup([head, .., tail]) => (ty_search_pat(head).0, ty_search_pat(tail).1), TyKind::OpaqueDef(..) => (Pat::Str("impl"), Pat::Str("")), TyKind::Path(qpath) => qpath_search_pat(&qpath), - TyKind::Infer => (Pat::Str("_"), Pat::Str("_")), - TyKind::TraitObject(_, _, TraitObjectSyntax::Dyn) => (Pat::Str("dyn"), Pat::Str("")), + TyKind::Infer(()) => (Pat::Str("_"), Pat::Str("_")), + TyKind::TraitObject(_, tagged_ptr) if let TraitObjectSyntax::Dyn = tagged_ptr.tag() => (Pat::Str("dyn"), Pat::Str("")), // NOTE: `TraitObject` is incomplete. It will always return true then. _ => (Pat::Str(""), Pat::Str("")), } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index a1c48d5c36c..d76231a6eea 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -459,9 +459,9 @@ impl HirEqInterExpr<'_, '_, '_> { fn eq_generic_arg(&mut self, left: &GenericArg<'_>, right: &GenericArg<'_>) -> bool { match (left, right) { - (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l, r), + (GenericArg::Const(l), GenericArg::Const(r)) => self.eq_const_arg(l.as_unambig_ct(), r.as_unambig_ct()), (GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => Self::eq_lifetime(l_lt, r_lt), - (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty), + (GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty.as_unambig_ty(), r_ty.as_unambig_ty()), (GenericArg::Infer(l_inf), GenericArg::Infer(r_inf)) => self.eq_ty(&l_inf.to_ty(), &r_inf.to_ty()), _ => false, } @@ -618,7 +618,7 @@ impl HirEqInterExpr<'_, '_, '_> { }, (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r), (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)), - (&TyKind::Infer, &TyKind::Infer) => true, + (&TyKind::Infer(()), &TyKind::Infer(())) => true, _ => false, } } @@ -1281,7 +1281,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, TyKind::Path(qpath) => self.hash_qpath(qpath), - TyKind::TraitObject(_, lifetime, _) => { + TyKind::TraitObject(_, lifetime) => { self.hash_lifetime(lifetime); }, TyKind::Typeof(anon_const) => { @@ -1291,7 +1291,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty(binder.inner_ty); }, TyKind::Err(_) - | TyKind::Infer + | TyKind::Infer(()) | TyKind::Never | TyKind::InferDelegation(..) | TyKind::OpaqueDef(_) @@ -1318,8 +1318,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { for arg in arg_list { match *arg { GenericArg::Lifetime(l) => self.hash_lifetime(l), - GenericArg::Type(ty) => self.hash_ty(ty), - GenericArg::Const(ca) => self.hash_const_arg(ca), + GenericArg::Type(ty) => self.hash_ty(ty.as_unambig_ty()), + GenericArg::Const(ca) => self.hash_const_arg(ca.as_unambig_ct()), GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()), } } diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index eecfc3fb13f..9e11a57d1b3 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -112,7 +112,6 @@ use rustc_hir::{ use rustc_lexer::{TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; -use rustc_middle::mir::Const; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::IntegerExt; @@ -437,7 +436,7 @@ pub fn qpath_generic_tys<'tcx>(qpath: &QPath<'tcx>) -> impl Iterator<Item = &'tc .map_or(&[][..], |a| a.args) .iter() .filter_map(|a| match a { - hir::GenericArg::Type(ty) => Some(*ty), + hir::GenericArg::Type(ty) => Some(ty.as_unambig_ty()), _ => None, }) } @@ -1584,8 +1583,8 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti let start_is_none_or_min = start.is_none_or(|start| { if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) - && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) - && let Some(min_const) = mir_to_const(cx.tcx, Const::from_ty_const(min_val, bnd_ty, cx.tcx)) + && let Some(min_const) = bnd_ty.numeric_min_val(cx.tcx) + && let Some(min_const) = mir_to_const(cx.tcx, min_const) && let Some(start_const) = ConstEvalCtxt::new(cx).eval(start) { start_const == min_const @@ -1597,8 +1596,8 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti RangeLimits::Closed => { if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) - && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx) - && let Some(max_const) = mir_to_const(cx.tcx, Const::from_ty_const(max_val, bnd_ty, cx.tcx)) + && let Some(max_const) = bnd_ty.numeric_max_val(cx.tcx) + && let Some(max_const) = mir_to_const(cx.tcx, max_const) && let Some(end_const) = ConstEvalCtxt::new(cx).eval(end) { end_const == max_const @@ -2148,7 +2147,7 @@ fn is_body_identity_function(cx: &LateContext<'_>, func: &Body<'_>) -> bool { pub fn is_expr_untyped_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { match expr.kind { ExprKind::Closure(&Closure { body, fn_decl, .. }) - if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer)) => + if fn_decl.inputs.iter().all(|ty| matches!(ty.kind, TyKind::Infer(()))) => { is_body_identity_function(cx, cx.tcx.hir().body(body)) }, diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs index d7640ebfb00..b5cec31ba9d 100644 --- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs @@ -14,8 +14,8 @@ use crate::def_path_res; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::{Visitor, walk_qpath, walk_ty}; -use rustc_hir::{self as hir, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind}; +use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_qpath, walk_ty}; +use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, GenericArgs, HirId, Node, PathSegment, QPath, TyKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, AdtDef, GenericArgKind, Ty}; use rustc_span::{Span, Symbol}; @@ -116,14 +116,15 @@ impl<'cx> Visitor<'cx> for CertaintyVisitor<'cx, '_> { } } - fn visit_ty(&mut self, ty: &'cx hir::Ty<'_>) { - if matches!(ty.kind, TyKind::Infer) { - self.certainty = Certainty::Uncertain; - } + fn visit_ty(&mut self, ty: &'cx hir::Ty<'_, AmbigArg>) { if self.certainty != Certainty::Uncertain { walk_ty(self, ty); } } + + fn visit_infer(&mut self, _inf_id: HirId, _inf_span: Span, _kind: InferKind<'cx>) -> Self::Result { + self.certainty = Certainty::Uncertain; + } } fn type_certainty(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Certainty { @@ -139,7 +140,7 @@ fn type_certainty(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Certainty { } let mut visitor = CertaintyVisitor::new(cx); - visitor.visit_ty(ty); + visitor.visit_ty_unambig(ty); visitor.certainty } diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs index 7a3a861a9ca..dcc763a8abd 100644 --- a/src/tools/clippy/clippy_utils/src/visitors.rs +++ b/src/tools/clippy/clippy_utils/src/visitors.rs @@ -2,7 +2,7 @@ use crate::ty::needs_ordered_drop; use crate::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; use rustc_ast::visit::{VisitorResult, try_visit}; -use rustc_hir as hir; +use rustc_hir::{self as hir, AmbigArg}; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::intravisit::{self, Visitor, walk_block, walk_expr}; use rustc_hir::{ @@ -122,7 +122,7 @@ pub fn for_each_expr_without_closures<'tcx, B, C: Continue>( } // Avoid unnecessary `walk_*` calls. - fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result { + fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { ControlFlow::Continue(()) } fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result { @@ -172,7 +172,7 @@ pub fn for_each_expr<'tcx, B, C: Continue>( ControlFlow::Continue(()) } // Avoid unnecessary `walk_*` calls. - fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx>) -> Self::Result { + fn visit_ty(&mut self, _: &'tcx hir::Ty<'tcx, AmbigArg>) -> Self::Result { ControlFlow::Continue(()) } fn visit_pat(&mut self, _: &'tcx Pat<'tcx>) -> Self::Result { diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 75ef60a5dc8..68edefd3095 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -186,7 +186,7 @@ pub fn main() { rustc_driver::init_rustc_env_logger(&early_dcx); - let using_internal_features = rustc_driver::install_ice_hook(BUG_REPORT_URL, |dcx| { + rustc_driver::install_ice_hook(BUG_REPORT_URL, |dcx| { // FIXME: this macro calls unwrap internally but is called in a panicking context! It's not // as simple as moving the call from the hook to main, because `install_ice_hook` doesn't // accept a generic closure. @@ -236,7 +236,7 @@ pub fn main() { let mut args: Vec<String> = orig_args.clone(); pass_sysroot_env_if_given(&mut args, sys_root_env); - rustc_driver::RunCompiler::new(&args, &mut DefaultCallbacks).run(); + rustc_driver::run_compiler(&args, &mut DefaultCallbacks); return Ok(()); } @@ -295,13 +295,9 @@ pub fn main() { let clippy_enabled = !cap_lints_allow && relevant_package && !info_query; if clippy_enabled { args.extend(clippy_args); - rustc_driver::RunCompiler::new(&args, &mut ClippyCallbacks { clippy_args_var }) - .set_using_internal_features(using_internal_features) - .run(); + rustc_driver::run_compiler(&args, &mut ClippyCallbacks { clippy_args_var }); } else { - rustc_driver::RunCompiler::new(&args, &mut RustcCallbacks { clippy_args_var }) - .set_using_internal_features(using_internal_features) - .run(); + rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var }); } Ok(()) })) diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed index f66554de300..26c6a5033d1 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed +++ b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.fixed @@ -1,10 +1,9 @@ #![warn(clippy::borrow_as_ptr)] -#![feature(lang_items, start, libc)] #![no_std] +#![crate_type = "lib"] #[clippy::msrv = "1.75"] -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let val = 1; let _p = core::ptr::addr_of!(val); @@ -12,11 +11,3 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { let _p_mut = core::ptr::addr_of_mut!(val_mut); 0 } - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs index 1fc254aafa7..d8d8b4c380c 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs +++ b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.rs @@ -1,10 +1,9 @@ #![warn(clippy::borrow_as_ptr)] -#![feature(lang_items, start, libc)] #![no_std] +#![crate_type = "lib"] #[clippy::msrv = "1.75"] -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let val = 1; let _p = &val as *const i32; @@ -12,11 +11,3 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { let _p_mut = &mut val_mut as *mut i32; 0 } - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.stderr b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.stderr index 6802c86ec95..488e0bd9677 100644 --- a/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.stderr +++ b/src/tools/clippy/tests/ui/borrow_as_ptr_no_std.stderr @@ -1,5 +1,5 @@ error: borrow as raw pointer - --> tests/ui/borrow_as_ptr_no_std.rs:9:14 + --> tests/ui/borrow_as_ptr_no_std.rs:8:14 | LL | let _p = &val as *const i32; | ^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of!(val)` @@ -8,7 +8,7 @@ LL | let _p = &val as *const i32; = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr_no_std.rs:12:18 + --> tests/ui/borrow_as_ptr_no_std.rs:11:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::addr_of_mut!(val_mut)` diff --git a/src/tools/clippy/tests/ui/box_default_no_std.rs b/src/tools/clippy/tests/ui/box_default_no_std.rs index 4326abc9a54..edb701fcd08 100644 --- a/src/tools/clippy/tests/ui/box_default_no_std.rs +++ b/src/tools/clippy/tests/ui/box_default_no_std.rs @@ -1,6 +1,6 @@ -#![feature(lang_items, start, libc)] #![warn(clippy::box_default)] #![no_std] +#![crate_type = "lib"] pub struct NotBox<T> { _value: T, @@ -18,16 +18,7 @@ impl<T: Default> Default for NotBox<T> { } } -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let _p = NotBox::new(isize::default()); 0 } - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/crashes/ice-7410.rs b/src/tools/clippy/tests/ui/crashes/ice-7410.rs index ccf6d7ff94f..addbca54e80 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-7410.rs +++ b/src/tools/clippy/tests/ui/crashes/ice-7410.rs @@ -1,7 +1,7 @@ //@compile-flags: -Clink-arg=-nostartfiles //@ignore-target: apple windows -#![feature(lang_items, start, libc)] +#![crate_type = "lib"] #![no_std] #![allow(clippy::if_same_then_else)] #![allow(clippy::redundant_pattern_matching)] @@ -15,18 +15,9 @@ impl Drop for S { fn drop(&mut self) {} } -#[start] -fn main(argc: isize, argv: *const *const u8) -> isize { +pub fn main(argc: isize, argv: *const *const u8) -> isize { if let Some(_) = Some(S) { } else { } 0 } - -#[panic_handler] -fn panic(_info: &PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs deleted file mode 100644 index 9e5b2a48903..00000000000 --- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_main_recursion.rs +++ /dev/null @@ -1,32 +0,0 @@ -//@compile-flags: -Clink-arg=-nostartfiles -//@ignore-target: apple - -#![feature(lang_items, start, libc)] -#![no_std] - -use core::panic::PanicInfo; -use core::sync::atomic::{AtomicUsize, Ordering}; - -static N: AtomicUsize = AtomicUsize::new(0); - -#[warn(clippy::main_recursion)] -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { - let x = N.load(Ordering::Relaxed); - N.store(x + 1, Ordering::Relaxed); - - if x < 3 { - main(_argc, _argv); - } - - 0 -} - -#[allow(clippy::empty_loop)] -#[panic_handler] -fn panic(_info: &PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed index 32bccd3a0ff..e09a913ef06 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed +++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.fixed @@ -1,11 +1,10 @@ #![no_std] -#![feature(lang_items, start, libc)] #![crate_type = "lib"] use core::panic::PanicInfo; #[warn(clippy::all)] -fn main() { +pub fn main() { let mut a = 42; let mut b = 1337; diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs index 8ed45a33465..536e71b4a25 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs +++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.rs @@ -1,11 +1,10 @@ #![no_std] -#![feature(lang_items, start, libc)] #![crate_type = "lib"] use core::panic::PanicInfo; #[warn(clippy::all)] -fn main() { +pub fn main() { let mut a = 42; let mut b = 1337; diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr index bcc8684f7c2..3e37bd95ef3 100644 --- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr +++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr @@ -1,5 +1,5 @@ error: this looks like you are trying to swap `a` and `b` - --> tests/ui/crate_level_checks/no_std_swap.rs:12:5 + --> tests/ui/crate_level_checks/no_std_swap.rs:11:5 | LL | / a = b; ... | diff --git a/src/tools/clippy/tests/ui/def_id_nocore.rs b/src/tools/clippy/tests/ui/def_id_nocore.rs index c9650312db8..03f5ca31f5f 100644 --- a/src/tools/clippy/tests/ui/def_id_nocore.rs +++ b/src/tools/clippy/tests/ui/def_id_nocore.rs @@ -1,6 +1,6 @@ //@ignore-target: apple -#![feature(no_core, lang_items, start)] +#![feature(no_core, lang_items)] #![no_core] #![allow(clippy::missing_safety_doc)] diff --git a/src/tools/clippy/tests/ui/double_neg.rs b/src/tools/clippy/tests/ui/double_neg.rs deleted file mode 100644 index 3be8c628873..00000000000 --- a/src/tools/clippy/tests/ui/double_neg.rs +++ /dev/null @@ -1,10 +0,0 @@ -#[warn(clippy::double_neg)] -#[allow(clippy::no_effect)] -fn main() { - let x = 1; - -x; - -(-x); - --x; - //~^ ERROR: `--x` could be misinterpreted as pre-decrement by C programmers, is usually - //~| NOTE: `-D clippy::double-neg` implied by `-D warnings` -} diff --git a/src/tools/clippy/tests/ui/double_neg.stderr b/src/tools/clippy/tests/ui/double_neg.stderr deleted file mode 100644 index 9a902d1323c..00000000000 --- a/src/tools/clippy/tests/ui/double_neg.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: `--x` could be misinterpreted as pre-decrement by C programmers, is usually a no-op - --> tests/ui/double_neg.rs:7:5 - | -LL | --x; - | ^^^ - | - = note: `-D clippy::double-neg` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::double_neg)]` - -error: aborting due to 1 previous error - diff --git a/src/tools/clippy/tests/ui/empty_loop_no_std.rs b/src/tools/clippy/tests/ui/empty_loop_no_std.rs index 1bb895bda75..9bfcbfba969 100644 --- a/src/tools/clippy/tests/ui/empty_loop_no_std.rs +++ b/src/tools/clippy/tests/ui/empty_loop_no_std.rs @@ -2,27 +2,11 @@ //@ignore-target: apple #![warn(clippy::empty_loop)] -#![feature(lang_items, start, libc)] +#![crate_type = "lib"] #![no_std] -use core::panic::PanicInfo; - -#[start] -fn main(argc: isize, argv: *const *const u8) -> isize { +pub fn main(argc: isize, argv: *const *const u8) -> isize { // This should trigger the lint loop {} //~^ ERROR: empty `loop {}` wastes CPU cycles } - -#[panic_handler] -fn panic(_info: &PanicInfo) -> ! { - // This should NOT trigger the lint - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() { - // This should also trigger the lint - loop {} - //~^ ERROR: empty `loop {}` wastes CPU cycles -} diff --git a/src/tools/clippy/tests/ui/empty_loop_no_std.stderr b/src/tools/clippy/tests/ui/empty_loop_no_std.stderr index f4a18204c3c..f36fb9d9e3f 100644 --- a/src/tools/clippy/tests/ui/empty_loop_no_std.stderr +++ b/src/tools/clippy/tests/ui/empty_loop_no_std.stderr @@ -1,5 +1,5 @@ error: empty `loop {}` wastes CPU cycles - --> tests/ui/empty_loop_no_std.rs:13:5 + --> tests/ui/empty_loop_no_std.rs:10:5 | LL | loop {} | ^^^^^^^ @@ -8,13 +8,5 @@ LL | loop {} = note: `-D clippy::empty-loop` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::empty_loop)]` -error: empty `loop {}` wastes CPU cycles - --> tests/ui/empty_loop_no_std.rs:26:5 - | -LL | loop {} - | ^^^^^^^ - | - = help: you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs b/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs index 8ea75fae89b..81e4e0380da 100644 --- a/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs +++ b/src/tools/clippy/tests/ui/floating_point_arithmetic_nostd.rs @@ -1,4 +1,4 @@ -#![feature(lang_items, start)] +#![crate_type = "lib"] #![warn(clippy::imprecise_flops)] #![warn(clippy::suboptimal_flops)] #![no_std] @@ -17,15 +17,6 @@ fn fake_abs1(num: f64) -> f64 { if num >= 0.0 { num } else { -num } } -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { 0 } - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs index d2f9e34a5ce..fdde68790a8 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs @@ -6,7 +6,6 @@ //@aux-build:../auxiliary/proc_macros.rs #![warn(clippy::missing_const_for_fn)] -#![feature(start)] #![feature(type_alias_impl_trait)] extern crate helper; @@ -71,15 +70,6 @@ mod with_test_fn { } } -// Allowing on this function, because it would lint, which we don't want in this case. -// if we have `#[start]` and `#[test]` check `is_entrypoint_fn(cx, def_id.to_def_id())` is stopped -// working -#[allow(clippy::missing_const_for_fn)] -#[start] -fn init(num: isize, something: *const *const u8) -> isize { - 1 -} - trait Foo { // This should not be suggested to be made const // (rustc doesn't allow const trait methods) diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed index 497e0e24317..771ab1ab21a 100644 --- a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed +++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.fixed @@ -1,22 +1,13 @@ #![warn(clippy::missing_spin_loop)] -#![feature(lang_items, start, libc)] +#![crate_type = "lib"] #![no_std] use core::sync::atomic::{AtomicBool, Ordering}; -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { // This should trigger the lint let b = AtomicBool::new(true); // This should lint with `core::hint::spin_loop()` while b.load(Ordering::Acquire) { core::hint::spin_loop() } 0 } - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs index 1c85a9c58d6..bf890fc4066 100644 --- a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs +++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.rs @@ -1,22 +1,13 @@ #![warn(clippy::missing_spin_loop)] -#![feature(lang_items, start, libc)] +#![crate_type = "lib"] #![no_std] use core::sync::atomic::{AtomicBool, Ordering}; -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { // This should trigger the lint let b = AtomicBool::new(true); // This should lint with `core::hint::spin_loop()` while b.load(Ordering::Acquire) {} 0 } - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr index 7911620d32c..d4b9485be46 100644 --- a/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr +++ b/src/tools/clippy/tests/ui/missing_spin_loop_no_std.stderr @@ -1,5 +1,5 @@ error: busy-waiting loop should at least have a spin loop hint - --> tests/ui/missing_spin_loop_no_std.rs:12:37 + --> tests/ui/missing_spin_loop_no_std.rs:11:37 | LL | while b.load(Ordering::Acquire) {} | ^^ help: try: `{ core::hint::spin_loop() }` diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index 47d6e119543..501811fa491 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -13,9 +13,8 @@ #![allow(clippy::disallowed_methods)] #![allow(clippy::disallowed_types)] #![allow(clippy::mixed_read_write_in_expression)] -#![allow(clippy::manual_find_map)] #![allow(clippy::manual_filter_map)] -#![allow(unpredictable_function_pointer_comparisons)] +#![allow(clippy::manual_find_map)] #![allow(clippy::useless_conversion)] #![allow(clippy::redundant_pattern_matching)] #![allow(clippy::match_result_ok)] @@ -30,6 +29,7 @@ #![allow(clippy::unwrap_used)] #![allow(clippy::panicking_overflow_checks)] #![allow(clippy::needless_borrow)] +#![allow(clippy::reversed_empty_ranges)] #![allow(clippy::single_char_add_str)] #![allow(clippy::module_name_repetitions)] #![allow(clippy::missing_const_for_thread_local)] @@ -39,9 +39,11 @@ #![allow(invalid_reference_casting)] #![allow(suspicious_double_ref_op)] #![allow(invalid_nan_comparisons)] +#![allow(double_negations)] #![allow(drop_bounds)] #![allow(dropping_copy_types)] #![allow(dropping_references)] +#![allow(unpredictable_function_pointer_comparisons)] #![allow(useless_ptr_null_checks)] #![allow(for_loops_over_fallibles)] #![allow(forgetting_copy_types)] @@ -60,8 +62,6 @@ #![allow(unknown_lints)] #![allow(unused_labels)] #![allow(ambiguous_wide_pointer_comparisons)] -#![allow(unpredictable_function_pointer_comparisons)] -#![allow(clippy::reversed_empty_ranges)] #![warn(clippy::almost_complete_range)] //~ ERROR: lint `clippy::almost_complete_letter_range` #![warn(clippy::disallowed_names)] //~ ERROR: lint `clippy::blacklisted_name` #![warn(clippy::blocks_in_conditions)] //~ ERROR: lint `clippy::block_in_if_condition_expr` @@ -74,9 +74,8 @@ #![warn(clippy::disallowed_methods)] //~ ERROR: lint `clippy::disallowed_method` #![warn(clippy::disallowed_types)] //~ ERROR: lint `clippy::disallowed_type` #![warn(clippy::mixed_read_write_in_expression)] //~ ERROR: lint `clippy::eval_order_dependence` -#![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::manual_filter_map)] //~ ERROR: lint `clippy::filter_map` -#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons` +#![warn(clippy::manual_find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::useless_conversion)] //~ ERROR: lint `clippy::identity_conversion` #![warn(clippy::redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching` #![warn(clippy::match_result_ok)] //~ ERROR: lint `clippy::if_let_some_result` @@ -95,6 +94,7 @@ #![warn(clippy::expect_used)] //~ ERROR: lint `clippy::result_expect_used` #![warn(clippy::map_unwrap_or)] //~ ERROR: lint `clippy::result_map_unwrap_or_else` #![warn(clippy::unwrap_used)] //~ ERROR: lint `clippy::result_unwrap_used` +#![warn(clippy::reversed_empty_ranges)] //~ ERROR: lint `clippy::reverse_range_loop` #![warn(clippy::single_char_add_str)] //~ ERROR: lint `clippy::single_char_push_str` #![warn(clippy::module_name_repetitions)] //~ ERROR: lint `clippy::stutter` #![warn(clippy::missing_const_for_thread_local)] //~ ERROR: lint `clippy::thread_local_initializer_can_be_made_const` @@ -104,9 +104,11 @@ #![warn(invalid_reference_casting)] //~ ERROR: lint `clippy::cast_ref_to_mut` #![warn(suspicious_double_ref_op)] //~ ERROR: lint `clippy::clone_double_ref` #![warn(invalid_nan_comparisons)] //~ ERROR: lint `clippy::cmp_nan` +#![warn(double_negations)] //~ ERROR: lint `clippy::double_neg` #![warn(drop_bounds)] //~ ERROR: lint `clippy::drop_bounds` #![warn(dropping_copy_types)] //~ ERROR: lint `clippy::drop_copy` #![warn(dropping_references)] //~ ERROR: lint `clippy::drop_ref` +#![warn(unpredictable_function_pointer_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons` #![warn(useless_ptr_null_checks)] //~ ERROR: lint `clippy::fn_null_check` #![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loop_over_option` #![warn(for_loops_over_fallibles)] //~ ERROR: lint `clippy::for_loop_over_result` @@ -128,6 +130,5 @@ #![warn(unknown_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints` #![warn(unused_labels)] //~ ERROR: lint `clippy::unused_label` #![warn(ambiguous_wide_pointer_comparisons)] //~ ERROR: lint `clippy::vtable_address_comparisons` -#![warn(clippy::reversed_empty_ranges)] //~ ERROR: lint `clippy::reverse_range_loop` fn main() {} diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index 12c7db69be2..7f4b8062e1b 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -13,9 +13,8 @@ #![allow(clippy::disallowed_methods)] #![allow(clippy::disallowed_types)] #![allow(clippy::mixed_read_write_in_expression)] -#![allow(clippy::manual_find_map)] #![allow(clippy::manual_filter_map)] -#![allow(unpredictable_function_pointer_comparisons)] +#![allow(clippy::manual_find_map)] #![allow(clippy::useless_conversion)] #![allow(clippy::redundant_pattern_matching)] #![allow(clippy::match_result_ok)] @@ -30,6 +29,7 @@ #![allow(clippy::unwrap_used)] #![allow(clippy::panicking_overflow_checks)] #![allow(clippy::needless_borrow)] +#![allow(clippy::reversed_empty_ranges)] #![allow(clippy::single_char_add_str)] #![allow(clippy::module_name_repetitions)] #![allow(clippy::missing_const_for_thread_local)] @@ -39,9 +39,11 @@ #![allow(invalid_reference_casting)] #![allow(suspicious_double_ref_op)] #![allow(invalid_nan_comparisons)] +#![allow(double_negations)] #![allow(drop_bounds)] #![allow(dropping_copy_types)] #![allow(dropping_references)] +#![allow(unpredictable_function_pointer_comparisons)] #![allow(useless_ptr_null_checks)] #![allow(for_loops_over_fallibles)] #![allow(forgetting_copy_types)] @@ -60,8 +62,6 @@ #![allow(unknown_lints)] #![allow(unused_labels)] #![allow(ambiguous_wide_pointer_comparisons)] -#![allow(unpredictable_function_pointer_comparisons)] -#![allow(clippy::reversed_empty_ranges)] #![warn(clippy::almost_complete_letter_range)] //~ ERROR: lint `clippy::almost_complete_letter_range` #![warn(clippy::blacklisted_name)] //~ ERROR: lint `clippy::blacklisted_name` #![warn(clippy::block_in_if_condition_expr)] //~ ERROR: lint `clippy::block_in_if_condition_expr` @@ -74,9 +74,8 @@ #![warn(clippy::disallowed_method)] //~ ERROR: lint `clippy::disallowed_method` #![warn(clippy::disallowed_type)] //~ ERROR: lint `clippy::disallowed_type` #![warn(clippy::eval_order_dependence)] //~ ERROR: lint `clippy::eval_order_dependence` -#![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::filter_map)] //~ ERROR: lint `clippy::filter_map` -#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons` +#![warn(clippy::find_map)] //~ ERROR: lint `clippy::find_map` #![warn(clippy::identity_conversion)] //~ ERROR: lint `clippy::identity_conversion` #![warn(clippy::if_let_redundant_pattern_matching)] //~ ERROR: lint `clippy::if_let_redundant_pattern_matching` #![warn(clippy::if_let_some_result)] //~ ERROR: lint `clippy::if_let_some_result` @@ -95,6 +94,7 @@ #![warn(clippy::result_expect_used)] //~ ERROR: lint `clippy::result_expect_used` #![warn(clippy::result_map_unwrap_or_else)] //~ ERROR: lint `clippy::result_map_unwrap_or_else` #![warn(clippy::result_unwrap_used)] //~ ERROR: lint `clippy::result_unwrap_used` +#![warn(clippy::reverse_range_loop)] //~ ERROR: lint `clippy::reverse_range_loop` #![warn(clippy::single_char_push_str)] //~ ERROR: lint `clippy::single_char_push_str` #![warn(clippy::stutter)] //~ ERROR: lint `clippy::stutter` #![warn(clippy::thread_local_initializer_can_be_made_const)] //~ ERROR: lint `clippy::thread_local_initializer_can_be_made_const` @@ -104,9 +104,11 @@ #![warn(clippy::cast_ref_to_mut)] //~ ERROR: lint `clippy::cast_ref_to_mut` #![warn(clippy::clone_double_ref)] //~ ERROR: lint `clippy::clone_double_ref` #![warn(clippy::cmp_nan)] //~ ERROR: lint `clippy::cmp_nan` +#![warn(clippy::double_neg)] //~ ERROR: lint `clippy::double_neg` #![warn(clippy::drop_bounds)] //~ ERROR: lint `clippy::drop_bounds` #![warn(clippy::drop_copy)] //~ ERROR: lint `clippy::drop_copy` #![warn(clippy::drop_ref)] //~ ERROR: lint `clippy::drop_ref` +#![warn(clippy::fn_address_comparisons)] //~ ERROR: lint `clippy::fn_address_comparisons` #![warn(clippy::fn_null_check)] //~ ERROR: lint `clippy::fn_null_check` #![warn(clippy::for_loop_over_option)] //~ ERROR: lint `clippy::for_loop_over_option` #![warn(clippy::for_loop_over_result)] //~ ERROR: lint `clippy::for_loop_over_result` @@ -128,6 +130,5 @@ #![warn(clippy::unknown_clippy_lints)] //~ ERROR: lint `clippy::unknown_clippy_lints` #![warn(clippy::unused_label)] //~ ERROR: lint `clippy::unused_label` #![warn(clippy::vtable_address_comparisons)] //~ ERROR: lint `clippy::vtable_address_comparisons` -#![warn(clippy::reverse_range_loop)] //~ ERROR: lint `clippy::reverse_range_loop` fn main() {} diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index 1ec45c4f1f7..f24eaec3917 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -73,132 +73,132 @@ error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_r LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` -error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map` - --> tests/ui/rename.rs:77:9 - | -LL | #![warn(clippy::find_map)] - | ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map` - error: lint `clippy::filter_map` has been renamed to `clippy::manual_filter_map` - --> tests/ui/rename.rs:78:9 + --> tests/ui/rename.rs:77:9 | LL | #![warn(clippy::filter_map)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_filter_map` -error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons` - --> tests/ui/rename.rs:79:9 +error: lint `clippy::find_map` has been renamed to `clippy::manual_find_map` + --> tests/ui/rename.rs:78:9 | -LL | #![warn(clippy::fn_address_comparisons)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons` +LL | #![warn(clippy::find_map)] + | ^^^^^^^^^^^^^^^^ help: use the new name: `clippy::manual_find_map` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> tests/ui/rename.rs:80:9 + --> tests/ui/rename.rs:79:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_redundant_pattern_matching` has been renamed to `clippy::redundant_pattern_matching` - --> tests/ui/rename.rs:81:9 + --> tests/ui/rename.rs:80:9 | LL | #![warn(clippy::if_let_redundant_pattern_matching)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_pattern_matching` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> tests/ui/rename.rs:82:9 + --> tests/ui/rename.rs:81:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl` - --> tests/ui/rename.rs:83:9 + --> tests/ui/rename.rs:82:9 | LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl` error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl` - --> tests/ui/rename.rs:84:9 + --> tests/ui/rename.rs:83:9 | LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl` error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects` - --> tests/ui/rename.rs:85:9 + --> tests/ui/rename.rs:84:9 | LL | #![warn(clippy::integer_arithmetic)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> tests/ui/rename.rs:86:9 + --> tests/ui/rename.rs:85:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> tests/ui/rename.rs:87:9 + --> tests/ui/rename.rs:86:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> tests/ui/rename.rs:88:9 + --> tests/ui/rename.rs:87:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> tests/ui/rename.rs:89:9 + --> tests/ui/rename.rs:88:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:90:9 + --> tests/ui/rename.rs:89:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:91:9 + --> tests/ui/rename.rs:90:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> tests/ui/rename.rs:92:9 + --> tests/ui/rename.rs:91:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::overflow_check_conditional` has been renamed to `clippy::panicking_overflow_checks` - --> tests/ui/rename.rs:93:9 + --> tests/ui/rename.rs:92:9 | LL | #![warn(clippy::overflow_check_conditional)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::panicking_overflow_checks` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> tests/ui/rename.rs:94:9 + --> tests/ui/rename.rs:93:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> tests/ui/rename.rs:95:9 + --> tests/ui/rename.rs:94:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> tests/ui/rename.rs:96:9 + --> tests/ui/rename.rs:95:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> tests/ui/rename.rs:97:9 + --> tests/ui/rename.rs:96:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` +error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges` + --> tests/ui/rename.rs:97:9 + | +LL | #![warn(clippy::reverse_range_loop)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges` + error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` --> tests/ui/rename.rs:98:9 | @@ -253,155 +253,161 @@ error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons` LL | #![warn(clippy::cmp_nan)] | ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons` -error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` +error: lint `clippy::double_neg` has been renamed to `double_negations` --> tests/ui/rename.rs:107:9 | +LL | #![warn(clippy::double_neg)] + | ^^^^^^^^^^^^^^^^^^ help: use the new name: `double_negations` + +error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` + --> tests/ui/rename.rs:108:9 + | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types` - --> tests/ui/rename.rs:108:9 + --> tests/ui/rename.rs:109:9 | LL | #![warn(clippy::drop_copy)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types` error: lint `clippy::drop_ref` has been renamed to `dropping_references` - --> tests/ui/rename.rs:109:9 + --> tests/ui/rename.rs:110:9 | LL | #![warn(clippy::drop_ref)] | ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references` +error: lint `clippy::fn_address_comparisons` has been renamed to `unpredictable_function_pointer_comparisons` + --> tests/ui/rename.rs:111:9 + | +LL | #![warn(clippy::fn_address_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unpredictable_function_pointer_comparisons` + error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks` - --> tests/ui/rename.rs:110:9 + --> tests/ui/rename.rs:112:9 | LL | #![warn(clippy::fn_null_check)] | ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:111:9 + --> tests/ui/rename.rs:113:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:112:9 + --> tests/ui/rename.rs:114:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> tests/ui/rename.rs:113:9 + --> tests/ui/rename.rs:115:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types` - --> tests/ui/rename.rs:114:9 + --> tests/ui/rename.rs:116:9 | LL | #![warn(clippy::forget_copy)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types` error: lint `clippy::forget_ref` has been renamed to `forgetting_references` - --> tests/ui/rename.rs:115:9 + --> tests/ui/rename.rs:117:9 | LL | #![warn(clippy::forget_ref)] | ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> tests/ui/rename.rs:116:9 + --> tests/ui/rename.rs:118:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> tests/ui/rename.rs:117:9 + --> tests/ui/rename.rs:119:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> tests/ui/rename.rs:118:9 + --> tests/ui/rename.rs:120:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked` - --> tests/ui/rename.rs:119:9 + --> tests/ui/rename.rs:121:9 | LL | #![warn(clippy::invalid_utf8_in_unchecked)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> tests/ui/rename.rs:120:9 + --> tests/ui/rename.rs:122:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::maybe_misused_cfg` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:121:9 + --> tests/ui/rename.rs:123:9 | LL | #![warn(clippy::maybe_misused_cfg)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> tests/ui/rename.rs:122:9 + --> tests/ui/rename.rs:124:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::mismatched_target_os` has been renamed to `unexpected_cfgs` - --> tests/ui/rename.rs:123:9 + --> tests/ui/rename.rs:125:9 | LL | #![warn(clippy::mismatched_target_os)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unexpected_cfgs` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> tests/ui/rename.rs:124:9 + --> tests/ui/rename.rs:126:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> tests/ui/rename.rs:125:9 + --> tests/ui/rename.rs:127:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `dangling_pointers_from_temporaries` - --> tests/ui/rename.rs:126:9 + --> tests/ui/rename.rs:128:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `dangling_pointers_from_temporaries` error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops` - --> tests/ui/rename.rs:127:9 + --> tests/ui/rename.rs:129:9 | LL | #![warn(clippy::undropped_manually_drops)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> tests/ui/rename.rs:128:9 + --> tests/ui/rename.rs:130:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> tests/ui/rename.rs:129:9 + --> tests/ui/rename.rs:131:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons` - --> tests/ui/rename.rs:130:9 + --> tests/ui/rename.rs:132:9 | LL | #![warn(clippy::vtable_address_comparisons)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons` -error: lint `clippy::reverse_range_loop` has been renamed to `clippy::reversed_empty_ranges` - --> tests/ui/rename.rs:131:9 - | -LL | #![warn(clippy::reverse_range_loop)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::reversed_empty_ranges` - -error: aborting due to 67 previous errors +error: aborting due to 68 previous errors diff --git a/src/tools/clippy/tests/ui/result_unit_error_no_std.rs b/src/tools/clippy/tests/ui/result_unit_error_no_std.rs index 1e7a028a7fc..c9f4996c368 100644 --- a/src/tools/clippy/tests/ui/result_unit_error_no_std.rs +++ b/src/tools/clippy/tests/ui/result_unit_error_no_std.rs @@ -1,5 +1,6 @@ -#![feature(lang_items, start, libc)] +#![feature(lang_items, libc)] #![no_std] +#![no_main] #![warn(clippy::result_unit_err)] #[clippy::msrv = "1.80"] @@ -12,8 +13,8 @@ pub fn returns_unit_error_lint() -> Result<u32, ()> { Err(()) } -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { 0 } diff --git a/src/tools/clippy/tests/ui/result_unit_error_no_std.stderr b/src/tools/clippy/tests/ui/result_unit_error_no_std.stderr index 33692e60554..a7807f089ab 100644 --- a/src/tools/clippy/tests/ui/result_unit_error_no_std.stderr +++ b/src/tools/clippy/tests/ui/result_unit_error_no_std.stderr @@ -1,5 +1,5 @@ error: this returns a `Result<_, ()>` - --> tests/ui/result_unit_error_no_std.rs:11:1 + --> tests/ui/result_unit_error_no_std.rs:12:1 | LL | pub fn returns_unit_error_lint() -> Result<u32, ()> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed b/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed index 4f4d19e883d..25143eee8cc 100644 --- a/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed +++ b/src/tools/clippy/tests/ui/zero_ptr_no_std.fixed @@ -1,19 +1,10 @@ -#![feature(lang_items, start, libc)] +#![crate_type = "lib"] #![no_std] #![deny(clippy::zero_ptr)] -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let _ = core::ptr::null::<usize>(); let _ = core::ptr::null_mut::<f64>(); let _: *const u8 = core::ptr::null(); 0 } - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.rs b/src/tools/clippy/tests/ui/zero_ptr_no_std.rs index 54954d8d13f..965733b45d9 100644 --- a/src/tools/clippy/tests/ui/zero_ptr_no_std.rs +++ b/src/tools/clippy/tests/ui/zero_ptr_no_std.rs @@ -1,19 +1,10 @@ -#![feature(lang_items, start, libc)] +#![crate_type = "lib"] #![no_std] #![deny(clippy::zero_ptr)] -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { let _ = 0 as *const usize; let _ = 0 as *mut f64; let _: *const u8 = 0 as *const _; 0 } - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[lang = "eh_personality"] -extern "C" fn eh_personality() {} diff --git a/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr b/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr index 42a1a41ca94..014bf312bf3 100644 --- a/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr +++ b/src/tools/clippy/tests/ui/zero_ptr_no_std.stderr @@ -1,5 +1,5 @@ error: `0 as *const _` detected - --> tests/ui/zero_ptr_no_std.rs:7:13 + --> tests/ui/zero_ptr_no_std.rs:6:13 | LL | let _ = 0 as *const usize; | ^^^^^^^^^^^^^^^^^ help: try: `core::ptr::null::<usize>()` @@ -11,13 +11,13 @@ LL | #![deny(clippy::zero_ptr)] | ^^^^^^^^^^^^^^^^ error: `0 as *mut _` detected - --> tests/ui/zero_ptr_no_std.rs:8:13 + --> tests/ui/zero_ptr_no_std.rs:7:13 | LL | let _ = 0 as *mut f64; | ^^^^^^^^^^^^^ help: try: `core::ptr::null_mut::<f64>()` error: `0 as *const _` detected - --> tests/ui/zero_ptr_no_std.rs:9:24 + --> tests/ui/zero_ptr_no_std.rs:8:24 | LL | let _: *const u8 = 0 as *const _; | ^^^^^^^^^^^^^ help: try: `core::ptr::null()` diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 16cc1d2a565..4f8e475e762 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -34,7 +34,7 @@ libc = "0.2" miow = "0.6" [target.'cfg(windows)'.dependencies.windows] -version = "0.57.0" +version = "0.59.0" features = [ "Win32_Foundation", "Win32_System_Diagnostics_Debug", diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index c6f3d7c0d10..00821fc9f9d 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -488,6 +488,17 @@ impl Config { git_merge_commit_email: &self.git_merge_commit_email, } } + + pub fn has_subprocess_support(&self) -> bool { + // FIXME(#135928): compiletest is always a **host** tool. Building and running an + // capability detection executable against the **target** is not trivial. The short term + // solution here is to hard-code some targets to allow/deny, unfortunately. + + let unsupported_target = self.target_cfg().env == "sgx" + || matches!(self.target_cfg().arch.as_str(), "wasm32" | "wasm64") + || self.target_cfg().os == "emscripten"; + !unsupported_target + } } /// Known widths of `target_has_atomic`. diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs index 01068af3e8c..acdb3cbdd45 100644 --- a/src/tools/compiletest/src/directive-list.rs +++ b/src/tools/compiletest/src/directive-list.rs @@ -152,6 +152,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "needs-sanitizer-support", "needs-sanitizer-thread", "needs-std-debug-assertions", + "needs-subprocess", "needs-symlink", "needs-target-has-atomic", "needs-threads", @@ -175,6 +176,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "only-beta", "only-bpf", "only-cdb", + "only-dist", "only-gnu", "only-i686-pc-windows-gnu", "only-i686-pc-windows-msvc", diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index efe758e65cf..37ef63ae42e 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -101,6 +101,8 @@ pub fn load_errors(testfile: &Path, revision: Option<&str>) -> Vec<Error> { rdr.lines() .enumerate() + // We want to ignore utf-8 failures in tests during collection of annotations. + .filter(|(_, line)| line.is_ok()) .filter_map(|(line_num, line)| { parse_expected(last_nonfollow_error, line_num + 1, &line.unwrap(), revision).map( |(which, error)| { diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs index 3f7225195ce..6e5ced17c20 100644 --- a/src/tools/compiletest/src/header/cfg.rs +++ b/src/tools/compiletest/src/header/cfg.rs @@ -235,6 +235,12 @@ fn parse_cfg_name_directive<'a>( message: "when the test mode is {name}", } + condition! { + name: "dist", + condition: std::env::var("COMPILETEST_ENABLE_DIST_TESTS") == Ok("1".to_string()), + message: "when performing tests on dist toolchain" + } + if prefix == "ignore" && outcome == MatchOutcome::Invalid { // Don't error out for ignore-tidy-* diretives, as those are not handled by compiletest. if name.starts_with("tidy-") { diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index e19dcd992fc..12f0790fb10 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -95,6 +95,11 @@ pub(super) fn handle_needs( ignore_reason: "ignored on targets without threading support", }, Need { + name: "needs-subprocess", + condition: config.has_subprocess_support(), + ignore_reason: "ignored on targets without subprocess support", + }, + Need { name: "needs-unwind", condition: config.can_unwind(), ignore_reason: "ignored on targets without unwinding support", @@ -351,6 +356,9 @@ fn find_dlltool(config: &Config) -> bool { dlltool_found } +// FIXME(#135928): this is actually not quite right because this detection is run on the **host**. +// This however still helps the case of windows -> windows local development in case symlinks are +// not available. #[cfg(windows)] fn has_symlinks() -> bool { if std::env::var_os("CI").is_some() { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 84f2149dbdf..ca48abda5fc 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -59,7 +59,7 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R { use std::sync::Mutex; use windows::Win32::System::Diagnostics::Debug::{ - SEM_FAILCRITICALERRORS, SEM_NOGPFAULTERRORBOX, SetErrorMode, THREAD_ERROR_MODE, + SEM_FAILCRITICALERRORS, SEM_NOGPFAULTERRORBOX, SetErrorMode, }; static LOCK: Mutex<()> = Mutex::new(()); @@ -80,7 +80,6 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R { unsafe { // read inherited flags let old_mode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS); - let old_mode = THREAD_ERROR_MODE(old_mode); SetErrorMode(old_mode | SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS); let r = f(); SetErrorMode(old_mode); diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 8a49d630535..7ef16e4a966 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -414,6 +414,8 @@ impl TestCx<'_> { // Provide path to checkout root. This is the top-level directory containing // rust-lang/rust checkout. .env("SOURCE_ROOT", &source_root) + // Path to the build directory. This is usually the same as `source_root.join("build").join("host")`. + .env("BUILD_ROOT", &build_root) // Provide path to stage-corresponding rustc. .env("RUSTC", &self.config.rustc_path) // Provide the directory to libraries that are needed to run the *compiler*. This is not diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs index 7fcb8ffd1f9..a37e6c2eb5c 100644 --- a/src/tools/jsondoclint/src/validator/tests.rs +++ b/src/tools/jsondoclint/src/validator/tests.rs @@ -163,7 +163,7 @@ fn errors_on_missing_path() { sig: FunctionSignature { inputs: vec![], output: Some(Type::ResolvedPath(Path { - name: "Bar".to_owned(), + path: "Bar".to_owned(), id: Id(1), args: None, })), @@ -191,7 +191,7 @@ fn errors_on_missing_path() { check(&krate, &[Error { kind: ErrorKind::Custom( - r#"No entry in '$.paths' for Path { name: "Bar", id: Id(1), args: None }"#.to_owned(), + r#"No entry in '$.paths' for Path { path: "Bar", id: Id(1), args: None }"#.to_owned(), ), id: Id(1), }]); diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 570b2c374c0..19340b5d07a 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -50,6 +50,29 @@ const LINKCHECK_EXCEPTIONS: &[(&str, &[&str])] = &[ ("alloc/slice/trait.Concat.html", &["#method.concat"]), ("alloc/slice/index.html", &["#method.concat", "#method.join"]), ("alloc/vec/struct.Vec.html", &["#method.sort_by_key", "#method.sort_by_cached_key"]), + ("alloc/bstr/struct.ByteStr.html", &[ + "#method.to_ascii_uppercase", + "#method.to_ascii_lowercase", + "core/slice::sort_by_key", + "core\\slice::sort_by_key", + "#method.sort_by_cached_key", + "#method.sort_by_key" + ]), + ("alloc/bstr/struct.ByteString.html", &[ + "#method.to_ascii_uppercase", + "#method.to_ascii_lowercase", + "core/slice::sort_by_key", + "core\\slice::sort_by_key", + "#method.sort_by_cached_key", + "#method.sort_by_key" + ]), + ("core/bstr/struct.ByteStr.html", &[ + "#method.to_ascii_uppercase", + "#method.to_ascii_lowercase", + "core/bstr/slice::sort_by_key", + "core\\bstr\\slice::sort_by_key", + "#method.sort_by_cached_key" + ]), ("core/primitive.str.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase"]), ("core/primitive.slice.html", &["#method.to_ascii_uppercase", "#method.to_ascii_lowercase", "core/slice::sort_by_key", "core\\slice::sort_by_key", diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 5583030b490..fb3fc621565 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -14,7 +14,9 @@ function endgroup { begingroup "Building Miri" # Global configuration -export RUSTFLAGS="-D warnings" +# We are getting some odd linker warnings on macOS, make sure they do not fail the build. +# (See <https://github.com/rust-lang/rust/issues/136086>.) +export RUSTFLAGS="-D warnings -A linker-messages" export CARGO_INCREMENTAL=0 export CARGO_EXTRA_FLAGS="--locked" diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index fa5dbb99e81..0d405f532fc 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -01706e1a34c87656fcbfce198608f4cd2ac6461a +2f0ad2a71e4a4528bb80bcb24bf8fa4e50cb87c2 diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 9055aa30271..988a0be6327 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -29,11 +29,12 @@ use std::num::NonZero; use std::ops::Range; use std::path::PathBuf; use std::str::FromStr; -use std::sync::atomic::{AtomicI32, Ordering}; -use std::sync::{Arc, Once}; +use std::sync::Once; +use std::sync::atomic::{AtomicI32, AtomicU32, Ordering}; use miri::{ - BacktraceStyle, BorrowTrackerMethod, MiriConfig, ProvenanceMode, RetagFields, ValidationMode, + BacktraceStyle, BorrowTrackerMethod, MiriConfig, MiriEntryFnType, ProvenanceMode, RetagFields, + ValidationMode, }; use rustc_abi::ExternAbi; use rustc_data_structures::sync; @@ -51,7 +52,7 @@ use rustc_middle::query::LocalCrate; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::util::Providers; -use rustc_session::config::{CrateType, EntryFnType, ErrorOutputType, OptLevel}; +use rustc_session::config::{CrateType, ErrorOutputType, OptLevel}; use rustc_session::search_paths::PathKind; use rustc_session::{CtfeBacktrace, EarlyDiagCtxt}; use rustc_span::def_id::DefId; @@ -73,9 +74,9 @@ impl MiriCompilerCalls { } } -fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, EntryFnType) { - if let Some(entry_def) = tcx.entry_fn(()) { - return entry_def; +fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) { + if let Some((def_id, entry_type)) = tcx.entry_fn(()) { + return (def_id, MiriEntryFnType::Rustc(entry_type)); } // Look for a symbol in the local crate named `miri_start`, and treat that as the entry point. let sym = tcx.exported_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| { @@ -102,7 +103,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, EntryFnType) { .is_ok(); if correct_func_sig { - (*id, EntryFnType::Start) + (*id, MiriEntryFnType::MiriStart) } else { tcx.dcx().fatal( "`miri_start` must have the following signature:\n\ @@ -182,7 +183,8 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { if let Some(many_seeds) = self.many_seeds.take() { assert!(config.seed.is_none()); let exit_code = sync::IntoDynSyncSend(AtomicI32::new(rustc_driver::EXIT_SUCCESS)); - sync::par_for_each_in(many_seeds.seeds, |seed| { + let num_failed = sync::IntoDynSyncSend(AtomicU32::new(0)); + sync::par_for_each_in(many_seeds.seeds.clone(), |seed| { let mut config = config.clone(); config.seed = Some(seed.into()); eprintln!("Trying seed: {seed}"); @@ -196,8 +198,13 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { std::process::exit(return_code); } exit_code.store(return_code, Ordering::Relaxed); + num_failed.fetch_add(1, Ordering::Relaxed); } }); + let num_failed = num_failed.0.into_inner(); + if num_failed > 0 { + eprintln!("{num_failed}/{total} SEEDS FAILED", total = many_seeds.seeds.count()); + } std::process::exit(exit_code.0.into_inner()); } else { let return_code = miri::eval_entry(tcx, entry_def_id, entry_type, config) @@ -370,13 +377,10 @@ fn init_late_loggers(early_dcx: &EarlyDiagCtxt, tcx: TyCtxt<'_>) { fn run_compiler_and_exit( args: &[String], callbacks: &mut (dyn rustc_driver::Callbacks + Send), - using_internal_features: Arc<std::sync::atomic::AtomicBool>, ) -> ! { // Invoke compiler, and handle return code. let exit_code = rustc_driver::catch_with_exit_code(move || { - rustc_driver::RunCompiler::new(args, callbacks) - .set_using_internal_features(using_internal_features) - .run(); + rustc_driver::run_compiler(args, callbacks); Ok(()) }); std::process::exit(exit_code) @@ -467,8 +471,7 @@ fn main() { // If the environment asks us to actually be rustc, then do that. if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") { // Earliest rustc setup. - let using_internal_features = - rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ()); + rustc_driver::install_ice_hook(rustc_driver::DEFAULT_BUG_REPORT_URL, |_| ()); rustc_driver::init_rustc_env_logger(&early_dcx); let target_crate = if crate_kind == "target" { @@ -492,16 +495,11 @@ fn main() { } // We cannot use `rustc_driver::main` as we want it to use `args` as the CLI arguments. - run_compiler_and_exit( - &args, - &mut MiriBeRustCompilerCalls { target_crate }, - using_internal_features, - ) + run_compiler_and_exit(&args, &mut MiriBeRustCompilerCalls { target_crate }) } // Add an ICE bug report hook. - let using_internal_features = - rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ()); + rustc_driver::install_ice_hook("https://github.com/rust-lang/miri/issues/new", |_| ()); // Init loggers the Miri way. init_early_loggers(&early_dcx); @@ -725,19 +723,14 @@ fn main() { // Ensure we have parallelism for many-seeds mode. if many_seeds.is_some() && !rustc_args.iter().any(|arg| arg.starts_with("-Zthreads=")) { - rustc_args.push(format!( - "-Zthreads={}", - std::thread::available_parallelism().map_or(1, |n| n.get()) - )); + // Clamp to 8 threads; things get a lot less efficient beyond that due to lock contention. + let threads = std::thread::available_parallelism().map_or(1, |n| n.get()).min(8); + rustc_args.push(format!("-Zthreads={threads}")); } let many_seeds = many_seeds.map(|seeds| ManySeedsConfig { seeds, keep_going: many_seeds_keep_going }); debug!("rustc arguments: {:?}", rustc_args); debug!("crate arguments: {:?}", miri_config.args); - run_compiler_and_exit( - &rustc_args, - &mut MiriCompilerCalls::new(miri_config, many_seeds), - using_internal_features, - ) + run_compiler_and_exit(&rustc_args, &mut MiriCompilerCalls::new(miri_config, many_seeds)) } diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index eaf4b30c660..c8f04e25207 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -19,6 +19,12 @@ use crate::diagnostics::report_leaks; use crate::shims::tls; use crate::*; +#[derive(Copy, Clone, Debug)] +pub enum MiriEntryFnType { + MiriStart, + Rustc(EntryFnType), +} + /// When the main thread would exit, we will yield to any other thread that is ready to execute. /// But we must only do that a finite number of times, or a background thread running `loop {}` /// will hang the program. @@ -272,7 +278,7 @@ impl<'tcx> MainThreadState<'tcx> { pub fn create_ecx<'tcx>( tcx: TyCtxt<'tcx>, entry_id: DefId, - entry_type: EntryFnType, + entry_type: MiriEntryFnType, config: &MiriConfig, ) -> InterpResult<'tcx, InterpCx<'tcx, MiriMachine<'tcx>>> { let typing_env = ty::TypingEnv::fully_monomorphized(); @@ -300,7 +306,7 @@ pub fn create_ecx<'tcx>( // Setup first stack frame. let entry_instance = ty::Instance::mono(tcx, entry_id); - // First argument is constructed later, because it's skipped if the entry function uses #[start]. + // First argument is constructed later, because it's skipped for `miri_start.` // Second argument (argc): length of `config.args`. let argc = @@ -373,11 +379,9 @@ pub fn create_ecx<'tcx>( // Call start function. match entry_type { - EntryFnType::Main { .. } => { + MiriEntryFnType::Rustc(EntryFnType::Main { .. }) => { let start_id = tcx.lang_items().start_fn().unwrap_or_else(|| { - tcx.dcx().fatal( - "could not find start function. Make sure the entry point is marked with `#[start]`." - ); + tcx.dcx().fatal("could not find start lang item"); }); let main_ret_ty = tcx.fn_sig(entry_id).no_bound_vars().unwrap().output(); let main_ret_ty = main_ret_ty.no_bound_vars().unwrap(); @@ -413,7 +417,7 @@ pub fn create_ecx<'tcx>( StackPopCleanup::Root { cleanup: true }, )?; } - EntryFnType::Start => { + MiriEntryFnType::MiriStart => { ecx.call_function( entry_instance, ExternAbi::Rust, @@ -434,7 +438,7 @@ pub fn create_ecx<'tcx>( pub fn eval_entry<'tcx>( tcx: TyCtxt<'tcx>, entry_id: DefId, - entry_type: EntryFnType, + entry_type: MiriEntryFnType, config: MiriConfig, ) -> Option<i32> { // Copy setting before we move `config`. diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index ca8dbdac125..c5538351d7d 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -38,9 +38,10 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>) item: DefId, name: &'a str, ) -> impl Iterator<Item = DefId> + 'a { + let name = Symbol::intern(name); tcx.module_children(item) .iter() - .filter(move |item| item.ident.name.as_str() == name) + .filter(move |item| item.ident.name == name) .map(move |item| item.res.def_id()) } diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index a53b22c8041..2955dc38a8c 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -135,8 +135,8 @@ pub use crate::diagnostics::{ EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo, report_error, }; pub use crate::eval::{ - AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith, ValidationMode, - create_ecx, eval_entry, + AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, MiriEntryFnType, RejectOpWith, + ValidationMode, create_ecx, eval_entry, }; pub use crate::helpers::{AccessKind, EvalContextExt as _}; pub use crate::intrinsics::EvalContextExt as _; diff --git a/src/tools/miri/test-cargo-miri/no-std-smoke/src/main.rs b/src/tools/miri/test-cargo-miri/no-std-smoke/src/main.rs index 3a207b7d50a..aa3faf83f92 100644 --- a/src/tools/miri/test-cargo-miri/no-std-smoke/src/main.rs +++ b/src/tools/miri/test-cargo-miri/no-std-smoke/src/main.rs @@ -1,7 +1,7 @@ // Copied from tests/pass/no-std.rs -#![feature(start)] #![no_std] +#![no_main] // Plumbing to let us use `writeln!` to host stdout: @@ -22,8 +22,8 @@ impl Write for Host { } } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +fn miri_start(_: isize, _: *const *const u8) -> isize { writeln!(Host, "hello, world!").unwrap(); 0 } diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs index babdb73f093..8d41002735c 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs @@ -1,8 +1,9 @@ //@compile-flags: -Cpanic=abort -#![feature(start, core_intrinsics)] +#![feature(core_intrinsics)] #![feature(alloc_error_handler)] #![feature(allocator_api)] #![no_std] +#![no_main] extern crate alloc; @@ -43,7 +44,7 @@ mod plumbing { static GLOBAL: NoAlloc = NoAlloc; } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { handle_alloc_error(Layout::for_value(&0)); } diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr index d12e119bce3..1a9e7574339 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr @@ -16,7 +16,7 @@ LL | fn alloc_error_handler(layout: Layout) -> ! { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `alloc::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC -note: inside `start` +note: inside `miri_start` --> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC | LL | handle_alloc_error(Layout::for_value(&0)); diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs index 18a8a61f22f..f73f8e3e7e1 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs @@ -1,8 +1,9 @@ //@compile-flags: -Cpanic=abort -#![feature(start, core_intrinsics)] +#![feature(core_intrinsics)] #![feature(alloc_error_handler)] #![feature(allocator_api)] #![no_std] +#![no_main] extern crate alloc; @@ -41,7 +42,7 @@ mod plumbing { static GLOBAL: NoAlloc = NoAlloc; } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { handle_alloc_error(Layout::for_value(&0)); } diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr index f495d65a8b0..6b4266b9a8b 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr @@ -12,7 +12,7 @@ LL | core::intrinsics::abort(); = note: inside `alloc::alloc::__alloc_error_handler::__rdl_oom` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC = note: inside `alloc::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC -note: inside `start` +note: inside `miri_start` --> tests/fail/alloc/alloc_error_handler_no_std.rs:LL:CC | LL | handle_alloc_error(Layout::for_value(&0)); diff --git a/src/tools/miri/tests/fail/alloc/no_global_allocator.rs b/src/tools/miri/tests/fail/alloc/no_global_allocator.rs index 0952b2c46ba..f76aebaa3e3 100644 --- a/src/tools/miri/tests/fail/alloc/no_global_allocator.rs +++ b/src/tools/miri/tests/fail/alloc/no_global_allocator.rs @@ -2,15 +2,15 @@ //@normalize-stderr-test: "OS `.*`" -> "$$OS" // Make sure we pretend the allocation symbols don't exist when there is no allocator -#![feature(start)] #![no_std] +#![no_main] extern "Rust" { fn __rust_alloc(size: usize, align: usize) -> *mut u8; } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { unsafe { __rust_alloc(1, 1); //~ERROR: unsupported operation: can't call foreign function `__rust_alloc` } diff --git a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr index e08a747f7fa..541af64b894 100644 --- a/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr +++ b/src/tools/miri/tests/fail/alloc/no_global_allocator.stderr @@ -7,7 +7,7 @@ LL | __rust_alloc(1, 1); = help: if this is a basic API commonly used on this target, please report an issue with Miri = help: however, note that Miri does not aim to support every FFI function out there; for instance, we will not support APIs for things such as GUIs, scripting languages, or databases = note: BACKTRACE: - = note: inside `start` at tests/fail/alloc/no_global_allocator.rs:LL:CC + = note: inside `miri_start` at tests/fail/alloc/no_global_allocator.rs:LL:CC error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs index 9c73bdc17be..791ffa7343d 100644 --- a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs +++ b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); -} +#[rustc_intrinsic] +unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize); fn main() { let mut data = [0u8; 16]; diff --git a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs index 281217f06f5..9a82c69fba8 100644 --- a/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs +++ b/src/tools/miri/tests/fail/intrinsics/copy_unaligned.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); -} +#[rustc_intrinsic] +unsafe fn copy_nonoverlapping<T>(_src: *const T, _dst: *mut T, _count: usize); fn main() { let mut data = [0u16; 8]; diff --git a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs index 0b34afc6090..e42811d9e13 100644 --- a/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs +++ b/src/tools/miri/tests/fail/intrinsics/ctlz_nonzero.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] mod rusti { - extern "rust-intrinsic" { - pub fn ctlz_nonzero<T>(x: T) -> u32; - } + #[rustc_intrinsic] + pub unsafe fn ctlz_nonzero<T>(_x: T) -> u32; } pub fn main() { diff --git a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs index e220411f585..e046a30e734 100644 --- a/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs +++ b/src/tools/miri/tests/fail/intrinsics/cttz_nonzero.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] mod rusti { - extern "rust-intrinsic" { - pub fn cttz_nonzero<T>(x: T) -> u32; - } + #[rustc_intrinsic] + pub unsafe fn cttz_nonzero<T>(_x: T) -> u32; } pub fn main() { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs index a57845426d5..d75046ff360 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs index d383fc5b50a..8d343cdc1bd 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs index a39a5066b6f..737a6fbafe0 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs index 71436eb3ba8..ee8b45c0aae 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs index 98ba964e47c..4bb5ded1033 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs index 424b8fd965e..6b42ae56ece 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs index 5c50926c4df..81019a1c608 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs index e0abd19d03f..24896bcae51 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs index f5f842e58ec..fbb67d28fed 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs index 244c25b31cb..93236bf4874 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs index f7a663d12a5..2770dea4406 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs index 171cbcc5934..1272566c07c 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs index 40b67e173b9..a1165794982 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs index e785123c4ca..0e68f4eaff7 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs index 4bf31d8ac02..ad3ac16dc6f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs index 9775a56724b..1addb9fb1d7 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs index 53ff06e1e46..a04c29c37da 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs index 44356ff1771..32bdcd07073 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs index 66f5be96bfd..861af44a66f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs index 18b380e8575..3b3e208f32f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs index 2a23b1dc8a4..81ca766de47 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs index 7fc3effda5d..2b437f38552 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs index 2a8f9c36642..94ee572f4d0 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.rs @@ -1,9 +1,8 @@ #![feature(intrinsics)] // Directly call intrinsic to avoid debug assertions in libstd -extern "rust-intrinsic" { - fn float_to_int_unchecked<Float: Copy, Int: Copy>(value: Float) -> Int; -} +#[rustc_intrinsic] +unsafe fn float_to_int_unchecked<Float: Copy, Int: Copy>(_value: Float) -> Int; fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/panic/no_std.rs b/src/tools/miri/tests/fail/panic/no_std.rs index 4d32b6d7461..cd8a3251fef 100644 --- a/src/tools/miri/tests/fail/panic/no_std.rs +++ b/src/tools/miri/tests/fail/panic/no_std.rs @@ -1,14 +1,15 @@ //@compile-flags: -Cpanic=abort -#![feature(start, core_intrinsics)] +#![feature(core_intrinsics)] #![no_std] +#![no_main] use core::fmt::Write; #[path = "../../utils/mod.no_std.rs"] mod utils; -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { panic!("blarg I am dead") } diff --git a/src/tools/miri/tests/fail/panic/no_std.stderr b/src/tools/miri/tests/fail/panic/no_std.stderr index c1cd53e310f..d54f2a58776 100644 --- a/src/tools/miri/tests/fail/panic/no_std.stderr +++ b/src/tools/miri/tests/fail/panic/no_std.stderr @@ -8,7 +8,7 @@ LL | core::intrinsics::abort(); | = note: BACKTRACE: = note: inside `panic_handler` at tests/fail/panic/no_std.rs:LL:CC -note: inside `start` +note: inside `miri_start` --> tests/fail/panic/no_std.rs:LL:CC | LL | panic!("blarg I am dead") diff --git a/src/tools/miri/tests/fail/rustc-error2.rs b/src/tools/miri/tests/fail/rustc-error2.rs index fd2c5393385..ec42fd17e89 100644 --- a/src/tools/miri/tests/fail/rustc-error2.rs +++ b/src/tools/miri/tests/fail/rustc-error2.rs @@ -4,7 +4,7 @@ struct Struct<T>(T); impl<T> std::ops::Deref for Struct<T> { type Target = dyn Fn(T); fn deref(&self) -> &assert_mem_uninitialized_valid::Target { - //~^ERROR: undeclared crate or module + //~^ERROR: use of unresolved module or unlinked crate unimplemented!() } } diff --git a/src/tools/miri/tests/fail/rustc-error2.stderr b/src/tools/miri/tests/fail/rustc-error2.stderr index cfbf305d3bb..62e3f392ea9 100644 --- a/src/tools/miri/tests/fail/rustc-error2.stderr +++ b/src/tools/miri/tests/fail/rustc-error2.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `assert_mem_uninitialized_valid` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `assert_mem_uninitialized_valid` --> tests/fail/rustc-error2.rs:LL:CC | LL | fn deref(&self) -> &assert_mem_uninitialized_valid::Target { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `assert_mem_uninitialized_valid` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `assert_mem_uninitialized_valid` + | + = help: you might be missing a crate named `assert_mem_uninitialized_valid` error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr b/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr index 6acd69ab3f8..33e1e53ea06 100644 --- a/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr +++ b/src/tools/miri/tests/fail/tail_calls/dangling-local-var.stderr @@ -14,8 +14,8 @@ LL | let local = 0; help: ALLOC was deallocated here: --> tests/fail/tail_calls/dangling-local-var.rs:LL:CC | -LL | } - | ^ +LL | become g(ptr) + | ^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): = note: inside `g` at tests/fail/tail_calls/dangling-local-var.rs:LL:CC note: inside `main` diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs index 3adeb89ecec..0ca13b5039d 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs @@ -235,7 +235,7 @@ fn concurrent_wait_wake() { static mut DATA: i32 = 0; static WOKEN: AtomicI32 = AtomicI32::new(0); - let rounds = 50; + let rounds = 64; for _ in 0..rounds { unsafe { DATA = 0 }; // Reset // Suppose the main thread is holding a lock implemented using futex... @@ -267,8 +267,7 @@ fn concurrent_wait_wake() { } }); // Increase the chance that the other thread actually goes to sleep. - // (5 yields in a loop seem to make that happen around 40% of the time.) - for _ in 0..5 { + for _ in 0..6 { thread::yield_now(); } diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.rs b/src/tools/miri/tests/pass/alloc-access-tracking.rs index 50e217918b0..c47063bef03 100644 --- a/src/tools/miri/tests/pass/alloc-access-tracking.rs +++ b/src/tools/miri/tests/pass/alloc-access-tracking.rs @@ -1,5 +1,5 @@ -#![feature(start)] #![no_std] +#![no_main] //@compile-flags: -Zmiri-track-alloc-id=21 -Zmiri-track-alloc-accesses -Cpanic=abort //@normalize-stderr-test: "id 21" -> "id $$ALLOC" //@only-target: linux # alloc IDs differ between OSes (due to extern static allocations) @@ -9,8 +9,8 @@ extern "Rust" { fn miri_dealloc(ptr: *mut u8, size: usize, align: usize); } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { unsafe { let ptr = miri_alloc(123, 1); *ptr = 42; // Crucially, only a write is printed here, no read! diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.stderr b/src/tools/miri/tests/pass/alloc-access-tracking.stderr index 451f5de25d3..0c85afd831b 100644 --- a/src/tools/miri/tests/pass/alloc-access-tracking.stderr +++ b/src/tools/miri/tests/pass/alloc-access-tracking.stderr @@ -5,7 +5,7 @@ LL | let ptr = miri_alloc(123, 1); | ^^^^^^^^^^^^^^^^^^ created Miri bare-metal heap allocation of 123 bytes (alignment ALIGN bytes) with id $ALLOC | = note: BACKTRACE: - = note: inside `start` at tests/pass/alloc-access-tracking.rs:LL:CC + = note: inside `miri_start` at tests/pass/alloc-access-tracking.rs:LL:CC note: tracking was triggered --> tests/pass/alloc-access-tracking.rs:LL:CC @@ -14,7 +14,7 @@ LL | *ptr = 42; // Crucially, only a write is printed here, no read! | ^^^^^^^^^ write access to allocation with id $ALLOC | = note: BACKTRACE: - = note: inside `start` at tests/pass/alloc-access-tracking.rs:LL:CC + = note: inside `miri_start` at tests/pass/alloc-access-tracking.rs:LL:CC note: tracking was triggered --> tests/pass/alloc-access-tracking.rs:LL:CC @@ -23,7 +23,7 @@ LL | assert_eq!(*ptr, 42); | ^^^^^^^^^^^^^^^^^^^^ read access to allocation with id $ALLOC | = note: BACKTRACE: - = note: inside `start` at RUSTLIB/core/src/macros/mod.rs:LL:CC + = note: inside `miri_start` at RUSTLIB/core/src/macros/mod.rs:LL:CC = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) note: tracking was triggered @@ -33,5 +33,5 @@ LL | miri_dealloc(ptr, 123, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^ freed allocation with id $ALLOC | = note: BACKTRACE: - = note: inside `start` at tests/pass/alloc-access-tracking.rs:LL:CC + = note: inside `miri_start` at tests/pass/alloc-access-tracking.rs:LL:CC diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index acd3502f528..0d0d79098d5 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -14,10 +14,9 @@ use std::ptr; use std::simd::StdFloat; use std::simd::prelude::*; -extern "rust-intrinsic" { - #[rustc_nounwind] - pub fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U; -} +#[rustc_intrinsic] +#[rustc_nounwind] +pub unsafe fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(_x: T, _y: T) -> U; fn simd_ops_f32() { let a = f32x4::splat(10.0); diff --git a/src/tools/miri/tests/pass/miri-alloc.rs b/src/tools/miri/tests/pass/miri-alloc.rs index 17f6d5d05a5..20269d8ced0 100644 --- a/src/tools/miri/tests/pass/miri-alloc.rs +++ b/src/tools/miri/tests/pass/miri-alloc.rs @@ -1,5 +1,5 @@ -#![feature(start)] #![no_std] +#![no_main] //@compile-flags: -Cpanic=abort // windows tls dtors go through libstd right now, thus this test // cannot pass. When windows tls dtors go through the special magic @@ -11,8 +11,8 @@ extern "Rust" { fn miri_dealloc(ptr: *mut u8, size: usize, align: usize); } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { unsafe { let ptr = miri_alloc(123, 1); core::ptr::write_bytes(ptr, 0u8, 123); diff --git a/src/tools/miri/tests/pass/miri_start.stdout b/src/tools/miri/tests/pass/miri_start.stdout deleted file mode 100644 index 1c9e8489b57..00000000000 --- a/src/tools/miri/tests/pass/miri_start.stdout +++ /dev/null @@ -1 +0,0 @@ -Hello from miri_start! diff --git a/src/tools/miri/tests/pass/no_std.rs b/src/tools/miri/tests/pass/no_std.rs deleted file mode 100644 index fc1c16f5fb9..00000000000 --- a/src/tools/miri/tests/pass/no_std.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@compile-flags: -Cpanic=abort -#![feature(start)] -#![no_std] - -use core::fmt::Write; - -#[path = "../utils/mod.no_std.rs"] -mod utils; - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - writeln!(utils::MiriStdout, "hello, world!").unwrap(); - 0 -} - -#[panic_handler] -fn panic_handler(_: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/src/tools/miri/tests/pass/miri_start.rs b/src/tools/miri/tests/pass/no_std_miri_start.rs index 756a1f60be1..cf9636b9d8c 100644 --- a/src/tools/miri/tests/pass/miri_start.rs +++ b/src/tools/miri/tests/pass/no_std_miri_start.rs @@ -1,6 +1,6 @@ //@compile-flags: -Cpanic=abort -#![no_main] #![no_std] +#![no_main] use core::fmt::Write; @@ -9,7 +9,7 @@ mod utils; #[no_mangle] fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { - writeln!(utils::MiriStdout, "Hello from miri_start!").unwrap(); + writeln!(utils::MiriStdout, "hello, world!").unwrap(); 0 } diff --git a/src/tools/miri/tests/pass/no_std.stdout b/src/tools/miri/tests/pass/no_std_miri_start.stdout index 270c611ee72..270c611ee72 100644 --- a/src/tools/miri/tests/pass/no_std.stdout +++ b/src/tools/miri/tests/pass/no_std_miri_start.stdout diff --git a/src/tools/miri/tests/pass/start.rs b/src/tools/miri/tests/pass/start.rs deleted file mode 100644 index f25d62fa8c3..00000000000 --- a/src/tools/miri/tests/pass/start.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(start)] - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - println!("Hello from start!"); - - 0 -} diff --git a/src/tools/miri/tests/pass/start.stdout b/src/tools/miri/tests/pass/start.stdout deleted file mode 100644 index d7f627d237c..00000000000 --- a/src/tools/miri/tests/pass/start.stdout +++ /dev/null @@ -1 +0,0 @@ -Hello from start! diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 06ed076a864..8b3bd77141b 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -69,6 +69,7 @@ change-id = 115898 [rust] channel = "{channel}" +verbose-tests = true [build] rustc = "{rustc}" @@ -102,13 +103,19 @@ llvm-config = "{llvm_config}" "tests/incremental", "tests/mir-opt", "tests/pretty", + "tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu", "tests/ui", "tests/crashes", ]; for test_path in env.skipped_tests() { args.extend(["--skip", test_path]); } - cmd(&args).env("COMPILETEST_FORCE_STAGE0", "1").run().context("Cannot execute tests") + cmd(&args) + .env("COMPILETEST_FORCE_STAGE0", "1") + // Also run dist-only tests + .env("COMPILETEST_ENABLE_DIST_TESTS", "1") + .run() + .context("Cannot execute tests") } /// Tries to find the version of the dist artifacts (either nightly, beta, or 1.XY.Z). diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index e73413085fa..b4dc753ab53 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -151,6 +151,61 @@ impl Command { self } + /// Set an auxiliary stream passed to the process, besides the stdio streams. + /// + /// # Notes + /// + /// Use with caution! Ideally, only set one aux fd; if there are multiple, their old `fd` may + /// overlap with another's `new_fd`, and may break. The caller must make sure this is not the + /// case. This function is only "safe" because the safety requirements are practically not + /// possible to uphold. + #[cfg(unix)] + pub fn set_aux_fd<F: Into<std::os::fd::OwnedFd>>( + &mut self, + new_fd: std::os::fd::RawFd, + fd: F, + ) -> &mut Self { + use std::mem; + // NOTE: If more than 1 auxiliary file descriptor is needed, this function should be + // rewritten. + use std::os::fd::AsRawFd; + use std::os::unix::process::CommandExt; + + let cvt = |x| if x == -1 { Err(std::io::Error::last_os_error()) } else { Ok(()) }; + + // Ensure fd stays open until the fork. + let fd = mem::ManuallyDrop::new(fd.into()); + let fd = fd.as_raw_fd(); + + if fd == new_fd { + // If the new file descriptor is already the same as fd, just turn off `FD_CLOEXEC`. + let fd_flags = { + let ret = unsafe { libc::fcntl(fd, libc::F_GETFD, 0) }; + if ret < 0 { + panic!("failed to read fd flags: {}", std::io::Error::last_os_error()); + } + ret + }; + // Clear `FD_CLOEXEC`. + let fd_flags = fd_flags & !libc::FD_CLOEXEC; + + // SAFETY(io-safety): `fd` is already owned. + cvt(unsafe { libc::fcntl(fd, libc::F_SETFD, fd_flags as libc::c_int) }) + .expect("disabling CLOEXEC failed"); + } + let pre_exec = move || { + if fd.as_raw_fd() != new_fd { + // SAFETY(io-safety): it's the caller's responsibility that we won't override the + // target fd. + cvt(unsafe { libc::dup2(fd, new_fd) })?; + } + Ok(()) + }; + // SAFETY(pre-exec-safe): `dup2` is pre-exec-safe. + unsafe { self.cmd.pre_exec(pre_exec) }; + self + } + /// Run the constructed command and assert that it is successfully run. /// /// By default, std{in,out,err} are [`Stdio::piped()`]. diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index ffd4ca22a00..7316244b384 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -90,7 +90,7 @@ pub use artifact_names::{ /// Path-related helpers. pub use path_helpers::{ cwd, filename_contains, filename_not_in_denylist, has_extension, has_prefix, has_suffix, - not_contains, path, shallow_find_files, source_root, + not_contains, path, shallow_find_files, build_root, source_root, }; /// Helpers for scoped test execution where certain properties are attempted to be maintained. diff --git a/src/tools/run-make-support/src/macros.rs b/src/tools/run-make-support/src/macros.rs index cc3d1281d0a..94955aefe57 100644 --- a/src/tools/run-make-support/src/macros.rs +++ b/src/tools/run-make-support/src/macros.rs @@ -104,6 +104,17 @@ macro_rules! impl_common_helpers { self } + /// Set an auxiliary stream passed to the process, besides the stdio streams. + #[cfg(unix)] + pub fn set_aux_fd<F: Into<std::os::fd::OwnedFd>>( + &mut self, + new_fd: std::os::fd::RawFd, + fd: F, + ) -> &mut Self { + self.cmd.set_aux_fd(new_fd, fd); + self + } + /// Run the constructed command and assert that it is successfully run. #[track_caller] pub fn run(&mut self) -> crate::command::CompletedProcess { diff --git a/src/tools/run-make-support/src/path_helpers.rs b/src/tools/run-make-support/src/path_helpers.rs index 87901793a92..1c59f2feea4 100644 --- a/src/tools/run-make-support/src/path_helpers.rs +++ b/src/tools/run-make-support/src/path_helpers.rs @@ -34,6 +34,12 @@ pub fn source_root() -> PathBuf { env_var("SOURCE_ROOT").into() } +/// Path to the build directory root. +#[must_use] +pub fn build_root() -> PathBuf { + env_var("BUILD_ROOT").into() +} + /// Browse the directory `path` non-recursively and return all files which respect the parameters /// outlined by `closure`. #[track_caller] diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 48b5f3aabfc..f92668a6a97 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -98,9 +98,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "borsh" @@ -194,9 +194,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chalk-derive" -version = "0.98.0" +version = "0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9426c8fd0fe61c3da880b801d3b510524df17843a8f9ec1f5b9cec24fb7412df" +checksum = "572583d9b97f9d277e5c7607f8239a30e2e04d3ed3b47c87d1cb2152ae724073" dependencies = [ "proc-macro2", "quote", @@ -206,19 +206,19 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.98.0" +version = "0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f2eb1cd6054da221bd1ac0197fb2fe5e2caf3dcb93619398fc1433f8f09093" +checksum = "e60e0ef9c81dce1336a9ed3c76f08775f5b623151d96d85ba45f7b10de76d1c7" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "chalk-derive", ] [[package]] name = "chalk-recursive" -version = "0.98.0" +version = "0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129dc03458f71cfb9c3cd621c9c68166a94e87b85b16ccd29af015d7ff9a1c61" +checksum = "5a06350d614e22b03a69b8105e3541614450a7ea48bc58ecc6c6bd92731a3995" dependencies = [ "chalk-derive", "chalk-ir", @@ -229,9 +229,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.98.0" +version = "0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7e8a8c1e928f98cdf227b868416ef21dcd8cc3c61b347576d783713444d41c8" +checksum = "0e428761e9b55bee516bfe2457caed8b6d1b86353f92ae825bbe438a36ce91e8" dependencies = [ "chalk-derive", "chalk-ir", @@ -523,6 +523,7 @@ dependencies = [ "hir-def", "hir-expand", "hir-ty", + "indexmap", "intern", "itertools", "rustc-hash 2.0.0", @@ -544,7 +545,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.6.0", + "bitflags 2.7.0", "cfg", "cov-mark", "dashmap", @@ -610,7 +611,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.6.0", + "bitflags 2.7.0", "chalk-derive", "chalk-ir", "chalk-recursive", @@ -734,7 +735,7 @@ version = "0.0.0" dependencies = [ "arrayvec", "base-db", - "bitflags 2.6.0", + "bitflags 2.7.0", "cov-mark", "crossbeam-channel", "either", @@ -820,11 +821,11 @@ dependencies = [ [[package]] name = "inotify" -version = "0.9.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.7.0", "inotify-sys", "libc", ] @@ -908,9 +909,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libloading" @@ -938,7 +939,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "libc", "redox_syscall", ] @@ -1117,14 +1118,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1142,7 +1143,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "cfg-if", "cfg_aliases 0.1.1", "libc", @@ -1156,12 +1157,11 @@ checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" [[package]] name = "notify" -version = "6.1.1" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" dependencies = [ - "bitflags 2.6.0", - "crossbeam-channel", + "bitflags 2.7.0", "filetime", "fsevent-sys", "inotify", @@ -1169,11 +1169,18 @@ dependencies = [ "libc", "log", "mio", + "notify-types", "walkdir", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] +name = "notify-types" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" + +[[package]] name = "nu-ansi-term" version = "0.50.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1371,6 +1378,7 @@ version = "0.0.0" dependencies = [ "expect-test", "intern", + "libc", "libloading", "memmap2", "object 0.33.0", @@ -1428,7 +1436,7 @@ dependencies = [ "libc", "perf-event", "tikv-jemalloc-ctl", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1482,7 +1490,7 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "memchr", "unicase", ] @@ -1507,20 +1515,20 @@ dependencies = [ [[package]] name = "ra-ap-rustc_abi" -version = "0.87.0" +version = "0.91.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b782af0a7a8df16ddf43cd70da9f17bc3b1ce712c9e4992b6edb16f5f53632" +checksum = "d5246e9e1f450333a990877eabbc36fe0567e7cedd56d5365db319e14079cf2a" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "ra-ap-rustc_index", "tracing", ] [[package]] name = "ra-ap-rustc_index" -version = "0.87.0" +version = "0.91.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce5742f134960482f543b35ecebec3cacc6d79a9a685713518b4d8d70c5f9aa8" +checksum = "59fd8e4f5b34c434ec111efb0e0614954db048b9307d3b2e4cc3c915da9d2160" dependencies = [ "ra-ap-rustc_index_macros", "smallvec", @@ -1528,9 +1536,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_index_macros" -version = "0.87.0" +version = "0.91.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ea011fcf68309a8835ad01d91c032cb18444617b00e2cab21d45b208164441" +checksum = "2d34973fe081392bd1edb022e865e9952fcaa093f9cdae183edce64472e5e889" dependencies = [ "proc-macro2", "quote", @@ -1539,9 +1547,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_lexer" -version = "0.87.0" +version = "0.91.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb76f0a4d4c20859e41f0a23bff0f37ab9ca9171c214a6c7dd72ea69434865dc" +checksum = "52fa42c582e21b35e8f61a5afe3c63a9c722d995826762eb19b18beeccf5157f" dependencies = [ "unicode-properties", "unicode-xid", @@ -1549,9 +1557,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_parse_format" -version = "0.87.0" +version = "0.91.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06080bd35078305421a62da77f3c128482d8d44441b6da8ce9d146d1cd9cdb5b" +checksum = "740383328d7033393e5385f4a6073b880d5811b0fc0fd2559e481f905940f2f8" dependencies = [ "ra-ap-rustc_index", "ra-ap-rustc_lexer", @@ -1559,9 +1567,9 @@ dependencies = [ [[package]] name = "ra-ap-rustc_pattern_analysis" -version = "0.87.0" +version = "0.91.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a3154fe4c20c177d7b3c678a2d3a97aba0cca156ddef88959915041889daf0" +checksum = "c39f544728f32cebffb1a8b92ba3c1f3dcb4144081438d192137ed197d479a9d" dependencies = [ "ra-ap-rustc_index", "rustc-hash 2.0.0", @@ -1626,7 +1634,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", ] [[package]] @@ -1713,7 +1721,7 @@ dependencies = [ "vfs", "vfs-notify", "walkdir", - "windows-sys 0.52.0", + "windows-sys 0.59.0", "xflags", "xshell", ] @@ -1936,7 +1944,7 @@ dependencies = [ "jod-thread", "libc", "miow", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 9440123de70..1029844cd3a 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -4,7 +4,7 @@ exclude = ["crates/proc-macro-srv/proc-macro-test/imp"] resolver = "2" [workspace.package] -rust-version = "1.82" +rust-version = "1.83" edition = "2021" license = "MIT OR Apache-2.0" authors = ["rust-analyzer team"] @@ -79,6 +79,7 @@ span = { path = "./crates/span", version = "0.0.0" } stdx = { path = "./crates/stdx", version = "0.0.0" } syntax = { path = "./crates/syntax", version = "0.0.0" } syntax-bridge = { path = "./crates/syntax-bridge", version = "0.0.0" } +test-fixture = { path = "./crates/test-fixture", version = "0.0.0" } test-utils = { path = "./crates/test-utils", version = "0.0.0" } toolchain = { path = "./crates/toolchain", version = "0.0.0" } tt = { path = "./crates/tt", version = "0.0.0" } @@ -86,16 +87,15 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" } vfs = { path = "./crates/vfs", version = "0.0.0" } edition = { path = "./crates/edition", version = "0.0.0" } -ra-ap-rustc_lexer = { version = "0.87", default-features = false } -ra-ap-rustc_parse_format = { version = "0.87", default-features = false } -ra-ap-rustc_index = { version = "0.87", default-features = false } -ra-ap-rustc_abi = { version = "0.87", default-features = false } -ra-ap-rustc_pattern_analysis = { version = "0.87", default-features = false } +ra-ap-rustc_lexer = { version = "0.91", default-features = false } +ra-ap-rustc_parse_format = { version = "0.91", default-features = false } +ra-ap-rustc_index = { version = "0.91", default-features = false } +ra-ap-rustc_abi = { version = "0.91", default-features = false } +ra-ap-rustc_pattern_analysis = { version = "0.91", default-features = false } # local crates that aren't published to crates.io. These should not have versions. -test-fixture = { path = "./crates/test-fixture" } -# In-tree crates that are published separately and follow semver. See lib/README.md +# in-tree crates that are published separately and follow semver. See lib/README.md line-index = { version = "0.1.2" } la-arena = { version = "0.3.1" } lsp-server = { version = "0.7.6" } @@ -106,10 +106,10 @@ arrayvec = "0.7.4" bitflags = "2.4.1" cargo_metadata = "0.18.1" camino = "1.1.6" -chalk-solve = { version = "0.98.0", default-features = false } -chalk-ir = "0.98.0" -chalk-recursive = { version = "0.98.0", default-features = false } -chalk-derive = "0.98.0" +chalk-solve = { version = "0.99.0", default-features = false } +chalk-ir = "0.99.0" +chalk-recursive = { version = "0.99.0", default-features = false } +chalk-derive = "0.99.0" crossbeam-channel = "0.5.8" dissimilar = "1.0.7" dot = "0.1.4" diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs index 0a9e83bc3ba..c7e4168f6bc 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs @@ -136,7 +136,7 @@ pub trait SourceRootDatabase: SourceDatabase { #[ra_salsa::input] fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>; - /// Crates whose root fool is in `id`. + /// Crates whose root file is in `id`. fn source_root_crates(&self, id: SourceRootId) -> Arc<[CrateId]>; } diff --git a/src/tools/rust-analyzer/crates/edition/src/lib.rs b/src/tools/rust-analyzer/crates/edition/src/lib.rs index c25d5b9557b..7e9c94af408 100644 --- a/src/tools/rust-analyzer/crates/edition/src/lib.rs +++ b/src/tools/rust-analyzer/crates/edition/src/lib.rs @@ -5,7 +5,8 @@ use std::fmt; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(u8)] pub enum Edition { - Edition2015, + // The syntax context stuff needs the discriminants to start from 0 and be consecutive. + Edition2015 = 0, Edition2018, Edition2021, Edition2024, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 37e2a99e60f..710bffcefe9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -122,6 +122,11 @@ impl Attrs { AttrQuery { attrs: self, key } } + pub fn rust_analyzer_tool(&self) -> impl Iterator<Item = &Attr> { + self.iter() + .filter(|&attr| attr.path.segments().first().is_some_and(|s| *s == sym::rust_analyzer)) + } + pub fn cfg(&self) -> Option<CfgExpr> { let mut cfgs = self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse); let first = cfgs.next()?; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index 433a956ff9a..de439249306 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -15,7 +15,7 @@ use hir_expand::{name::Name, ExpandError, InFile}; use la_arena::{Arena, ArenaMap, Idx, RawIdx}; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use span::{Edition, MacroFileId}; +use span::{Edition, MacroFileId, SyntaxContextData}; use syntax::{ast, AstPtr, SyntaxNodePtr}; use triomphe::Arc; use tt::TextRange; @@ -37,15 +37,22 @@ use crate::{ /// A wrapper around [`span::SyntaxContextId`] that is intended only for comparisons. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct HygieneId(pub(crate) span::SyntaxContextId); +pub struct HygieneId(span::SyntaxContextId); impl HygieneId { - pub const ROOT: Self = Self(span::SyntaxContextId::ROOT); + // The edition doesn't matter here, we only use this for comparisons and to lookup the macro. + pub const ROOT: Self = Self(span::SyntaxContextId::root(Edition::Edition2015)); - pub fn new(ctx: span::SyntaxContextId) -> Self { + pub fn new(mut ctx: span::SyntaxContextId) -> Self { + // See `Name` for why we're doing that. + ctx.remove_root_edition(); Self(ctx) } + pub(crate) fn lookup(self, db: &dyn DefDatabase) -> SyntaxContextData { + db.lookup_intern_syntax_context(self.0) + } + pub(crate) fn is_root(self) -> bool { self.0.is_root() } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs index 10b84d041bd..1327bb3ab59 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs @@ -8,6 +8,7 @@ use std::mem; use base_db::CrateId; use either::Either; use hir_expand::{ + mod_path::tool_path, name::{AsName, Name}, span_map::{ExpansionSpanMap, SpanMap}, InFile, MacroDefId, @@ -27,6 +28,7 @@ use text_size::TextSize; use triomphe::Arc; use crate::{ + attr::Attrs, body::{Body, BodyDiagnostic, BodySourceMap, ExprPtr, HygieneId, LabelPtr, PatPtr}, builtin_type::BuiltinUint, data::adt::StructKind, @@ -212,6 +214,43 @@ impl ExprCollector<'_> { body: Option<ast::Expr>, is_async_fn: bool, ) -> (Body, BodySourceMap) { + let skip_body = match self.owner { + DefWithBodyId::FunctionId(it) => self.db.attrs(it.into()), + DefWithBodyId::StaticId(it) => self.db.attrs(it.into()), + DefWithBodyId::ConstId(it) => self.db.attrs(it.into()), + DefWithBodyId::InTypeConstId(_) => Attrs::EMPTY, + DefWithBodyId::VariantId(it) => self.db.attrs(it.into()), + } + .rust_analyzer_tool() + .any(|attr| *attr.path() == tool_path![skip]); + // If #[rust_analyzer::skip] annotated, only construct enough information for the signature + // and skip the body. + if skip_body { + self.body.body_expr = self.missing_expr(); + if let Some((param_list, mut attr_enabled)) = param_list { + if let Some(self_param) = + param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false)) + { + let is_mutable = + self_param.mut_token().is_some() && self_param.amp_token().is_none(); + let binding_id: la_arena::Idx<Binding> = self.alloc_binding( + Name::new_symbol_root(sym::self_.clone()), + BindingAnnotation::new(is_mutable, false), + ); + self.body.self_param = Some(binding_id); + self.source_map.self_param = + Some(self.expander.in_file(AstPtr::new(&self_param))); + } + self.body.params = param_list + .params() + .zip(attr_enabled) + .filter(|(_, enabled)| *enabled) + .map(|_| self.missing_pat()) + .collect(); + }; + return (self.body, self.source_map); + } + self.awaitable_context.replace(if is_async_fn { Awaitable::Yes } else { @@ -542,10 +581,7 @@ impl ExprCollector<'_> { let mutability = if raw_tok { if e.mut_token().is_some() { Mutability::Mut - } else if e.const_token().is_some() { - Mutability::Shared } else { - never!("parser only remaps to raw_token() if matching mutability token follows"); Mutability::Shared } } else { @@ -2460,7 +2496,7 @@ impl ExprCollector<'_> { None => HygieneId::ROOT, Some(span_map) => { let ctx = span_map.span_at(span_start).ctx; - HygieneId(self.db.lookup_intern_syntax_context(ctx).opaque_and_semitransparent) + HygieneId::new(self.db.lookup_intern_syntax_context(ctx).opaque_and_semitransparent) } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs index 63a7a9af201..08af470b965 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/scope.rs @@ -345,7 +345,7 @@ mod tests { } } - fn do_check(ra_fixture: &str, expected: &[&str]) { + fn do_check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: &[&str]) { let (offset, code) = extract_offset(ra_fixture); let code = { let mut buf = String::new(); @@ -509,7 +509,7 @@ fn foo() { ); } - fn do_check_local_name(ra_fixture: &str, expected_offset: u32) { + fn do_check_local_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_offset: u32) { let (db, position) = TestDB::with_position(ra_fixture); let file_id = position.file_id; let offset = position.offset; diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs index 7e15a9f2d61..edc7c4c1f21 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs @@ -7,7 +7,7 @@ use crate::{test_db::TestDB, ModuleDefId}; use super::*; -fn lower(ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) { +fn lower(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) { let db = TestDB::with_files(ra_fixture); let krate = db.fetch_test_crate(); @@ -27,14 +27,14 @@ fn lower(ra_fixture: &str) -> (TestDB, Arc<Body>, DefWithBodyId) { (db, body, fn_def) } -fn def_map_at(ra_fixture: &str) -> String { +fn def_map_at(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String { let (db, position) = TestDB::with_position(ra_fixture); let module = db.module_at_position(position); module.def_map(&db).dump(&db) } -fn check_block_scopes_at(ra_fixture: &str, expect: Expect) { +fn check_block_scopes_at(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (db, position) = TestDB::with_position(ra_fixture); let module = db.module_at_position(position); @@ -42,7 +42,7 @@ fn check_block_scopes_at(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual); } -fn check_at(ra_fixture: &str, expect: Expect) { +fn check_at(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let actual = def_map_at(ra_fixture); expect.assert_eq(&actual); } @@ -444,3 +444,18 @@ fn foo() { }"# ); } + +#[test] +fn skip_skips_body() { + let (db, body, owner) = lower( + r#" +#[rust_analyzer::skip] +async fn foo(a: (), b: i32) -> u32 { + 0 + 1 + b() +} +"#, + ); + let printed = body.pretty_print(&db, owner, Edition::CURRENT); + expect!["fn foo(�: (), �: i32) -> impl ::core::future::Future::<Output = u32> �"] + .assert_eq(&printed); +} diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs index d85bc9a4320..12f5f6ad79a 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs @@ -244,7 +244,7 @@ bitflags::bitflags! { #[derive(Debug, Clone, PartialEq, Eq)] pub struct TraitData { pub name: Name, - pub items: Vec<(Name, AssocItemId)>, + pub items: Box<[(Name, AssocItemId)]>, pub flags: TraitFlags, pub visibility: RawVisibility, // box it as the vec is usually empty anyways @@ -360,7 +360,7 @@ impl TraitAliasData { pub struct ImplData { pub target_trait: Option<TraitRef>, pub self_ty: TypeRefId, - pub items: Box<[AssocItemId]>, + pub items: Box<[(Name, AssocItemId)]>, pub is_negative: bool, pub is_unsafe: bool, // box it as the vec is usually empty anyways @@ -393,7 +393,6 @@ impl ImplData { collector.collect(&item_tree, tree_id.tree_id(), &impl_def.items); let (items, macro_calls, diagnostics) = collector.finish(); - let items = items.into_iter().map(|(_, item)| item).collect(); ( Arc::new(ImplData { @@ -648,12 +647,12 @@ impl<'a> AssocItemCollector<'a> { fn finish( self, ) -> ( - Vec<(Name, AssocItemId)>, + Box<[(Name, AssocItemId)]>, Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>, Vec<DefDiagnostic>, ) { ( - self.items, + self.items.into_boxed_slice(), if self.macro_calls.is_empty() { None } else { Some(Box::new(self.macro_calls)) }, self.diagnostics, ) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs index 5315c1c6fbd..108258d5a11 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs @@ -10,7 +10,7 @@ use hir_expand::{ ExpandResult, HirFileId, InFile, Lookup, MacroCallId, }; use limit::Limit; -use span::SyntaxContextId; +use span::{Edition, SyntaxContextId}; use syntax::{ast, Parse}; use triomphe::Arc; @@ -60,7 +60,7 @@ impl Expander { pub fn syntax_context(&self) -> SyntaxContextId { // FIXME: - SyntaxContextId::ROOT + SyntaxContextId::root(Edition::CURRENT) } pub fn enter_expand<T: ast::AstNode>( diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs index a615abd1bbe..5d67902c8ac 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs @@ -665,7 +665,7 @@ mod tests { /// module the cursor is in. #[track_caller] fn check_found_path_( - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, path: &str, prefer_prelude: bool, prefer_absolute: bool, @@ -727,19 +727,35 @@ mod tests { expect.assert_eq(&res); } - fn check_found_path(ra_fixture: &str, path: &str, expect: Expect) { + fn check_found_path( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + path: &str, + expect: Expect, + ) { check_found_path_(ra_fixture, path, false, false, false, expect); } - fn check_found_path_prelude(ra_fixture: &str, path: &str, expect: Expect) { + fn check_found_path_prelude( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + path: &str, + expect: Expect, + ) { check_found_path_(ra_fixture, path, true, false, false, expect); } - fn check_found_path_absolute(ra_fixture: &str, path: &str, expect: Expect) { + fn check_found_path_absolute( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + path: &str, + expect: Expect, + ) { check_found_path_(ra_fixture, path, false, true, false, expect); } - fn check_found_path_prefer_no_std(ra_fixture: &str, path: &str, expect: Expect) { + fn check_found_path_prefer_no_std( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + path: &str, + expect: Expect, + ) { check_found_path_(ra_fixture, path, false, false, true, expect); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs index 9574e5d9cd3..ac262950f13 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs @@ -509,7 +509,12 @@ mod tests { } } - fn check_search(ra_fixture: &str, crate_name: &str, query: Query, expect: Expect) { + fn check_search( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + crate_name: &str, + query: Query, + expect: Expect, + ) { let db = TestDB::with_files(ra_fixture); let crate_graph = db.crate_graph(); let krate = crate_graph @@ -587,7 +592,7 @@ mod tests { )) } - fn check(ra_fixture: &str, expect: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let db = TestDB::with_files(ra_fixture); let crate_graph = db.crate_graph(); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs index 2c3eb5c8e5e..0fec7674109 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs @@ -162,6 +162,20 @@ impl ItemScope { .map(move |name| (name, self.get(name))) } + pub fn values(&self) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportId>)> + '_ { + self.values.iter().map(|(n, &i)| (n, i)) + } + + pub fn types( + &self, + ) -> impl Iterator<Item = (&Name, Item<ModuleDefId, ImportOrExternCrate>)> + '_ { + self.types.iter().map(|(n, &i)| (n, i)) + } + + pub fn macros(&self) -> impl Iterator<Item = (&Name, Item<MacroId, ImportId>)> + '_ { + self.macros.iter().map(|(n, &i)| (n, i)) + } + pub fn imports(&self) -> impl Iterator<Item = ImportId> + '_ { self.use_imports_types .keys() @@ -263,11 +277,6 @@ impl ItemScope { self.unnamed_consts.iter().copied() } - /// Iterate over all module scoped macros - pub(crate) fn macros(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ { - self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) - } - /// Iterate over all legacy textual scoped macros visible at the end of the module pub fn legacy_macros(&self) -> impl Iterator<Item = (&Name, &[MacroId])> + '_ { self.legacy_macros.iter().map(|(name, def)| (name, &**def)) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs index 0f53969d6c7..80b699649fb 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs @@ -4,7 +4,7 @@ use test_fixture::WithFixture; use crate::{db::DefDatabase, test_db::TestDB}; -fn check(ra_fixture: &str, expect: Expect) { +fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (db, file_id) = TestDB::with_single_file(ra_fixture); let item_tree = db.file_item_tree(file_id.into()); let pretty = item_tree.pretty_print(&db, Edition::CURRENT); @@ -270,7 +270,7 @@ m!(); // AstId: 2 pub macro m2 { ... } - // AstId: 3, SyntaxContext: 0, ExpandTo: Items + // AstId: 3, SyntaxContext: 2, ExpandTo: Items m!(...); "#]], ); diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 0629d87e544..afdc49a2dc5 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -107,7 +107,7 @@ impl LangItems { for (_, module_data) in crate_def_map.modules() { for impl_def in module_data.scope.impls() { lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef); - for assoc in db.impl_data(impl_def).items.iter().copied() { + for &(_, assoc) in db.impl_data(impl_def).items.iter() { match assoc { AssocItemId::FunctionId(f) => { lang_items.collect_lang_item(db, f, LangItemTarget::Function) diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs index 8af27513ebc..84c105a0a34 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs @@ -502,7 +502,7 @@ impl ModuleId { } /// Whether this module represents the crate root module - fn is_crate_root(&self) -> bool { + pub fn is_crate_root(&self) -> bool { self.local_id == DefMap::ROOT && self.block.is_none() } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs index 511626b5ed9..8c5bd3b6d36 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -35,9 +35,9 @@ macro_rules! f { }; } -struct#0:1@58..64#1# MyTraitMap2#0:2@31..42#0# {#0:1@72..73#1# - map#0:1@86..89#1#:#0:1@89..90#1# #0:1@89..90#1#::#0:1@91..93#1#std#0:1@93..96#1#::#0:1@96..98#1#collections#0:1@98..109#1#::#0:1@109..111#1#HashSet#0:1@111..118#1#<#0:1@118..119#1#(#0:1@119..120#1#)#0:1@120..121#1#>#0:1@121..122#1#,#0:1@122..123#1# -}#0:1@132..133#1# +struct#0:1@58..64#4# MyTraitMap2#0:2@31..42#2# {#0:1@72..73#4# + map#0:1@86..89#4#:#0:1@89..90#4# #0:1@89..90#4#::#0:1@91..93#4#std#0:1@93..96#4#::#0:1@96..98#4#collections#0:1@98..109#4#::#0:1@109..111#4#HashSet#0:1@111..118#4#<#0:1@118..119#4#(#0:1@119..120#4#)#0:1@120..121#4#>#0:1@121..122#4#,#0:1@122..123#4# +}#0:1@132..133#4# "#]], ); } @@ -75,12 +75,12 @@ macro_rules! f { }; } -fn#0:2@30..32#0# main#0:2@33..37#0#(#0:2@37..38#0#)#0:2@38..39#0# {#0:2@40..41#0# - 1#0:2@50..51#0#;#0:2@51..52#0# - 1.0#0:2@61..64#0#;#0:2@64..65#0# - (#0:2@74..75#0#(#0:2@75..76#0#1#0:2@76..77#0#,#0:2@77..78#0# )#0:2@78..79#0#,#0:2@79..80#0# )#0:2@80..81#0#.#0:2@81..82#0#0#0:2@82..85#0#.#0:2@82..85#0#0#0:2@82..85#0#;#0:2@85..86#0# - let#0:2@95..98#0# x#0:2@99..100#0# =#0:2@101..102#0# 1#0:2@103..104#0#;#0:2@104..105#0# -}#0:2@110..111#0# +fn#0:2@30..32#2# main#0:2@33..37#2#(#0:2@37..38#2#)#0:2@38..39#2# {#0:2@40..41#2# + 1#0:2@50..51#2#;#0:2@51..52#2# + 1.0#0:2@61..64#2#;#0:2@64..65#2# + (#0:2@74..75#2#(#0:2@75..76#2#1#0:2@76..77#2#,#0:2@77..78#2# )#0:2@78..79#2#,#0:2@79..80#2# )#0:2@80..81#2#.#0:2@81..82#2#0#0:2@82..85#2#.#0:2@82..85#2#0#0:2@82..85#2#;#0:2@85..86#2# + let#0:2@95..98#2# x#0:2@99..100#2# =#0:2@101..102#2# 1#0:2@103..104#2#;#0:2@104..105#2# +}#0:2@110..111#2# "#]], @@ -171,7 +171,7 @@ fn main(foo: ()) { } fn main(foo: ()) { - /* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#0#; + /* error: unresolved macro unresolved */"helloworld!"#0:3@236..321#2#; } } @@ -197,7 +197,7 @@ macro_rules! mk_struct { #[macro_use] mod foo; -struct#1:1@59..65#1# Foo#0:2@32..35#0#(#1:1@70..71#1#u32#0:2@41..44#0#)#1:1@74..75#1#;#1:1@75..76#1# +struct#1:1@59..65#4# Foo#0:2@32..35#2#(#1:1@70..71#4#u32#0:2@41..44#2#)#1:1@74..75#4#;#1:1@75..76#4# "#]], ); } @@ -423,10 +423,10 @@ m! { foo, bar } macro_rules! m { ($($i:ident),*) => ( impl Bar { $(fn $i() {})* } ); } -impl#\1# Bar#\1# {#\1# - fn#\1# foo#\0#(#\1#)#\1# {#\1#}#\1# - fn#\1# bar#\0#(#\1#)#\1# {#\1#}#\1# -}#\1# +impl#\4# Bar#\4# {#\4# + fn#\4# foo#\2#(#\4#)#\4# {#\4#}#\4# + fn#\4# bar#\2#(#\4#)#\4# {#\4#}#\4# +}#\4# "#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs index 5b9ffdf37be..408d03ff718 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -47,7 +47,7 @@ use crate::{ }; #[track_caller] -fn check_errors(ra_fixture: &str, expect: Expect) { +fn check_errors(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let db = TestDB::with_files(ra_fixture); let krate = db.fetch_test_crate(); let def_map = db.crate_def_map(krate); @@ -77,7 +77,7 @@ fn check_errors(ra_fixture: &str, expect: Expect) { } #[track_caller] -fn check(ra_fixture: &str, mut expect: Expect) { +fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, mut expect: Expect) { let extra_proc_macros = vec![( r#" #[proc_macro_attribute] @@ -358,6 +358,7 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander { let (parse, _) = syntax_bridge::token_tree_to_syntax_node( subtree, syntax_bridge::TopEntryPoint::MacroItems, + &mut |_| span::Edition::CURRENT, span::Edition::CURRENT, ); if parse.errors().is_empty() { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs index c0178adc9a6..70e3e1ed4e9 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/proc_macros.rs @@ -181,9 +181,9 @@ fn foo(&self) { self.0. 1; } -fn#0:1@45..47#0# foo#0:1@48..51#0#(#0:1@51..52#0#�:1@52..53#0#self#0:1@53..57#0# )#0:1@57..58#0# {#0:1@59..60#0# - self#0:1@65..69#0# .#0:1@69..70#0#0#0:1@70..71#0#.#0:1@71..72#0#1#0:1@73..74#0#;#0:1@74..75#0# -}#0:1@76..77#0#"#]], +fn#0:1@45..47#2# foo#0:1@48..51#2#(#0:1@51..52#2#�:1@52..53#2#self#0:1@53..57#2# )#0:1@57..58#2# {#0:1@59..60#2# + self#0:1@65..69#2# .#0:1@69..70#2#0#0:1@70..71#2#.#0:1@71..72#2#1#0:1@73..74#2#;#0:1@74..75#2# +}#0:1@76..77#2#"#]], ); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs index 8beeda82bca..1e4b42dff5f 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs @@ -74,7 +74,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI let proc_macros = if krate.is_proc_macro { db.proc_macros() - .for_crate(def_map.krate, db.syntax_context(tree_id.file_id())) + .for_crate(def_map.krate, db.syntax_context(tree_id.file_id(), krate.edition)) .unwrap_or_default() } else { Default::default() @@ -717,8 +717,8 @@ impl DefCollector<'_> { } } None => { - for (name, def) in root_scope.macros() { - self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate)); + for (name, it) in root_scope.macros() { + self.def_map.macro_use_prelude.insert(name.clone(), (it.def, extern_crate)); } } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs index 32c158415ba..318aee04f7b 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs @@ -11,19 +11,19 @@ use triomphe::Arc; use crate::{db::DefDatabase, nameres::DefMap, test_db::TestDB}; -fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { +fn compute_crate_def_map(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> Arc<DefMap> { let db = TestDB::with_files(ra_fixture); let krate = db.fetch_test_crate(); db.crate_def_map(krate) } -fn render_crate_def_map(ra_fixture: &str) -> String { +fn render_crate_def_map(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String { let db = TestDB::with_files(ra_fixture); let krate = db.fetch_test_crate(); db.crate_def_map(krate).dump(&db) } -fn check(ra_fixture: &str, expect: Expect) { +fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let actual = render_crate_def_map(ra_fixture); expect.assert_eq(&actual); } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index 82da57a9bb2..0b9b6da8d51 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs @@ -166,6 +166,17 @@ impl Resolver { db: &dyn DefDatabase, path: &Path, ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> { + self.resolve_path_in_type_ns_with_prefix_info(db, path).map( + |(resolution, remaining_segments, import, _)| (resolution, remaining_segments, import), + ) + } + + pub fn resolve_path_in_type_ns_with_prefix_info( + &self, + db: &dyn DefDatabase, + path: &Path, + ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)> + { let path = match path { Path::BarePath(mod_path) => mod_path, Path::Normal(it) => it.mod_path(), @@ -181,7 +192,12 @@ impl Resolver { | LangItemTarget::ImplDef(_) | LangItemTarget::Static(_) => return None, }; - return Some((type_ns, seg.as_ref().map(|_| 1), None)); + return Some(( + type_ns, + seg.as_ref().map(|_| 1), + None, + ResolvePathResultPrefixInfo::default(), + )); } }; let first_name = path.segments().first()?; @@ -197,17 +213,32 @@ impl Resolver { Scope::ExprScope(_) | Scope::MacroDefScope(_) => continue, Scope::GenericParams { params, def } => { if let Some(id) = params.find_type_by_name(first_name, *def) { - return Some((TypeNs::GenericParam(id), remaining_idx(), None)); + return Some(( + TypeNs::GenericParam(id), + remaining_idx(), + None, + ResolvePathResultPrefixInfo::default(), + )); } } &Scope::ImplDefScope(impl_) => { if *first_name == sym::Self_.clone() { - return Some((TypeNs::SelfType(impl_), remaining_idx(), None)); + return Some(( + TypeNs::SelfType(impl_), + remaining_idx(), + None, + ResolvePathResultPrefixInfo::default(), + )); } } &Scope::AdtScope(adt) => { if *first_name == sym::Self_.clone() { - return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None)); + return Some(( + TypeNs::AdtSelfType(adt), + remaining_idx(), + None, + ResolvePathResultPrefixInfo::default(), + )); } } Scope::BlockScope(m) => { @@ -220,18 +251,6 @@ impl Resolver { self.module_scope.resolve_path_in_type_ns(db, path) } - pub fn resolve_path_in_type_ns_fully_with_imports( - &self, - db: &dyn DefDatabase, - path: &Path, - ) -> Option<(TypeNs, Option<ImportOrExternCrate>)> { - let (res, unresolved, imp) = self.resolve_path_in_type_ns(db, path)?; - if unresolved.is_some() { - return None; - } - Some((res, imp)) - } - pub fn resolve_path_in_type_ns_fully( &self, db: &dyn DefDatabase, @@ -324,7 +343,7 @@ impl Resolver { if n_segments <= 1 { let mut hygiene_info = if !hygiene_id.is_root() { - let ctx = db.lookup_intern_syntax_context(hygiene_id.0); + let ctx = hygiene_id.lookup(db); ctx.outer_expn.map(|expansion| { let expansion = db.lookup_intern_macro_call(expansion); (ctx.parent, expansion.def) @@ -986,11 +1005,12 @@ impl ModuleItemMap { &self, db: &dyn DefDatabase, path: &ModPath, - ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> { - let (module_def, idx, _) = + ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>, ResolvePathResultPrefixInfo)> + { + let (module_def, idx, prefix_info) = self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other); let (res, import) = to_type_ns(module_def)?; - Some((res, idx, import)) + Some((res, idx, import, prefix_info)) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs index 4edb6835922..c4473e454a1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs @@ -240,12 +240,12 @@ impl Visibility { if a_ancestors.any(|m| m == mod_b.local_id) { // B is above A - return Some(Visibility::Module(mod_a, expl_b)); + return Some(Visibility::Module(mod_a, expl_a)); } if b_ancestors.any(|m| m == mod_a.local_id) { // A is above B - return Some(Visibility::Module(mod_b, expl_a)); + return Some(Visibility::Module(mod_b, expl_b)); } None diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs index 4510a593af4..28b68121394 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs @@ -4,7 +4,7 @@ use intern::sym; use itertools::{izip, Itertools}; use parser::SyntaxKind; use rustc_hash::FxHashSet; -use span::{MacroCallId, Span, SyntaxContextId}; +use span::{Edition, MacroCallId, Span, SyntaxContextId}; use stdx::never; use syntax_bridge::DocCommentDesugarMode; use tracing::debug; @@ -33,7 +33,7 @@ macro_rules! register_builtin { } impl BuiltinDeriveExpander { - pub fn expander(&self) -> fn(Span, &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { + pub fn expander(&self) -> fn(&dyn ExpandDatabase, Span, &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { match *self { $( BuiltinDeriveExpander::$trait => $expand, )* } @@ -58,8 +58,8 @@ impl BuiltinDeriveExpander { tt: &tt::TopSubtree, span: Span, ) -> ExpandResult<tt::TopSubtree> { - let span = span_with_def_site_ctxt(db, span, id); - self.expander()(span, tt) + let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT); + self.expander()(db, span, tt) } } @@ -226,8 +226,12 @@ struct AdtParam { } // FIXME: This whole thing needs a refactor. Each derive requires its special values, and the result is a mess. -fn parse_adt(tt: &tt::TopSubtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> { - let (adt, tm) = to_adt_syntax(tt, call_site)?; +fn parse_adt( + db: &dyn ExpandDatabase, + tt: &tt::TopSubtree, + call_site: Span, +) -> Result<BasicAdtInfo, ExpandError> { + let (adt, tm) = to_adt_syntax(db, tt, call_site)?; parse_adt_from_syntax(&adt, &tm, call_site) } @@ -382,12 +386,14 @@ fn parse_adt_from_syntax( } fn to_adt_syntax( + db: &dyn ExpandDatabase, tt: &tt::TopSubtree, call_site: Span, ) -> Result<(ast::Adt, span::SpanMap<SyntaxContextId>), ExpandError> { - let (parsed, tm) = syntax_bridge::token_tree_to_syntax_node( + let (parsed, tm) = crate::db::token_tree_to_syntax_node( + db, tt, - syntax_bridge::TopEntryPoint::MacroItems, + crate::ExpandTo::Items, parser::Edition::CURRENT_FIXME, ); let macro_items = ast::MacroItems::cast(parsed.syntax_node()) @@ -446,12 +452,13 @@ fn name_to_token( /// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and /// therefore does not get bound by the derived trait. fn expand_simple_derive( + db: &dyn ExpandDatabase, invoc_span: Span, tt: &tt::TopSubtree, trait_path: tt::TopSubtree, make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree, ) -> ExpandResult<tt::TopSubtree> { - let info = match parse_adt(tt, invoc_span) { + let info = match parse_adt(db, tt, invoc_span) { Ok(info) => info, Err(e) => { return ExpandResult::new( @@ -520,14 +527,22 @@ fn expand_simple_derive_with_parsed( } } -fn copy_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn copy_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>}) + expand_simple_derive(db, span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>}) } -fn clone_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn clone_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::clone::Clone }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::clone::Clone }, |adt| { if matches!(adt.shape, AdtShape::Union) { let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span }; return quote! {span => @@ -576,9 +591,13 @@ fn and_and(span: Span) -> tt::TopSubtree { quote! {span => #and& } } -fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn default_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::default::Default }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::default::Default }, |adt| { let body = match &adt.shape { AdtShape::Struct(fields) => { let name = &adt.name; @@ -615,9 +634,13 @@ fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtre }) } -fn debug_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn debug_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::fmt::Debug }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::fmt::Debug }, |adt| { let for_variant = |name: String, v: &VariantShape| match v { VariantShape::Struct(fields) => { let for_fields = fields.iter().map(|it| { @@ -687,9 +710,13 @@ fn debug_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> }) } -fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn hash_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::hash::Hash }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::hash::Hash }, |adt| { if matches!(adt.shape, AdtShape::Union) { // FIXME: Return expand error here return quote! {span =>}; @@ -734,14 +761,22 @@ fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> }) } -fn eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn eq_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>}) + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>}) } -fn partial_eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn partial_eq_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| { if matches!(adt.shape, AdtShape::Union) { // FIXME: Return expand error here return quote! {span =>}; @@ -811,9 +846,13 @@ fn self_and_other_patterns( (self_patterns, other_patterns) } -fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn ord_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::cmp::Ord }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::Ord }, |adt| { fn compare( krate: &tt::Ident, left: tt::TopSubtree, @@ -869,9 +908,13 @@ fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { }) } -fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { +fn partial_ord_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { let krate = &dollar_crate(span); - expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| { + expand_simple_derive(db, span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| { fn compare( krate: &tt::Ident, left: tt::TopSubtree, @@ -932,8 +975,12 @@ fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSu }) } -fn coerce_pointee_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> { - let (adt, _span_map) = match to_adt_syntax(tt, span) { +fn coerce_pointee_expand( + db: &dyn ExpandDatabase, + span: Span, + tt: &tt::TopSubtree, +) -> ExpandResult<tt::TopSubtree> { + let (adt, _span_map) = match to_adt_syntax(db, tt, span) { Ok(it) => it, Err(err) => { return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err); diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs index 5b06de98757..310ddaaf9e9 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs @@ -69,7 +69,7 @@ impl BuiltinFnLikeExpander { tt: &tt::TopSubtree, span: Span, ) -> ExpandResult<tt::TopSubtree> { - let span = span_with_def_site_ctxt(db, span, id); + let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT); self.expander()(db, id, tt, span) } @@ -86,7 +86,7 @@ impl EagerExpander { tt: &tt::TopSubtree, span: Span, ) -> ExpandResult<tt::TopSubtree> { - let span = span_with_def_site_ctxt(db, span, id); + let span = span_with_def_site_ctxt(db, span, id, Edition::CURRENT); self.expander()(db, id, tt, span) } @@ -221,7 +221,7 @@ fn assert_expand( tt: &tt::TopSubtree, span: Span, ) -> ExpandResult<tt::TopSubtree> { - let call_site_span = span_with_call_site_ctxt(db, span, id); + let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT); let mut iter = tt.iter(); @@ -342,7 +342,7 @@ fn panic_expand( span: Span, ) -> ExpandResult<tt::TopSubtree> { let dollar_crate = dollar_crate(span); - let call_site_span = span_with_call_site_ctxt(db, span, id); + let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT); let mac = if use_panic_2021(db, call_site_span) { sym::panic_2021.clone() @@ -373,7 +373,7 @@ fn unreachable_expand( span: Span, ) -> ExpandResult<tt::TopSubtree> { let dollar_crate = dollar_crate(span); - let call_site_span = span_with_call_site_ctxt(db, span, id); + let call_site_span = span_with_call_site_ctxt(db, span, id, Edition::CURRENT); let mac = if use_panic_2021(db, call_site_span) { sym::unreachable_2021.clone() diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs index 6c1abc26203..9b637fc7684 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs @@ -102,6 +102,7 @@ macro_rules! quote_impl__ { ($span:ident $builder:ident # ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '#')}; ($span:ident $builder:ident $ ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '$')}; ($span:ident $builder:ident * ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '*')}; + ($span:ident $builder:ident = ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '=')}; ($span:ident $builder:ident $first:tt $($tail:tt)+ ) => {{ $crate::builtin::quote::__quote!($span $builder $first); @@ -225,7 +226,7 @@ mod tests { use ::tt::IdentIsRaw; use expect_test::expect; use intern::Symbol; - use span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; + use span::{Edition, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use syntax::{TextRange, TextSize}; use super::quote; @@ -239,7 +240,7 @@ mod tests { ), ast_id: ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }; #[test] @@ -276,8 +277,8 @@ mod tests { assert_eq!(quoted.to_string(), "hello"); let t = format!("{quoted:#?}"); expect![[r#" - SUBTREE $$ 937550:0@0..0#0 937550:0@0..0#0 - IDENT hello 937550:0@0..0#0"#]] + SUBTREE $$ 937550:0@0..0#2 937550:0@0..0#2 + IDENT hello 937550:0@0..0#2"#]] .assert_eq(&t); } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs index f4e80ef9e26..b7804f888ae 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs @@ -5,7 +5,7 @@ use either::Either; use limit::Limit; use mbe::MatchedArmIndex; use rustc_hash::FxHashSet; -use span::{AstIdMap, EditionedFileId, Span, SyntaxContextData, SyntaxContextId}; +use span::{AstIdMap, Edition, EditionedFileId, Span, SyntaxContextData, SyntaxContextId}; use syntax::{ast, AstNode, Parse, SyntaxElement, SyntaxError, SyntaxNode, SyntaxToken, T}; use syntax_bridge::{syntax_node_to_token_tree, DocCommentDesugarMode}; use triomphe::Arc; @@ -136,12 +136,12 @@ pub trait ExpandDatabase: SourceDatabase { macro_call: MacroCallId, ) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>; #[ra_salsa::transparent] - fn syntax_context(&self, file: HirFileId) -> SyntaxContextId; + fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContextId; } -fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId) -> SyntaxContextId { +fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId, edition: Edition) -> SyntaxContextId { match file.repr() { - HirFileIdRepr::FileId(_) => SyntaxContextId::ROOT, + HirFileIdRepr::FileId(_) => SyntaxContextId::root(edition), HirFileIdRepr::MacroFile(m) => { db.macro_arg_considering_derives(m.macro_call_id, &m.macro_call_id.lookup(db).kind) .2 @@ -273,9 +273,9 @@ pub fn expand_speculative( loc.krate, &tt, attr_arg.as_ref(), - span_with_def_site_ctxt(db, span, actual_macro_call), - span_with_call_site_ctxt(db, span, actual_macro_call), - span_with_mixed_site_ctxt(db, span, actual_macro_call), + span_with_def_site_ctxt(db, span, actual_macro_call, loc.def.edition), + span_with_call_site_ctxt(db, span, actual_macro_call, loc.def.edition), + span_with_mixed_site_ctxt(db, span, actual_macro_call, loc.def.edition), ) } MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => { @@ -300,7 +300,7 @@ pub fn expand_speculative( fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info); let (node, rev_tmap) = - token_tree_to_syntax_node(&speculative_expansion.value, expand_to, loc.def.edition); + token_tree_to_syntax_node(db, &speculative_expansion.value, expand_to, loc.def.edition); let syntax_node = node.syntax_node(); let token = rev_tmap @@ -346,6 +346,7 @@ fn parse_macro_expansion( macro_expand(db, macro_file.macro_call_id, loc); let (parse, mut rev_token_map) = token_tree_to_syntax_node( + db, match &tt { CowArc::Arc(it) => it, CowArc::Owned(it) => it, @@ -699,9 +700,9 @@ fn expand_proc_macro( loc.krate, ¯o_arg, attr_arg, - span_with_def_site_ctxt(db, span, id), - span_with_call_site_ctxt(db, span, id), - span_with_mixed_site_ctxt(db, span, id), + span_with_def_site_ctxt(db, span, id, loc.def.edition), + span_with_call_site_ctxt(db, span, id, loc.def.edition), + span_with_mixed_site_ctxt(db, span, id, loc.def.edition), ) }; @@ -715,7 +716,8 @@ fn expand_proc_macro( ExpandResult { value: Arc::new(tt), err } } -fn token_tree_to_syntax_node( +pub(crate) fn token_tree_to_syntax_node( + db: &dyn ExpandDatabase, tt: &tt::TopSubtree, expand_to: ExpandTo, edition: parser::Edition, @@ -727,7 +729,12 @@ fn token_tree_to_syntax_node( ExpandTo::Type => syntax_bridge::TopEntryPoint::Type, ExpandTo::Expr => syntax_bridge::TopEntryPoint::Expr, }; - syntax_bridge::token_tree_to_syntax_node(tt, entry_point, edition) + syntax_bridge::token_tree_to_syntax_node( + tt, + entry_point, + &mut |ctx| ctx.lookup(db).edition, + edition, + ) } fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> { @@ -751,5 +758,7 @@ fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> { } fn setup_syntax_context_root(db: &dyn ExpandDatabase) { - db.intern_syntax_context(SyntaxContextData::root()); + for edition in Edition::iter() { + db.intern_syntax_context(SyntaxContextData::root(edition)); + } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs index d1c39f32ca3..fef77acb7bb 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs @@ -2,7 +2,7 @@ use base_db::CrateId; use intern::sym; -use span::{Edition, MacroCallId, Span, SyntaxContextId}; +use span::{Edition, HirFileIdRepr, MacroCallId, Span, SyntaxContextId}; use stdx::TupleExt; use syntax::{ast, AstNode}; use syntax_bridge::DocCommentDesugarMode; @@ -20,6 +20,7 @@ use crate::{ pub struct DeclarativeMacroExpander { pub mac: mbe::DeclarativeMacro, pub transparency: Transparency, + edition: Edition, } impl DeclarativeMacroExpander { @@ -40,7 +41,7 @@ impl DeclarativeMacroExpander { .mac .expand( &tt, - |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency), + |s| s.ctx = apply_mark(db, s.ctx, call_id, self.transparency, self.edition), span, loc.def.edition, ) @@ -159,6 +160,10 @@ impl DeclarativeMacroExpander { transparency(¯o_def).unwrap_or(Transparency::Opaque), ), }; - Arc::new(DeclarativeMacroExpander { mac, transparency }) + let edition = ctx_edition(match id.file_id.repr() { + HirFileIdRepr::MacroFile(macro_file) => macro_file.macro_call_id.lookup(db).ctxt, + HirFileIdRepr::FileId(file) => SyntaxContextId::root(file.edition()), + }); + Arc::new(DeclarativeMacroExpander { mac, transparency, edition }) } } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs index 8c04d054029..13ddb0d4acc 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs @@ -380,14 +380,14 @@ impl InFile<TextRange> { ) -> (FileRange, SyntaxContextId) { match self.file_id.repr() { HirFileIdRepr::FileId(file_id) => { - (FileRange { file_id, range: self.value }, SyntaxContextId::ROOT) + (FileRange { file_id, range: self.value }, SyntaxContextId::root(file_id.edition())) } HirFileIdRepr::MacroFile(mac_file) => { match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) { Some(it) => it, None => { let loc = db.lookup_intern_macro_call(mac_file.macro_call_id); - (loc.kind.original_call_range(db), SyntaxContextId::ROOT) + (loc.kind.original_call_range(db), SyntaxContextId::root(loc.def.edition)) } } } @@ -432,9 +432,10 @@ impl InFile<TextRange> { db: &dyn db::ExpandDatabase, ) -> Option<(FileRange, SyntaxContextId)> { match self.file_id.repr() { - HirFileIdRepr::FileId(file_id) => { - Some((FileRange { file_id, range: self.value }, SyntaxContextId::ROOT)) - } + HirFileIdRepr::FileId(file_id) => Some(( + FileRange { file_id, range: self.value }, + SyntaxContextId::root(file_id.edition()), + )), HirFileIdRepr::MacroFile(mac_file) => { map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs index 3d2d52a0afe..eb430177390 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs @@ -380,7 +380,7 @@ pub(crate) fn reverse_fixups(tt: &mut TopSubtree, undo_info: &SyntaxFixupUndoInf let span = |file_id| Span { range: TextRange::empty(TextSize::new(0)), anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::Edition2015), }; delimiter.open = span(delimiter.open.anchor.file_id); delimiter.close = span(delimiter.close.anchor.file_id); @@ -441,8 +441,8 @@ fn transform_tt<'a, 'b>( }; let len_diff = replacement.len() as i64 - old_len as i64; tt.splice(i..i + old_len, replacement.flat_tokens().iter().cloned()); - // `+1` for the loop. - i = i.checked_add_signed(len_diff as isize + 1).unwrap(); + // Skip the newly inserted replacement, we don't want to visit it. + i += replacement.len(); for &subtree_idx in &subtrees_stack { let tt::TokenTree::Subtree(subtree) = &mut tt[subtree_idx] else { @@ -532,7 +532,7 @@ mod tests { } #[track_caller] - fn check(ra_fixture: &str, mut expect: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, mut expect: Expect) { let parsed = syntax::SourceFile::parse(ra_fixture, span::Edition::CURRENT); let span_map = SpanMap::RealSpanMap(Arc::new(RealSpanMap::absolute(EditionedFileId::new( FileId::from_raw(0), @@ -562,6 +562,7 @@ mod tests { let (parse, _) = syntax_bridge::token_tree_to_syntax_node( &tt, syntax_bridge::TopEntryPoint::MacroItems, + &mut |_| parser::Edition::CURRENT, parser::Edition::CURRENT, ); assert!( diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs index f48de807c28..fe05af0ac9d 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/hygiene.rs @@ -24,26 +24,37 @@ use std::iter; -use span::{MacroCallId, Span, SyntaxContextData, SyntaxContextId}; +use span::{Edition, MacroCallId, Span, SyntaxContextData, SyntaxContextId}; use crate::db::{ExpandDatabase, InternSyntaxContextQuery}; pub use span::Transparency; -pub fn span_with_def_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span { - span_with_ctxt_from_mark(db, span, expn_id, Transparency::Opaque) +pub fn span_with_def_site_ctxt( + db: &dyn ExpandDatabase, + span: Span, + expn_id: MacroCallId, + edition: Edition, +) -> Span { + span_with_ctxt_from_mark(db, span, expn_id, Transparency::Opaque, edition) } -pub fn span_with_call_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span { - span_with_ctxt_from_mark(db, span, expn_id, Transparency::Transparent) +pub fn span_with_call_site_ctxt( + db: &dyn ExpandDatabase, + span: Span, + expn_id: MacroCallId, + edition: Edition, +) -> Span { + span_with_ctxt_from_mark(db, span, expn_id, Transparency::Transparent, edition) } pub fn span_with_mixed_site_ctxt( db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId, + edition: Edition, ) -> Span { - span_with_ctxt_from_mark(db, span, expn_id, Transparency::SemiTransparent) + span_with_ctxt_from_mark(db, span, expn_id, Transparency::SemiTransparent, edition) } fn span_with_ctxt_from_mark( @@ -51,8 +62,12 @@ fn span_with_ctxt_from_mark( span: Span, expn_id: MacroCallId, transparency: Transparency, + edition: Edition, ) -> Span { - Span { ctx: apply_mark(db, SyntaxContextId::ROOT, expn_id, transparency), ..span } + Span { + ctx: apply_mark(db, SyntaxContextId::root(edition), expn_id, transparency, edition), + ..span + } } pub(super) fn apply_mark( @@ -60,9 +75,10 @@ pub(super) fn apply_mark( ctxt: SyntaxContextId, call_id: MacroCallId, transparency: Transparency, + edition: Edition, ) -> SyntaxContextId { if transparency == Transparency::Opaque { - return apply_mark_internal(db, ctxt, call_id, transparency); + return apply_mark_internal(db, ctxt, call_id, transparency, edition); } let call_site_ctxt = db.lookup_intern_macro_call(call_id).ctxt; @@ -73,7 +89,7 @@ pub(super) fn apply_mark( }; if call_site_ctxt.is_root() { - return apply_mark_internal(db, ctxt, call_id, transparency); + return apply_mark_internal(db, ctxt, call_id, transparency, edition); } // Otherwise, `expn_id` is a macros 1.0 definition and the call site is in a @@ -86,9 +102,9 @@ pub(super) fn apply_mark( // // See the example at `test/ui/hygiene/legacy_interaction.rs`. for (call_id, transparency) in ctxt.marks(db) { - call_site_ctxt = apply_mark_internal(db, call_site_ctxt, call_id, transparency); + call_site_ctxt = apply_mark_internal(db, call_site_ctxt, call_id, transparency, edition); } - apply_mark_internal(db, call_site_ctxt, call_id, transparency) + apply_mark_internal(db, call_site_ctxt, call_id, transparency, edition) } fn apply_mark_internal( @@ -96,6 +112,7 @@ fn apply_mark_internal( ctxt: SyntaxContextId, call_id: MacroCallId, transparency: Transparency, + edition: Edition, ) -> SyntaxContextId { use base_db::ra_salsa; @@ -108,13 +125,14 @@ fn apply_mark_internal( if transparency >= Transparency::Opaque { let parent = opaque; opaque = ra_salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert( - (parent, call_id, transparency), + (parent, call_id, transparency, edition), |new_opaque| SyntaxContextData { outer_expn: call_id, outer_transparency: transparency, parent, opaque: new_opaque, opaque_and_semitransparent: new_opaque, + edition, }, ); } @@ -123,13 +141,14 @@ fn apply_mark_internal( let parent = opaque_and_semitransparent; opaque_and_semitransparent = ra_salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert( - (parent, call_id, transparency), + (parent, call_id, transparency, edition), |new_opaque_and_semitransparent| SyntaxContextData { outer_expn: call_id, outer_transparency: transparency, parent, opaque, opaque_and_semitransparent: new_opaque_and_semitransparent, + edition, }, ); } @@ -141,6 +160,7 @@ fn apply_mark_internal( parent, opaque, opaque_and_semitransparent, + edition, }) } diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs index a0c4c125db4..2c664029f61 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs @@ -188,6 +188,8 @@ impl fmt::Display for RenderedExpandError { impl RenderedExpandError { const GENERAL_KIND: &str = "macro-error"; + const DISABLED: &str = "proc-macro-disabled"; + const ATTR_EXP_DISABLED: &str = "attribute-expansion-disabled"; } impl ExpandErrorKind { @@ -196,12 +198,12 @@ impl ExpandErrorKind { ExpandErrorKind::ProcMacroAttrExpansionDisabled => RenderedExpandError { message: "procedural attribute macro expansion is disabled".to_owned(), error: false, - kind: "proc-macros-disabled", + kind: RenderedExpandError::ATTR_EXP_DISABLED, }, ExpandErrorKind::MacroDisabled => RenderedExpandError { message: "proc-macro is explicitly disabled".to_owned(), error: false, - kind: "proc-macro-disabled", + kind: RenderedExpandError::DISABLED, }, &ExpandErrorKind::MissingProcMacroExpander(def_crate) => { match db.proc_macros().get_error_for_crate(def_crate) { diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs index 7ecf5219873..89eae862bd9 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs @@ -273,10 +273,9 @@ fn convert_path( res } } - ast::PathSegmentKind::SelfTypeKw => ModPath::from_segments( - PathKind::Plain, - Some(Name::new_symbol(sym::Self_.clone(), SyntaxContextId::ROOT)), - ), + ast::PathSegmentKind::SelfTypeKw => { + ModPath::from_segments(PathKind::Plain, Some(Name::new_symbol_root(sym::Self_.clone()))) + } ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()), ast::PathSegmentKind::SelfKw => handle_super_kw(0)?, ast::PathSegmentKind::SuperKw => handle_super_kw(1)?, @@ -399,6 +398,9 @@ macro_rules! __known_path { (core::fmt::Debug) => {}; (std::fmt::format) => {}; (core::ops::Try) => {}; + (core::convert::From) => {}; + (core::convert::TryFrom) => {}; + (core::str::FromStr) => {}; ($path:path) => { compile_error!("Please register your known path in the path module") }; @@ -415,3 +417,14 @@ macro_rules! __path { } pub use crate::__path as path; + +#[macro_export] +macro_rules! __tool_path { + ($start:ident $(:: $seg:ident)*) => ({ + $crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Plain, vec![ + $crate::name::Name::new_symbol_root(intern::sym::rust_analyzer.clone()), $crate::name::Name::new_symbol_root(intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root(intern::sym::$seg.clone()),)* + ]) + }); +} + +pub use crate::__tool_path as tool_path; diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs index 267d5458333..cc53d2e34aa 100644 --- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs +++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs @@ -11,7 +11,7 @@ use syntax::utils::is_raw_identifier; /// and declarations. In theory, names should also carry hygiene info, but we are /// not there yet! /// -/// Note that the rawness (`r#`) of names does not depend on whether they are written raw. +/// Note that the rawness (`r#`) of names is not preserved. Names are always stored without a `r#` prefix. /// This is because we want to show (in completions etc.) names as raw depending on the needs /// of the current crate, for example if it is edition 2021 complete `gen` even if the defining /// crate is in edition 2024 and wrote `r#gen`, and the opposite holds as well. @@ -77,20 +77,49 @@ impl Name { /// Hopefully, this should allow us to integrate hygiene cleaner in the /// future, and to switch to interned representation of names. fn new_text(text: &str) -> Name { + debug_assert!(!text.starts_with("r#")); Name { symbol: Symbol::intern(text), ctx: () } } - pub fn new(text: &str, ctx: SyntaxContextId) -> Name { + pub fn new(text: &str, mut ctx: SyntaxContextId) -> Name { + // For comparisons etc. we remove the edition, because sometimes we search for some `Name` + // and we don't know which edition it came from. + // Can't do that for all `SyntaxContextId`s because it breaks Salsa. + ctx.remove_root_edition(); _ = ctx; Self::new_text(text) } + pub fn new_root(text: &str) -> Name { + // The edition doesn't matter for hygiene. + Self::new(text.trim_start_matches("r#"), SyntaxContextId::root(Edition::Edition2015)) + } + pub fn new_tuple_field(idx: usize) -> Name { - Name { symbol: Symbol::intern(&idx.to_string()), ctx: () } + let symbol = match idx { + 0 => sym::INTEGER_0.clone(), + 1 => sym::INTEGER_1.clone(), + 2 => sym::INTEGER_2.clone(), + 3 => sym::INTEGER_3.clone(), + 4 => sym::INTEGER_4.clone(), + 5 => sym::INTEGER_5.clone(), + 6 => sym::INTEGER_6.clone(), + 7 => sym::INTEGER_7.clone(), + 8 => sym::INTEGER_8.clone(), + 9 => sym::INTEGER_9.clone(), + 10 => sym::INTEGER_10.clone(), + 11 => sym::INTEGER_11.clone(), + 12 => sym::INTEGER_12.clone(), + 13 => sym::INTEGER_13.clone(), + 14 => sym::INTEGER_14.clone(), + 15 => sym::INTEGER_15.clone(), + _ => Symbol::intern(&idx.to_string()), + }; + Name { symbol, ctx: () } } pub fn new_lifetime(lt: &ast::Lifetime) -> Name { - Name { symbol: Symbol::intern(lt.text().as_str()), ctx: () } + Self::new_text(lt.text().as_str().trim_start_matches("r#")) } /// Resolve a name from the text of token. @@ -133,15 +162,18 @@ impl Name { } /// Returns the text this name represents if it isn't a tuple field. + /// + /// Do not use this for user-facing text, use `display` instead to handle editions properly. pub fn as_str(&self) -> &str { self.symbol.as_str() } + // FIXME: Remove this pub fn unescaped(&self) -> UnescapedName<'_> { UnescapedName(self) } - pub fn is_escaped(&self, edition: Edition) -> bool { + pub fn needs_escape(&self, edition: Edition) -> bool { is_raw_identifier(self.symbol.as_str(), edition) } @@ -164,16 +196,19 @@ impl Name { &self.symbol } - pub const fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self { + pub fn new_symbol(symbol: Symbol, ctx: SyntaxContextId) -> Self { + debug_assert!(!symbol.as_str().starts_with("r#")); _ = ctx; Self { symbol, ctx: () } } // FIXME: This needs to go once we have hygiene - pub const fn new_symbol_root(sym: Symbol) -> Self { + pub fn new_symbol_root(sym: Symbol) -> Self { + debug_assert!(!sym.as_str().starts_with("r#")); Self { symbol: sym, ctx: () } } + // FIXME: Remove this #[inline] pub fn eq_ident(&self, ident: &str) -> bool { self.as_str() == ident.trim_start_matches("r#") diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs index 9f01f1eb259..c8ff6cba3dd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs @@ -856,7 +856,7 @@ fn impl_def_datum( let associated_ty_value_ids = impl_data .items .iter() - .filter_map(|item| match item { + .filter_map(|(_, item)| match item { AssocItemId::TypeAliasId(type_alias) => Some(*type_alias), _ => None, }) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 0a8bfaa70f8..2d7d4cacd2c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -31,7 +31,10 @@ fn simplify(e: ConstEvalError) -> ConstEvalError { } #[track_caller] -fn check_fail(ra_fixture: &str, error: impl FnOnce(ConstEvalError) -> bool) { +fn check_fail( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + error: impl FnOnce(ConstEvalError) -> bool, +) { let (db, file_id) = TestDB::with_single_file(ra_fixture); match eval_goal(&db, file_id) { Ok(_) => panic!("Expected fail, but it succeeded"), @@ -42,7 +45,7 @@ fn check_fail(ra_fixture: &str, error: impl FnOnce(ConstEvalError) -> bool) { } #[track_caller] -fn check_number(ra_fixture: &str, answer: i128) { +fn check_number(#[rust_analyzer::rust_fixture] ra_fixture: &str, answer: i128) { check_answer(ra_fixture, |b, _| { assert_eq!( b, @@ -54,7 +57,7 @@ fn check_number(ra_fixture: &str, answer: i128) { } #[track_caller] -fn check_str(ra_fixture: &str, answer: &str) { +fn check_str(#[rust_analyzer::rust_fixture] ra_fixture: &str, answer: &str) { check_answer(ra_fixture, |b, mm| { let addr = usize::from_le_bytes(b[0..b.len() / 2].try_into().unwrap()); let size = usize::from_le_bytes(b[b.len() / 2..].try_into().unwrap()); @@ -71,7 +74,10 @@ fn check_str(ra_fixture: &str, answer: &str) { } #[track_caller] -fn check_answer(ra_fixture: &str, check: impl FnOnce(&[u8], &MemoryMap)) { +fn check_answer( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + check: impl FnOnce(&[u8], &MemoryMap), +) { let (db, file_ids) = TestDB::with_many_files(ra_fixture); let file_id = *file_ids.last().unwrap(); let r = match eval_goal(&db, file_id) { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index a4e052a0362..3545bf76776 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs @@ -471,10 +471,55 @@ impl HirDisplay for ProjectionTy { if f.should_truncate() { return write!(f, "{TYPE_HINT_TRUNCATION}"); } - let trait_ref = self.trait_ref(f.db); + let self_ty = trait_ref.self_type_parameter(Interner); + + // if we are projection on a type parameter, check if the projection target has bounds + // itself, if so, we render them directly as `impl Bound` instead of the less useful + // `<Param as Trait>::Assoc` + if !f.display_target.is_source_code() { + if let TyKind::Placeholder(idx) = self_ty.kind(Interner) { + let db = f.db; + let id = from_placeholder_idx(db, *idx); + let generics = generics(db.upcast(), id.parent); + + let substs = generics.placeholder_subst(db); + let bounds = db + .generic_predicates(id.parent) + .iter() + .map(|pred| pred.clone().substitute(Interner, &substs)) + .filter(|wc| match wc.skip_binders() { + WhereClause::Implemented(tr) => { + match tr.self_type_parameter(Interner).kind(Interner) { + TyKind::Alias(AliasTy::Projection(proj)) => proj == self, + _ => false, + } + } + WhereClause::TypeOutlives(t) => match t.ty.kind(Interner) { + TyKind::Alias(AliasTy::Projection(proj)) => proj == self, + _ => false, + }, + // We shouldn't be here if these exist + WhereClause::AliasEq(_) => false, + WhereClause::LifetimeOutlives(_) => false, + }) + .collect::<Vec<_>>(); + if !bounds.is_empty() { + return write_bounds_like_dyn_trait_with_prefix( + f, + "impl", + Either::Left( + &TyKind::Alias(AliasTy::Projection(self.clone())).intern(Interner), + ), + &bounds, + SizedByDefault::NotSized, + ); + }; + } + } + write!(f, "<")?; - trait_ref.self_type_parameter(Interner).hir_fmt(f)?; + self_ty.hir_fmt(f)?; write!(f, " as ")?; trait_ref.hir_fmt(f)?; write!( diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs index 8a56bd28b59..3060b610bb6 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility/tests.rs @@ -26,7 +26,7 @@ enum DynCompatibilityViolationKind { } fn check_dyn_compatibility<'a>( - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, expected: impl IntoIterator<Item = (&'a str, Vec<DynCompatibilityViolationKind>)>, ) { let mut expected: FxHashMap<_, _> = diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index 66159ddce2b..4d3896660b4 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -25,7 +25,10 @@ fn current_machine_data_layout() -> String { .unwrap() } -fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutError> { +fn eval_goal( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + minicore: &str, +) -> Result<Arc<Layout>, LayoutError> { let target_data_layout = current_machine_data_layout(); let ra_fixture = format!( "//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\n{ra_fixture}", @@ -81,7 +84,10 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro } /// A version of `eval_goal` for types that can not be expressed in ADTs, like closures and `impl Trait` -fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutError> { +fn eval_expr( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + minicore: &str, +) -> Result<Arc<Layout>, LayoutError> { let target_data_layout = current_machine_data_layout(); let ra_fixture = format!( "//- target_data_layout: {target_data_layout}\n{minicore}//- /main.rs crate:test\nfn main(){{let goal = {{{ra_fixture}}};}}", @@ -114,21 +120,31 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro } #[track_caller] -fn check_size_and_align(ra_fixture: &str, minicore: &str, size: u64, align: u64) { +fn check_size_and_align( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + minicore: &str, + size: u64, + align: u64, +) { let l = eval_goal(ra_fixture, minicore).unwrap(); assert_eq!(l.size.bytes(), size, "size mismatch"); assert_eq!(l.align.abi.bytes(), align, "align mismatch"); } #[track_caller] -fn check_size_and_align_expr(ra_fixture: &str, minicore: &str, size: u64, align: u64) { +fn check_size_and_align_expr( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + minicore: &str, + size: u64, + align: u64, +) { let l = eval_expr(ra_fixture, minicore).unwrap(); assert_eq!(l.size.bytes(), size, "size mismatch"); assert_eq!(l.align.abi.bytes(), align, "align mismatch"); } #[track_caller] -fn check_fail(ra_fixture: &str, e: LayoutError) { +fn check_fail(#[rust_analyzer::rust_fixture] ra_fixture: &str, e: LayoutError) { let r = eval_goal(ra_fixture, ""); assert_eq!(r, Err(e)); } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 24f67fd6602..432b8f4d94e 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs @@ -761,8 +761,8 @@ impl<'a> TyLoweringContext<'a> { path: &Path, on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic), ) -> Option<(TypeNs, Option<usize>)> { - let (resolution, remaining_index, _) = - self.resolver.resolve_path_in_type_ns(self.db.upcast(), path)?; + let (resolution, remaining_index, _, prefix_info) = + self.resolver.resolve_path_in_type_ns_with_prefix_info(self.db.upcast(), path)?; let segments = path.segments(); match path { @@ -771,13 +771,12 @@ impl<'a> TyLoweringContext<'a> { _ => return Some((resolution, remaining_index)), }; - let (module_segments, resolved_segment_idx, resolved_segment) = match remaining_index { - None => ( - segments.strip_last(), - segments.len() - 1, - segments.last().expect("resolved path has at least one element"), - ), - Some(i) => (segments.take(i - 1), i - 1, segments.get(i - 1).unwrap()), + let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index { + None if prefix_info.enum_variant => { + (segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2)) + } + None => (segments.strip_last(), segments.len() - 1, None), + Some(i) => (segments.take(i - 1), i - 1, None), }; for (i, mod_segment) in module_segments.iter().enumerate() { @@ -792,9 +791,23 @@ impl<'a> TyLoweringContext<'a> { } } + if let Some(enum_segment) = enum_segment { + if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some()) + && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some()) + { + on_diagnostic( + self, + PathLoweringDiagnostic::GenericArgsProhibited { + segment: (enum_segment + 1) as u32, + reason: GenericArgsProhibitedReason::EnumVariant, + }, + ); + } + } + self.handle_type_ns_resolution( &resolution, - resolved_segment, + segments.get(resolved_segment_idx).expect("should have resolved segment"), resolved_segment_idx, on_diagnostic, ); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 62b071b2f32..182032f0481 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -746,16 +746,9 @@ fn lookup_impl_assoc_item_for_trait_ref( let table = InferenceTable::new(db, env); let (impl_data, impl_subst) = find_matching_impl(impls, table, trait_ref)?; - let item = impl_data.items.iter().find_map(|&it| match it { - AssocItemId::FunctionId(f) => { - (db.function_data(f).name == *name).then_some(AssocItemId::FunctionId(f)) - } - AssocItemId::ConstId(c) => db - .const_data(c) - .name - .as_ref() - .map(|n| n == name) - .and_then(|result| if result { Some(AssocItemId::ConstId(c)) } else { None }), + let item = impl_data.items.iter().find_map(|(n, it)| match *it { + AssocItemId::FunctionId(f) => (n == name).then_some(AssocItemId::FunctionId(f)), + AssocItemId::ConstId(c) => (n == name).then_some(AssocItemId::ConstId(c)), AssocItemId::TypeAliasId(_) => None, })?; Some((item, impl_subst)) @@ -850,7 +843,7 @@ fn is_inherent_impl_coherent( }; rustc_has_incoherent_inherent_impls && !impl_data.items.is_empty() - && impl_data.items.iter().copied().all(|assoc| match assoc { + && impl_data.items.iter().all(|&(_, assoc)| match assoc { AssocItemId::FunctionId(it) => db.function_data(it).rustc_allow_incoherent_impl, AssocItemId::ConstId(it) => db.const_data(it).rustc_allow_incoherent_impl, AssocItemId::TypeAliasId(it) => db.type_alias_data(it).rustc_allow_incoherent_impl, @@ -1399,7 +1392,7 @@ fn iterate_inherent_methods( callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, ) -> ControlFlow<()> { for &impl_id in impls.for_self_ty(self_ty) { - for &item in table.db.impl_data(impl_id).items.iter() { + for &(ref item_name, item) in table.db.impl_data(impl_id).items.iter() { let visible = match is_valid_impl_method_candidate( table, self_ty, @@ -1408,6 +1401,7 @@ fn iterate_inherent_methods( name, impl_id, item, + item_name, ) { IsValidCandidate::Yes => true, IsValidCandidate::NotVisible => false, @@ -1467,6 +1461,7 @@ fn is_valid_impl_method_candidate( name: Option<&Name>, impl_id: ImplId, item: AssocItemId, + item_name: &Name, ) -> IsValidCandidate { match item { AssocItemId::FunctionId(f) => is_valid_impl_fn_candidate( @@ -1477,11 +1472,12 @@ fn is_valid_impl_method_candidate( receiver_ty, self_ty, visible_from_module, + item_name, ), AssocItemId::ConstId(c) => { let db = table.db; check_that!(receiver_ty.is_none()); - check_that!(name.is_none_or(|n| db.const_data(c).name.as_ref() == Some(n))); + check_that!(name.is_none_or(|n| n == item_name)); if let Some(from_module) = visible_from_module { if !db.const_visibility(c).is_visible_from(db.upcast(), from_module) { @@ -1565,11 +1561,13 @@ fn is_valid_impl_fn_candidate( receiver_ty: Option<&Ty>, self_ty: &Ty, visible_from_module: Option<ModuleId>, + item_name: &Name, ) -> IsValidCandidate { + check_that!(name.is_none_or(|n| n == item_name)); + let db = table.db; let data = db.function_data(fn_id); - check_that!(name.is_none_or(|n| n == &data.name)); if let Some(from_module) = visible_from_module { if !db.function_visibility(fn_id).is_visible_from(db.upcast(), from_module) { cov_mark::hit!(autoderef_candidate_not_visible); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index ce43e90df7d..f1e86daea23 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -37,11 +37,15 @@ fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), Ok((output.stdout().into_owned(), output.stderr().into_owned())) } -fn check_pass(ra_fixture: &str) { +fn check_pass(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_pass_and_stdio(ra_fixture, "", ""); } -fn check_pass_and_stdio(ra_fixture: &str, expected_stdout: &str, expected_stderr: &str) { +fn check_pass_and_stdio( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expected_stdout: &str, + expected_stderr: &str, +) { let (db, file_ids) = TestDB::with_many_files(ra_fixture); let file_id = *file_ids.last().unwrap(); let x = eval_main(&db, file_id); @@ -73,7 +77,7 @@ fn check_pass_and_stdio(ra_fixture: &str, expected_stdout: &str, expected_stderr } } -fn check_panic(ra_fixture: &str, expected_panic: &str) { +fn check_panic(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected_panic: &str) { let (db, file_ids) = TestDB::with_many_files(ra_fixture); let file_id = *file_ids.last().unwrap(); let e = eval_main(&db, file_id).unwrap_err(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs index b7607b5f639..00da9b25176 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs @@ -69,27 +69,32 @@ fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> { } #[track_caller] -fn check_types(ra_fixture: &str) { +fn check_types(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_impl(ra_fixture, false, true, false) } #[track_caller] -fn check_types_source_code(ra_fixture: &str) { +fn check_types_source_code(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_impl(ra_fixture, false, true, true) } #[track_caller] -fn check_no_mismatches(ra_fixture: &str) { +fn check_no_mismatches(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_impl(ra_fixture, true, false, false) } #[track_caller] -fn check(ra_fixture: &str) { +fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_impl(ra_fixture, false, false, false) } #[track_caller] -fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_source: bool) { +fn check_impl( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + allow_none: bool, + only_types: bool, + display_source: bool, +) { let _tracing = setup_tracing(); let (db, files) = TestDB::with_many_files(ra_fixture); @@ -282,7 +287,7 @@ fn pat_node( }) } -fn infer(ra_fixture: &str) -> String { +fn infer(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String { infer_with_mismatches(ra_fixture, false) } @@ -430,7 +435,7 @@ pub(crate) fn visit_module( visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb); for impl_id in crate_def_map[module_id].scope.impls() { let impl_data = db.impl_data(impl_id); - for &item in impl_data.items.iter() { + for &(_, item) in impl_data.items.iter() { match item { AssocItemId::FunctionId(it) => { let body = db.body(it.into()); @@ -520,13 +525,13 @@ fn ellipsize(mut text: String, max_len: usize) -> String { text } -fn check_infer(ra_fixture: &str, expect: Expect) { +fn check_infer(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let mut actual = infer(ra_fixture); actual.push('\n'); expect.assert_eq(&actual); } -fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) { +fn check_infer_with_mismatches(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let mut actual = infer_with_mismatches(ra_fixture, true); actual.push('\n'); expect.assert_eq(&actual); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs index 7de92d6b160..34d299edd1b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs @@ -14,7 +14,7 @@ use crate::test_db::TestDB; use super::visit_module; -fn check_closure_captures(ra_fixture: &str, expect: Expect) { +fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (db, file_id) = TestDB::with_single_file(ra_fixture); let module = db.module_for_file(file_id); let def_map = module.def_map(&db); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs index 5f0f341f393..15636604570 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs @@ -3802,3 +3802,15 @@ fn foo() { "#, ); } + +#[test] +fn tool_attr_skip() { + check_no_mismatches( + r#" +#[rust_analyzer::skip] +async fn foo(a: (), b: i32) -> u32 { + 0 + 1 + b() +} + "#, + ); +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index 30711b16dfb..afd163fbd96 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -968,7 +968,7 @@ struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V); } #[track_caller] - fn check(ra_fixture: &str, expected: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: Expect) { // use tracing_subscriber::{layer::SubscriberExt, Layer}; // let my_layer = tracing_subscriber::fmt::layer(); // let _g = tracing::subscriber::set_default(tracing_subscriber::registry().with( diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml index 6aadc5c4f7e..c68ff706e48 100644 --- a/src/tools/rust-analyzer/crates/hir/Cargo.toml +++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml @@ -20,6 +20,7 @@ itertools.workspace = true smallvec.workspace = true tracing.workspace = true triomphe.workspace = true +indexmap.workspace = true # local deps base-db.workspace = true diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index a23fdf1b393..4351a34e822 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -12,7 +12,6 @@ use hir_def::{ }; use hir_expand::{mod_path::PathKind, name::Name}; use hir_ty::{db::HirDatabase, method_resolution}; -use span::SyntaxContextId; use crate::{ Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, @@ -90,6 +89,16 @@ impl HasAttrs for AssocItem { } } +impl HasAttrs for crate::Crate { + fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner { + let def = AttrDefId::ModuleId(self.root_module().id); + AttrsWithOwner::new(db.upcast(), def) + } + fn attr_id(self) -> AttrDefId { + AttrDefId::ModuleId(self.root_module().id) + } +} + /// Resolves the item `link` points to in the scope of `def`. pub fn resolve_doc_path_on( db: &dyn HirDatabase, @@ -328,9 +337,7 @@ fn doc_modpath_from_str(link: &str) -> Option<ModPath> { }; let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() { Ok(idx) => Name::new_tuple_field(idx), - Err(_) => { - Name::new(segment.split_once('<').map_or(segment, |it| it.0), SyntaxContextId::ROOT) - } + Err(_) => Name::new_root(segment.split_once('<').map_or(segment, |it| it.0)), }); Some(ModPath::from_segments(kind, parts)) }; diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index e09ded32fbd..b29c91694d3 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/crates/hir/src/display.rs @@ -23,10 +23,10 @@ use hir_ty::{ use itertools::Itertools; use crate::{ - Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, - Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam, Macro, Module, - SelfParam, Static, Struct, Trait, TraitAlias, TraitRef, TupleField, TyBuilder, Type, TypeAlias, - TypeOrConstParam, TypeParam, Union, Variant, + Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Crate, Enum, + ExternCrateDecl, Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam, + Macro, Module, SelfParam, Static, Struct, Trait, TraitAlias, TraitRef, TupleField, TyBuilder, + Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant, }; impl HirDisplay for Function { @@ -846,14 +846,27 @@ impl HirDisplay for TypeAlias { impl HirDisplay for Module { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { - // FIXME: Module doesn't have visibility saved in data. + match self.parent(f.db) { + Some(m) => write_visibility(m.id, self.visibility(f.db), f)?, + None => { + return match self.krate(f.db).display_name(f.db) { + Some(name) => write!(f, "extern crate {name}"), + None => f.write_str("extern crate {unknown}"), + } + } + } match self.name(f.db) { Some(name) => write!(f, "mod {}", name.display(f.db.upcast(), f.edition())), - None if self.is_crate_root() => match self.krate(f.db).display_name(f.db) { - Some(name) => write!(f, "extern crate {name}"), - None => f.write_str("extern crate {unknown}"), - }, - None => f.write_str("mod {unnamed}"), + None => f.write_str("mod {unknown}"), + } + } +} + +impl HirDisplay for Crate { + fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { + match self.display_name(f.db) { + Some(name) => write!(f, "extern crate {name}"), + None => f.write_str("extern crate {unknown}"), } } } diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 00b4db54374..db3121d3cd3 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs @@ -54,11 +54,11 @@ use hir_def::{ per_ns::PerNs, resolver::{HasResolver, Resolver}, type_ref::TypesSourceMap, - AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, CrateRootModuleId, - DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, - HasModule, ImplId, InTypeConstId, ItemContainerId, LifetimeParamId, LocalFieldId, Lookup, - MacroExpander, ModuleId, StaticId, StructId, SyntheticSyntax, TraitAliasId, TraitId, TupleId, - TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, + AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId, + CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId, FunctionId, + GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstId, ItemContainerId, + LifetimeParamId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId, + SyntheticSyntax, TraitAliasId, TupleId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, }; use hir_expand::{ attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, RenderedExpandError, @@ -83,7 +83,7 @@ use itertools::Itertools; use nameres::diagnostics::DefDiagnosticKind; use rustc_hash::FxHashSet; use smallvec::SmallVec; -use span::{Edition, EditionedFileId, FileId, MacroCallId, SyntaxContextId}; +use span::{Edition, EditionedFileId, FileId, MacroCallId}; use stdx::{format_to, impl_from, never}; use syntax::{ ast::{self, HasAttrs as _, HasGenericParams, HasName}, @@ -127,7 +127,7 @@ pub use { ImportPathConfig, // FIXME: This is here since some queries take it as input that are used // outside of hir. - {AdtId, MacroId, ModuleDefId}, + {ModuleDefId, TraitId}, }, hir_expand::{ attrs::{Attr, AttrId}, @@ -775,29 +775,16 @@ impl Module { AssocItemId::ConstId(id) => !db.const_data(id).has_body, AssocItemId::TypeAliasId(it) => db.type_alias_data(it).type_ref.is_none(), }); - impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().filter_map( - |&item| { - Some(( - item, - match item { - AssocItemId::FunctionId(it) => db.function_data(it).name.clone(), - AssocItemId::ConstId(it) => { - db.const_data(it).name.as_ref()?.clone() - } - AssocItemId::TypeAliasId(it) => db.type_alias_data(it).name.clone(), - }, - )) - }, - )); + impl_assoc_items_scratch.extend(db.impl_data(impl_def.id).items.iter().cloned()); let redundant = impl_assoc_items_scratch .iter() - .filter(|(id, name)| { + .filter(|(name, id)| { !items.iter().any(|(impl_name, impl_item)| { discriminant(impl_item) == discriminant(id) && impl_name == name }) }) - .map(|(item, name)| (name.clone(), AssocItem::from(*item))); + .map(|(name, item)| (name.clone(), AssocItem::from(*item))); for (name, assoc_item) in redundant { acc.push( TraitImplRedundantAssocItems { @@ -812,7 +799,7 @@ impl Module { let missing: Vec<_> = required_items .filter(|(name, id)| { - !impl_assoc_items_scratch.iter().any(|(impl_item, impl_name)| { + !impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| { discriminant(impl_item) == discriminant(id) && impl_name == name }) }) @@ -844,7 +831,7 @@ impl Module { source_map, ); - for &item in db.impl_data(impl_def.id).items.iter() { + for &(_, item) in db.impl_data(impl_def.id).items.iter() { AssocItem::from(item).diagnostics(db, acc, style_lints); } } @@ -3000,6 +2987,10 @@ impl Macro { matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export) } + pub fn is_proc_macro(self) -> bool { + matches!(self.id, MacroId::ProcMacroId(_)) + } + pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind { match self.id { MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander { @@ -3046,14 +3037,23 @@ impl Macro { MacroId::Macro2Id(it) => { matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env()) } - MacroId::MacroRulesId(_) | MacroId::ProcMacroId(_) => false, + MacroId::MacroRulesId(it) => { + matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env()) + } + MacroId::ProcMacroId(_) => false, } } pub fn is_asm_or_global_asm(&self, db: &dyn HirDatabase) -> bool { - matches!(self.id, MacroId::Macro2Id(it) if { - matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm()) - }) + match self.id { + MacroId::Macro2Id(it) => { + matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm()) + } + MacroId::MacroRulesId(it) => { + matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltIn(m) if m.is_asm()) + } + MacroId::ProcMacroId(_) => false, + } } pub fn is_attr(&self, db: &dyn HirDatabase) -> bool { @@ -3902,6 +3902,10 @@ impl ToolModule { db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone(), ) } + + pub fn krate(&self) -> Crate { + Crate { id: self.krate } + } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -4290,7 +4294,7 @@ impl Impl { } pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> { - db.impl_data(self.id).items.iter().map(|&it| it.into()).collect() + db.impl_data(self.id).items.iter().map(|&(_, it)| it.into()).collect() } pub fn is_negative(self, db: &dyn HirDatabase) -> bool { @@ -4731,6 +4735,14 @@ impl Type { Some((self.derived(ty.clone()), m)) } + pub fn add_reference(&self, mutability: Mutability) -> Type { + let ty_mutability = match mutability { + Mutability::Shared => hir_ty::Mutability::Not, + Mutability::Mut => hir_ty::Mutability::Mut, + }; + self.derived(TyKind::Ref(ty_mutability, error_lifetime(), self.ty.clone()).intern(Interner)) + } + pub fn is_slice(&self) -> bool { matches!(self.ty.kind(Interner), TyKind::Slice(..)) } @@ -4786,9 +4798,9 @@ impl Type { } /// Checks that particular type `ty` implements `std::future::IntoFuture` or - /// `std::future::Future`. + /// `std::future::Future` and returns the `Output` associated type. /// This function is used in `.await` syntax completion. - pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool { + pub fn into_future_output(&self, db: &dyn HirDatabase) -> Option<Type> { let trait_ = db .lang_item(self.env.krate, LangItem::IntoFutureIntoFuture) .and_then(|it| { @@ -4800,16 +4812,18 @@ impl Type { .or_else(|| { let future_trait = db.lang_item(self.env.krate, LangItem::Future)?; future_trait.as_trait() - }); - - let trait_ = match trait_ { - Some(it) => it, - None => return false, - }; + })?; let canonical_ty = Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; - method_resolution::implements_trait(&canonical_ty, db, &self.env, trait_) + if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) { + return None; + } + + let output_assoc_type = db + .trait_data(trait_) + .associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?; + self.normalize_trait_assoc_type(db, &[], output_assoc_type.into()) } /// This does **not** resolve `IntoFuture`, only `Future`. @@ -4824,10 +4838,31 @@ impl Type { let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?; let iterator_item = db .trait_data(iterator_trait) - .associated_type_by_name(&Name::new_symbol(sym::Item.clone(), SyntaxContextId::ROOT))?; + .associated_type_by_name(&Name::new_symbol_root(sym::Item.clone()))?; self.normalize_trait_assoc_type(db, &[], iterator_item.into()) } + /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type + pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option<Type> { + let trait_ = db.lang_item(self.env.krate, LangItem::IntoIterIntoIter).and_then(|it| { + let into_iter_fn = it.as_function()?; + let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?; + let into_iter_trait = assoc_item.container_or_implemented_trait(db)?; + Some(into_iter_trait.id) + })?; + + let canonical_ty = + Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) }; + if !method_resolution::implements_trait_unique(&canonical_ty, db, &self.env, trait_) { + return None; + } + + let into_iter_assoc_type = db + .trait_data(trait_) + .associated_type_by_name(&Name::new_symbol_root(sym::IntoIter.clone()))?; + self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into()) + } + /// Checks that particular type `ty` implements `std::ops::FnOnce`. /// /// This function can be used to check if a particular type is callable, since FnOnce is a @@ -5117,7 +5152,7 @@ impl Type { let impls = db.inherent_impls_in_crate(krate); for impl_def in impls.for_self_ty(&self.ty) { - for &item in db.impl_data(*impl_def).items.iter() { + for &(_, item) in db.impl_data(*impl_def).items.iter() { if callback(item) { return; } @@ -5535,6 +5570,7 @@ impl Type { walk_substs(db, type_, &opaque_ty.substitution, cb); } TyKind::Placeholder(_) => { + cb(type_.derived(ty.clone())); if let Some(bounds) = ty.impl_trait_bounds(db) { walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 34d169cd761..523bc6f10aa 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -39,8 +39,8 @@ use stdx::TupleExt; use syntax::{ algo::skip_trivia_token, ast::{self, HasAttrs as _, HasGenericParams}, - AstNode, AstToken, Direction, SmolStr, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, - TextRange, TextSize, + AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, + TextSize, }; use triomphe::Arc; @@ -136,8 +136,6 @@ pub struct Semantics<'db, DB> { pub struct SemanticsImpl<'db> { pub db: &'db dyn HirDatabase, s2d_cache: RefCell<SourceToDefCache>, - /// Rootnode to HirFileId cache - root_to_file_cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>, /// MacroCall to its expansion's MacroFileId cache macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, MacroFileId>>, } @@ -304,12 +302,7 @@ impl<DB: HirDatabase> Semantics<'_, DB> { impl<'db> SemanticsImpl<'db> { fn new(db: &'db dyn HirDatabase) -> Self { - SemanticsImpl { - db, - s2d_cache: Default::default(), - root_to_file_cache: Default::default(), - macro_call_cache: Default::default(), - } + SemanticsImpl { db, s2d_cache: Default::default(), macro_call_cache: Default::default() } } pub fn parse(&self, file_id: EditionedFileId) -> ast::SourceFile { @@ -483,7 +476,7 @@ impl<'db> SemanticsImpl<'db> { Some( calls .into_iter() - .map(|call| macro_call_to_macro_id(self, ctx, call?).map(|id| Macro { id })) + .map(|call| macro_call_to_macro_id(ctx, call?).map(|id| Macro { id })) .collect(), ) }) @@ -962,7 +955,7 @@ impl<'db> SemanticsImpl<'db> { let InMacroFile { file_id, value: mapped_tokens } = self.with_ctx(|ctx| { Some( ctx.cache - .get_or_insert_expansion(self, macro_file) + .get_or_insert_expansion(ctx.db, macro_file) .map_range_down(span)? .map(SmallVec::<[_; 2]>::from_iter), ) @@ -986,7 +979,10 @@ impl<'db> SemanticsImpl<'db> { process_expansion_for_token(&mut stack, include)?; } None => { - stack.push((file_id.into(), smallvec![(token, SyntaxContextId::ROOT)])); + stack.push(( + file_id.into(), + smallvec![(token, SyntaxContextId::root(file_id.edition()))], + )); } } @@ -1284,7 +1280,7 @@ impl<'db> SemanticsImpl<'db> { let macro_file = file_id.macro_file()?; self.with_ctx(|ctx| { - let expansion_info = ctx.cache.get_or_insert_expansion(self, macro_file); + let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file); expansion_info.arg().map(|node| node?.parent()).transpose() }) } @@ -1315,8 +1311,8 @@ impl<'db> SemanticsImpl<'db> { } pub fn resolve_label(&self, label: &ast::Lifetime) -> Option<Label> { - let (parent, label_id) = self - .with_ctx(|ctx| ctx.label_ref_to_def(self.wrap_node_infile(label.clone()).as_ref()))?; + let src = self.wrap_node_infile(label.clone()); + let (parent, label_id) = self.with_ctx(|ctx| ctx.label_ref_to_def(src.as_ref()))?; Some(Label { parent, label_id }) } @@ -1443,6 +1439,10 @@ impl<'db> SemanticsImpl<'db> { self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call) } + pub fn resolve_known_blanket_dual_impls(&self, call: &ast::MethodCallExpr) -> Option<Function> { + self.analyze(call.syntax())?.resolve_known_blanket_dual_impls(self.db, call) + } + fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<StructId> { self.analyze(range_pat.syntax())?.resolve_range_pat(self.db, range_pat) } @@ -1516,7 +1516,7 @@ impl<'db> SemanticsImpl<'db> { let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call); self.with_ctx(|ctx| { ctx.macro_call_to_macro_call(macro_call) - .and_then(|call| macro_call_to_macro_id(self, ctx, call)) + .and_then(|call| macro_call_to_macro_id(ctx, call)) .map(Into::into) }) .or_else(|| { @@ -1558,7 +1558,7 @@ impl<'db> SemanticsImpl<'db> { let item_in_file = self.wrap_node_infile(item.clone()); let id = self.with_ctx(|ctx| { let macro_call_id = ctx.item_to_macro_call(item_in_file.as_ref())?; - macro_call_to_macro_id(self, ctx, macro_call_id) + macro_call_to_macro_id(ctx, macro_call_id) })?; Some(Macro { id }) } @@ -1591,14 +1591,11 @@ impl<'db> SemanticsImpl<'db> { pub fn resolve_mod_path_relative( &self, to: Module, - segments: impl IntoIterator<Item = SmolStr>, + segments: impl IntoIterator<Item = Name>, ) -> Option<impl Iterator<Item = ItemInNs>> { let items = to.id.resolver(self.db.upcast()).resolve_module_path_in_items( self.db.upcast(), - &ModPath::from_segments( - hir_def::path::PathKind::Plain, - segments.into_iter().map(|it| Name::new(&it, SyntaxContextId::ROOT)), - ), + &ModPath::from_segments(hir_def::path::PathKind::Plain, segments), ); Some(items.iter_items().map(|(item, _)| item.into())) } @@ -1722,10 +1719,11 @@ impl<'db> SemanticsImpl<'db> { } fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) { - assert!(root_node.parent().is_none()); - let mut cache = self.root_to_file_cache.borrow_mut(); - let prev = cache.insert(root_node, file_id); - assert!(prev.is_none() || prev == Some(file_id)); + SourceToDefCache::cache( + &mut self.s2d_cache.borrow_mut().root_to_file_cache, + root_node, + file_id, + ); } pub fn assert_contains_node(&self, node: &SyntaxNode) { @@ -1733,8 +1731,8 @@ impl<'db> SemanticsImpl<'db> { } fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> { - let cache = self.root_to_file_cache.borrow(); - cache.get(root_node).copied() + let cache = self.s2d_cache.borrow(); + cache.root_to_file_cache.get(root_node).copied() } fn wrap_node_infile<N: AstNode>(&self, node: N) -> InFile<N> { @@ -1753,13 +1751,14 @@ impl<'db> SemanticsImpl<'db> { let file_id = self.lookup(&root_node).unwrap_or_else(|| { panic!( "\n\nFailed to lookup {:?} in this Semantics.\n\ - Make sure to use only query nodes, derived from this instance of Semantics.\n\ + Make sure to only query nodes derived from this instance of Semantics.\n\ root node: {:?}\n\ known nodes: {}\n\n", node, root_node, - self.root_to_file_cache + self.s2d_cache .borrow() + .root_to_file_cache .keys() .map(|it| format!("{it:?}")) .collect::<Vec<_>>() @@ -1906,7 +1905,6 @@ impl<'db> SemanticsImpl<'db> { } fn macro_call_to_macro_id( - sema: &SemanticsImpl<'_>, ctx: &mut SourceToDefCtx<'_, '_>, macro_call_id: MacroCallId, ) -> Option<MacroId> { @@ -1922,7 +1920,7 @@ fn macro_call_to_macro_id( it.to_ptr(db).to_node(&db.parse(file_id).syntax_node()) } HirFileIdRepr::MacroFile(macro_file) => { - let expansion_info = ctx.cache.get_or_insert_expansion(sema, macro_file); + let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file); it.to_ptr(db).to_node(&expansion_info.expanded().value) } }; @@ -1934,7 +1932,7 @@ fn macro_call_to_macro_id( it.to_ptr(db).to_node(&db.parse(file_id).syntax_node()) } HirFileIdRepr::MacroFile(macro_file) => { - let expansion_info = ctx.cache.get_or_insert_expansion(sema, macro_file); + let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file); it.to_ptr(db).to_node(&expansion_info.expanded().value) } }; diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs index ec65ea9a9a8..d5dfb985718 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/child_by_source.rs @@ -56,7 +56,7 @@ impl ChildBySource for ImplId { res[keys::ATTR_MACRO_CALL].insert(ast_id.to_ptr(db.upcast()), call_id); }, ); - data.items.iter().for_each(|&item| { + data.items.iter().for_each(|&(_, item)| { add_assoc_item(db, res, file_id, item); }); } diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs index b5cc440fc22..3c9e7065c41 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs @@ -110,10 +110,7 @@ use syntax::{ AstNode, AstPtr, SyntaxNode, }; -use crate::{ - db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand, - SemanticsImpl, -}; +use crate::{db::HirDatabase, semantics::child_by_source::ChildBySource, InFile, InlineAsmOperand}; #[derive(Default)] pub(super) struct SourceToDefCache { @@ -121,9 +118,21 @@ pub(super) struct SourceToDefCache { expansion_info_cache: FxHashMap<MacroFileId, ExpansionInfo>, pub(super) file_to_def_cache: FxHashMap<FileId, SmallVec<[ModuleId; 1]>>, pub(super) included_file_cache: FxHashMap<EditionedFileId, Option<MacroFileId>>, + /// Rootnode to HirFileId cache + pub(super) root_to_file_cache: FxHashMap<SyntaxNode, HirFileId>, } impl SourceToDefCache { + pub(super) fn cache( + root_to_file_cache: &mut FxHashMap<SyntaxNode, HirFileId>, + root_node: SyntaxNode, + file_id: HirFileId, + ) { + assert!(root_node.parent().is_none()); + let prev = root_to_file_cache.insert(root_node, file_id); + assert!(prev.is_none() || prev == Some(file_id)); + } + pub(super) fn get_or_insert_include_for( &mut self, db: &dyn HirDatabase, @@ -143,14 +152,14 @@ impl SourceToDefCache { pub(super) fn get_or_insert_expansion( &mut self, - sema: &SemanticsImpl<'_>, + db: &dyn HirDatabase, macro_file: MacroFileId, ) -> &ExpansionInfo { self.expansion_info_cache.entry(macro_file).or_insert_with(|| { - let exp_info = macro_file.expansion_info(sema.db.upcast()); + let exp_info = macro_file.expansion_info(db.upcast()); let InMacroFile { file_id, value } = exp_info.expanded(); - sema.cache(value, file_id.into()); + Self::cache(&mut self.root_to_file_cache, value, file_id.into()); exp_info }) @@ -520,18 +529,11 @@ impl SourceToDefCtx<'_, '_> { node: InFile<&SyntaxNode>, mut cb: impl FnMut(&mut Self, InFile<SyntaxNode>) -> Option<T>, ) -> Option<T> { - use hir_expand::MacroFileIdExt; let parent = |this: &mut Self, node: InFile<&SyntaxNode>| match node.value.parent() { Some(parent) => Some(node.with_value(parent)), None => { let macro_file = node.file_id.macro_file()?; - - let expansion_info = this - .cache - .expansion_info_cache - .entry(macro_file) - .or_insert_with(|| macro_file.expansion_info(this.db.upcast())); - + let expansion_info = this.cache.get_or_insert_expansion(this.db, macro_file); expansion_info.arg().map(|node| node?.parent()).transpose() } }; diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index b699ccde412..6b78d7a3631 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs @@ -322,6 +322,68 @@ impl SourceAnalyzer { } } + // If the method is into(), try_into(), parse(), resolve it to from, try_from, from_str. + pub(crate) fn resolve_known_blanket_dual_impls( + &self, + db: &dyn HirDatabase, + call: &ast::MethodCallExpr, + ) -> Option<Function> { + // e.g. if the method call is let b = a.into(), + // - receiver_type is A (type of a) + // - return_type is B (type of b) + // We will find the definition of B::from(a: A). + let callable = self.resolve_method_call_as_callable(db, call)?; + let (_, receiver_type) = callable.receiver_param(db)?; + let return_type = callable.return_type(); + let (search_method, substs) = match call.name_ref()?.text().as_str() { + "into" => { + let trait_ = + self.resolver.resolve_known_trait(db.upcast(), &path![core::convert::From])?; + ( + self.trait_fn(db, trait_, "from")?, + hir_ty::TyBuilder::subst_for_def(db, trait_, None) + .push(return_type.ty) + .push(receiver_type.ty) + .build(), + ) + } + "try_into" => { + let trait_ = self + .resolver + .resolve_known_trait(db.upcast(), &path![core::convert::TryFrom])?; + ( + self.trait_fn(db, trait_, "try_from")?, + hir_ty::TyBuilder::subst_for_def(db, trait_, None) + // If the method is try_into() or parse(), return_type is Result<T, Error>. + // Get T from type arguments of Result<T, Error>. + .push(return_type.type_arguments().next()?.ty) + .push(receiver_type.ty) + .build(), + ) + } + "parse" => { + let trait_ = + self.resolver.resolve_known_trait(db.upcast(), &path![core::str::FromStr])?; + ( + self.trait_fn(db, trait_, "from_str")?, + hir_ty::TyBuilder::subst_for_def(db, trait_, None) + .push(return_type.type_arguments().next()?.ty) + .build(), + ) + } + _ => return None, + }; + + let found_method = self.resolve_impl_method_or_trait_def(db, search_method, substs); + // If found_method == search_method, the method in trait itself is resolved. + // It means the blanket dual impl is not found. + if found_method == search_method { + None + } else { + Some(found_method.into()) + } + } + pub(crate) fn resolve_expr_as_callable( &self, db: &dyn HirDatabase, @@ -1247,6 +1309,18 @@ impl SourceAnalyzer { Some((trait_id, fn_id)) } + fn trait_fn( + &self, + db: &dyn HirDatabase, + trait_id: TraitId, + method_name: &str, + ) -> Option<FunctionId> { + db.trait_data(trait_id).items.iter().find_map(|(item_name, item)| match item { + AssocItemId::FunctionId(t) if item_name.as_str() == method_name => Some(*t), + _ => None, + }) + } + fn ty_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<&Ty> { self.infer.as_ref()?.type_of_expr_or_pat(self.expr_id(db, expr)?) } diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs index f8416f86bf9..a6b8ed70c36 100644 --- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs +++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs @@ -1,27 +1,34 @@ //! File symbol extraction. +use either::Either; use hir_def::{ db::DefDatabase, - item_scope::ItemInNs, + item_scope::{ImportId, ImportOrExternCrate}, + per_ns::Item, src::{HasChildSource, HasSource}, - AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId, - TraitId, + visibility::{Visibility, VisibilityExplicitness}, + AdtId, AssocItemId, DefWithBodyId, ExternCrateId, HasModule, ImplId, Lookup, MacroId, + ModuleDefId, ModuleId, TraitId, }; -use hir_expand::HirFileId; +use hir_expand::{name::Name, HirFileId}; use hir_ty::{ db::HirDatabase, display::{hir_display_with_types_map, HirDisplay}, }; +use intern::Symbol; +use rustc_hash::FxHashMap; use span::Edition; use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr}; use crate::{Module, ModuleDef, Semantics}; +pub type FxIndexSet<T> = indexmap::IndexSet<T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>; + /// The actual data that is stored in the index. It should be as compact as /// possible. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FileSymbol { - pub name: SmolStr, + pub name: Symbol, pub def: ModuleDef, pub loc: DeclarationLocation, pub container_name: Option<SmolStr>, @@ -37,7 +44,7 @@ pub struct DeclarationLocation { /// This points to the whole syntax node of the declaration. pub ptr: SyntaxNodePtr, /// This points to the [`syntax::ast::Name`] identifier of the declaration. - pub name_ptr: AstPtr<syntax::ast::Name>, + pub name_ptr: AstPtr<Either<syntax::ast::Name, syntax::ast::NameRef>>, } impl DeclarationLocation { @@ -55,7 +62,7 @@ struct SymbolCollectorWork { pub struct SymbolCollector<'a> { db: &'a dyn HirDatabase, - symbols: Vec<FileSymbol>, + symbols: FxIndexSet<FileSymbol>, work: Vec<SymbolCollectorWork>, current_container_name: Option<SmolStr>, edition: Edition, @@ -86,11 +93,11 @@ impl<'a> SymbolCollector<'a> { } } - pub fn finish(self) -> Vec<FileSymbol> { - self.symbols + pub fn finish(self) -> Box<[FileSymbol]> { + self.symbols.into_iter().collect() } - pub fn collect_module(db: &dyn HirDatabase, module: Module) -> Vec<FileSymbol> { + pub fn collect_module(db: &dyn HirDatabase, module: Module) -> Box<[FileSymbol]> { let mut symbol_collector = SymbolCollector::new(db); symbol_collector.collect(module); symbol_collector.finish() @@ -104,96 +111,174 @@ impl<'a> SymbolCollector<'a> { } fn collect_from_module(&mut self, module_id: ModuleId) { - let def_map = module_id.def_map(self.db.upcast()); - let scope = &def_map[module_id.local_id].scope; - - for module_def_id in scope.declarations() { - match module_def_id { - ModuleDefId::ModuleId(id) => self.push_module(id), + let push_decl = |this: &mut Self, def, name| { + match def { + ModuleDefId::ModuleId(id) => this.push_module(id, name), ModuleDefId::FunctionId(id) => { - self.push_decl(id, false); - self.collect_from_body(id); + this.push_decl(id, name, false); + this.collect_from_body(id); } - ModuleDefId::AdtId(AdtId::StructId(id)) => self.push_decl(id, false), - ModuleDefId::AdtId(AdtId::EnumId(id)) => self.push_decl(id, false), - ModuleDefId::AdtId(AdtId::UnionId(id)) => self.push_decl(id, false), + ModuleDefId::AdtId(AdtId::StructId(id)) => this.push_decl(id, name, false), + ModuleDefId::AdtId(AdtId::EnumId(id)) => this.push_decl(id, name, false), + ModuleDefId::AdtId(AdtId::UnionId(id)) => this.push_decl(id, name, false), ModuleDefId::ConstId(id) => { - self.push_decl(id, false); - self.collect_from_body(id); + this.push_decl(id, name, false); + this.collect_from_body(id); } ModuleDefId::StaticId(id) => { - self.push_decl(id, false); - self.collect_from_body(id); + this.push_decl(id, name, false); + this.collect_from_body(id); } ModuleDefId::TraitId(id) => { - self.push_decl(id, false); - self.collect_from_trait(id); + this.push_decl(id, name, false); + this.collect_from_trait(id); } ModuleDefId::TraitAliasId(id) => { - self.push_decl(id, false); + this.push_decl(id, name, false); } ModuleDefId::TypeAliasId(id) => { - self.push_decl(id, false); + this.push_decl(id, name, false); } ModuleDefId::MacroId(id) => match id { - MacroId::Macro2Id(id) => self.push_decl(id, false), - MacroId::MacroRulesId(id) => self.push_decl(id, false), - MacroId::ProcMacroId(id) => self.push_decl(id, false), + MacroId::Macro2Id(id) => this.push_decl(id, name, false), + MacroId::MacroRulesId(id) => this.push_decl(id, name, false), + MacroId::ProcMacroId(id) => this.push_decl(id, name, false), }, // Don't index these. ModuleDefId::BuiltinType(_) => {} ModuleDefId::EnumVariantId(_) => {} } - } + }; - for impl_id in scope.impls() { - self.collect_from_impl(impl_id); - } + // Nested trees are very common, so a cache here will hit a lot. + let import_child_source_cache = &mut FxHashMap::default(); + + let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId| { + let source = import_child_source_cache + .entry(i.import) + .or_insert_with(|| i.import.child_source(this.db.upcast())); + let Some(use_tree_src) = source.value.get(i.idx) else { return }; + let Some(name_ptr) = use_tree_src + .rename() + .and_then(|rename| rename.name()) + .map(Either::Left) + .or_else(|| use_tree_src.path()?.segment()?.name_ref().map(Either::Right)) + .map(|it| AstPtr::new(&it)) + else { + return; + }; + let dec_loc = DeclarationLocation { + hir_file_id: source.file_id, + ptr: SyntaxNodePtr::new(use_tree_src.syntax()), + name_ptr, + }; + this.symbols.insert(FileSymbol { + name: name.symbol().clone(), + def: def.into(), + container_name: this.current_container_name.clone(), + loc: dec_loc, + is_alias: false, + is_assoc: false, + }); + }; - // Record renamed imports. - // FIXME: In case it imports multiple items under different namespaces we just pick one arbitrarily - // for now. - for id in scope.imports() { - let source = id.import.child_source(self.db.upcast()); - let Some(use_tree_src) = source.value.get(id.idx) else { continue }; - let Some(rename) = use_tree_src.rename() else { continue }; - let Some(name) = rename.name() else { continue }; - - let res = scope.fully_resolve_import(self.db.upcast(), id); - res.iter_items().for_each(|(item, _)| { - let def = match item { - ItemInNs::Types(def) | ItemInNs::Values(def) => def, - ItemInNs::Macros(def) => ModuleDefId::from(def), - } - .into(); + let push_extern_crate = + |this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId| { + let loc = i.lookup(this.db.upcast()); + let source = loc.source(this.db.upcast()); + let Some(name_ptr) = source + .value + .rename() + .and_then(|rename| rename.name()) + .map(Either::Left) + .or_else(|| source.value.name_ref().map(Either::Right)) + .map(|it| AstPtr::new(&it)) + else { + return; + }; let dec_loc = DeclarationLocation { hir_file_id: source.file_id, - ptr: SyntaxNodePtr::new(use_tree_src.syntax()), - name_ptr: AstPtr::new(&name), + ptr: SyntaxNodePtr::new(source.value.syntax()), + name_ptr, }; - - self.symbols.push(FileSymbol { - name: name.text().into(), - def, - container_name: self.current_container_name.clone(), + this.symbols.insert(FileSymbol { + name: name.symbol().clone(), + def: def.into(), + container_name: this.current_container_name.clone(), loc: dec_loc, is_alias: false, is_assoc: false, }); - }); + }; + + let is_explicit_import = |vis| { + match vis { + Visibility::Module(_, VisibilityExplicitness::Explicit) => true, + Visibility::Module(_, VisibilityExplicitness::Implicit) => { + // consider imports in the crate root explicit, as these are visibly + // crate-wide anyways + module_id.is_crate_root() + } + Visibility::Public => true, + } + }; + + let def_map = module_id.def_map(self.db.upcast()); + let scope = &def_map[module_id.local_id].scope; + + for impl_id in scope.impls() { + self.collect_from_impl(impl_id); + } + + for (name, Item { def, vis, import }) in scope.types() { + if let Some(i) = import { + if is_explicit_import(vis) { + match i { + ImportOrExternCrate::Import(i) => push_import(self, i, name, def), + ImportOrExternCrate::ExternCrate(i) => { + push_extern_crate(self, i, name, def) + } + } + } + continue; + } + // self is a declaration + push_decl(self, def, name) + } + + for (name, Item { def, vis, import }) in scope.macros() { + if let Some(i) = import { + if is_explicit_import(vis) { + push_import(self, i, name, def.into()); + } + continue; + } + // self is a declaration + push_decl(self, def.into(), name) + } + + for (name, Item { def, vis, import }) in scope.values() { + if let Some(i) = import { + if is_explicit_import(vis) { + push_import(self, i, name, def); + } + continue; + } + // self is a declaration + push_decl(self, def, name) } for const_id in scope.unnamed_consts() { self.collect_from_body(const_id); } - for (_, id) in scope.legacy_macros() { + for (name, id) in scope.legacy_macros() { for &id in id { if id.module(self.db.upcast()) == module_id { match id { - MacroId::Macro2Id(id) => self.push_decl(id, false), - MacroId::MacroRulesId(id) => self.push_decl(id, false), - MacroId::ProcMacroId(id) => self.push_decl(id, false), + MacroId::Macro2Id(id) => self.push_decl(id, name, false), + MacroId::MacroRulesId(id) => self.push_decl(id, name, false), + MacroId::ProcMacroId(id) => self.push_decl(id, name, false), } } } @@ -223,8 +308,8 @@ impl<'a> SymbolCollector<'a> { .to_smolstr(), ); self.with_container_name(impl_name, |s| { - for &assoc_item_id in impl_data.items.iter() { - s.push_assoc_item(assoc_item_id) + for &(ref name, assoc_item_id) in &impl_data.items { + s.push_assoc_item(assoc_item_id, name) } }) } @@ -232,8 +317,8 @@ impl<'a> SymbolCollector<'a> { fn collect_from_trait(&mut self, trait_id: TraitId) { let trait_data = self.db.trait_data(trait_id); self.with_container_name(Some(trait_data.name.as_str().into()), |s| { - for &(_, assoc_item_id) in &trait_data.items { - s.push_assoc_item(assoc_item_id); + for &(ref name, assoc_item_id) in &trait_data.items { + s.push_assoc_item(assoc_item_id, name); } }); } @@ -266,15 +351,15 @@ impl<'a> SymbolCollector<'a> { } } - fn push_assoc_item(&mut self, assoc_item_id: AssocItemId) { + fn push_assoc_item(&mut self, assoc_item_id: AssocItemId, name: &Name) { match assoc_item_id { - AssocItemId::FunctionId(id) => self.push_decl(id, true), - AssocItemId::ConstId(id) => self.push_decl(id, true), - AssocItemId::TypeAliasId(id) => self.push_decl(id, true), + AssocItemId::FunctionId(id) => self.push_decl(id, name, true), + AssocItemId::ConstId(id) => self.push_decl(id, name, true), + AssocItemId::TypeAliasId(id) => self.push_decl(id, name, true), } } - fn push_decl<'db, L>(&mut self, id: L, is_assoc: bool) + fn push_decl<'db, L>(&mut self, id: L, name: &Name, is_assoc: bool) where L: Lookup<Database<'db> = dyn DefDatabase + 'db> + Into<ModuleDefId>, <L as Lookup>::Data: HasSource, @@ -287,13 +372,13 @@ impl<'a> SymbolCollector<'a> { let dec_loc = DeclarationLocation { hir_file_id: source.file_id, ptr: SyntaxNodePtr::new(source.value.syntax()), - name_ptr: AstPtr::new(&name_node), + name_ptr: AstPtr::new(&name_node).wrap_left(), }; if let Some(attrs) = def.attrs(self.db) { for alias in attrs.doc_aliases() { - self.symbols.push(FileSymbol { - name: alias.as_str().into(), + self.symbols.insert(FileSymbol { + name: alias.clone(), def, loc: dec_loc.clone(), container_name: self.current_container_name.clone(), @@ -303,8 +388,8 @@ impl<'a> SymbolCollector<'a> { } } - self.symbols.push(FileSymbol { - name: name_node.text().into(), + self.symbols.insert(FileSymbol { + name: name.symbol().clone(), def, container_name: self.current_container_name.clone(), loc: dec_loc, @@ -313,7 +398,7 @@ impl<'a> SymbolCollector<'a> { }); } - fn push_module(&mut self, module_id: ModuleId) { + fn push_module(&mut self, module_id: ModuleId, name: &Name) { let def_map = module_id.def_map(self.db.upcast()); let module_data = &def_map[module_id.local_id]; let Some(declaration) = module_data.origin.declaration() else { return }; @@ -322,15 +407,15 @@ impl<'a> SymbolCollector<'a> { let dec_loc = DeclarationLocation { hir_file_id: declaration.file_id, ptr: SyntaxNodePtr::new(module.syntax()), - name_ptr: AstPtr::new(&name_node), + name_ptr: AstPtr::new(&name_node).wrap_left(), }; let def = ModuleDef::Module(module_id.into()); if let Some(attrs) = def.attrs(self.db) { for alias in attrs.doc_aliases() { - self.symbols.push(FileSymbol { - name: alias.as_str().into(), + self.symbols.insert(FileSymbol { + name: alias.clone(), def, loc: dec_loc.clone(), container_name: self.current_container_name.clone(), @@ -340,8 +425,8 @@ impl<'a> SymbolCollector<'a> { } } - self.symbols.push(FileSymbol { - name: name_node.text().into(), + self.symbols.insert(FileSymbol { + name: name.symbol().clone(), def: ModuleDef::Module(module_id.into()), container_name: self.current_container_name.clone(), loc: dec_loc, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs index 074d943719f..64e77b2d698 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs @@ -109,6 +109,10 @@ impl<'a> AssistContext<'a> { self.trimmed_range } + pub(crate) fn source_file(&self) -> &SourceFile { + &self.source_file + } + pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> { self.source_file.syntax().token_at_offset(self.offset()) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 24b34f140bd..5899ec5a005 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -212,8 +212,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) !hidden }) .map(|(pat, _)| { - make::match_arm(iter::once(pat), None, make::ext::expr_todo()) - .clone_for_update() + make::match_arm(pat, None, make::ext::expr_todo()).clone_for_update() }); let catch_all_arm = new_match_arm_list @@ -243,12 +242,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) if needs_catch_all_arm && !has_catch_all_arm { cov_mark::hit!(added_wildcard_pattern); - let arm = make::match_arm( - iter::once(make::wildcard_pat().into()), - None, - make::ext::expr_todo(), - ) - .clone_for_update(); + let arm = + make::match_arm(make::wildcard_pat().into(), None, make::ext::expr_todo()) + .clone_for_update(); todo_placeholders.push(arm.expr().unwrap()); added_arms.push(arm); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs index 62700ab1809..04d63f5bc8f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs @@ -189,7 +189,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti /// This will create a turbofish generic arg list corresponding to the number of arguments fn get_fish_head(make: &SyntaxFactory, number_of_arguments: usize) -> ast::GenericArgList { let args = (0..number_of_arguments).map(|_| make::type_arg(make::ty_placeholder()).into()); - make.turbofish_generic_arg_list(args) + make.generic_arg_list(args, true) } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs index f178a7e0cec..70fb5680052 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs @@ -252,7 +252,7 @@ fn tail_cb_impl(edit: &mut SourceChangeBuilder, e: &ast::Expr) { /// Add bang and parentheses to the expression. fn add_bang_paren(expr: ast::Expr) -> ast::Expr { - make::expr_prefix(T![!], make::expr_paren(expr)) + make::expr_prefix(T![!], make::expr_paren(expr)).into() } #[cfg(test)] diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs index f699899066b..cbd39796241 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/bool_to_enum.rs @@ -195,6 +195,7 @@ fn bool_expr_to_enum_expr(expr: ast::Expr) -> ast::Expr { make::tail_only_block_expr(true_expr), Some(ast::ElseBranch::Block(make::tail_only_block_expr(false_expr))), ) + .into() } } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs index 79f303b37a4..bb04a43cf96 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_closure_to_fn.rs @@ -507,7 +507,7 @@ fn wrap_capture_in_deref_if_needed( if does_autoderef { return capture_name; } - make::expr_prefix(T![*], capture_name) + make::expr_prefix(T![*], capture_name).into() } fn capture_as_arg(ctx: &AssistContext<'_>, capture: &ClosureCapture) -> ast::Expr { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs index 67c72a93dad..dd2e9cbcb5f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_from_to_tryfrom.rs @@ -97,7 +97,7 @@ pub(crate) fn convert_from_to_tryfrom(acc: &mut Assists, ctx: &AssistContext<'_> ); for r in return_exprs { - let t = r.expr().unwrap_or_else(make::expr_unit); + let t = r.expr().unwrap_or_else(make::ext::expr_unit); ted::replace(t.syntax(), wrap_ok(t.clone()).syntax().clone_for_update()); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs index 434daa279ca..0b92beefbcd 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs @@ -60,7 +60,7 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) .indent(while_indent_level); let block_expr = if is_pattern_cond(while_cond.clone()) { let if_expr = make::expr_if(while_cond, while_body, Some(break_block.into())); - let stmts = iter::once(make::expr_stmt(if_expr).into()); + let stmts = iter::once(make::expr_stmt(if_expr.into()).into()); make::block_expr(stmts, None) } else { let if_cond = invert_boolean_expression(while_cond); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs index 7df6ca1565f..39142d60620 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs @@ -1128,7 +1128,10 @@ fn main { destructure_tuple_binding_impl(acc, ctx, false) } - pub(crate) fn check_in_place_assist(ra_fixture_before: &str, ra_fixture_after: &str) { + pub(crate) fn check_in_place_assist( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, + ) { check_assist_by_label( in_place_assist, ra_fixture_before, @@ -1138,7 +1141,10 @@ fn main { ); } - pub(crate) fn check_sub_pattern_assist(ra_fixture_before: &str, ra_fixture_after: &str) { + pub(crate) fn check_sub_pattern_assist( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, + ) { check_assist_by_label( assist, ra_fixture_before, diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs index 0d1b6af7204..967da41c15f 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs @@ -1533,7 +1533,7 @@ impl FlowHandler { .into(), call_expr, ); - make::expr_if(condition.into(), block, None) + make::expr_if(condition.into(), block, None).into() } FlowHandler::IfOption { action } => { let path = make::ext::ident_path("Some"); @@ -1544,7 +1544,7 @@ impl FlowHandler { let action_expr = action.make_result_handler(Some(value)); let action_stmt = make::expr_stmt(action_expr); let then = make::block_expr(iter::once(action_stmt.into()), None); - make::expr_if(cond.into(), then, None) + make::expr_if(cond.into(), then, None).into() } FlowHandler::MatchOption { none } => { let some_name = "value"; @@ -1554,15 +1554,15 @@ impl FlowHandler { let value_pat = make::ext::simple_ident_pat(make::name(some_name)); let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); let value = make::expr_path(make::ext::ident_path(some_name)); - make::match_arm(iter::once(pat.into()), None, value) + make::match_arm(pat.into(), None, value) }; let none_arm = { let path = make::ext::ident_path("None"); let pat = make::path_pat(path); - make::match_arm(iter::once(pat), None, none.make_result_handler(None)) + make::match_arm(pat, None, none.make_result_handler(None)) }; let arms = make::match_arm_list(vec![some_arm, none_arm]); - make::expr_match(call_expr, arms) + make::expr_match(call_expr, arms).into() } FlowHandler::MatchResult { err } => { let ok_name = "value"; @@ -1573,21 +1573,17 @@ impl FlowHandler { let value_pat = make::ext::simple_ident_pat(make::name(ok_name)); let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); let value = make::expr_path(make::ext::ident_path(ok_name)); - make::match_arm(iter::once(pat.into()), None, value) + make::match_arm(pat.into(), None, value) }; let err_arm = { let path = make::ext::ident_path("Err"); let value_pat = make::ext::simple_ident_pat(make::name(err_name)); let pat = make::tuple_struct_pat(path, iter::once(value_pat.into())); let value = make::expr_path(make::ext::ident_path(err_name)); - make::match_arm( - iter::once(pat.into()), - None, - err.make_result_handler(Some(value)), - ) + make::match_arm(pat.into(), None, err.make_result_handler(Some(value))) }; let arms = make::match_arm_list(vec![ok_arm, err_arm]); - make::expr_match(call_expr, arms) + make::expr_match(call_expr, arms).into() } } } @@ -1879,7 +1875,7 @@ fn make_body(ctx: &AssistContext<'_>, old_indent: IndentLevel, fun: &Function) - .iter() .map(|var| path_expr_from_local(ctx, var.local, fun.mods.edition)); let expr = make::expr_tuple(exprs); - tail_expr = Some(expr); + tail_expr = Some(expr.into()); } }, }; @@ -1910,7 +1906,7 @@ fn make_body(ctx: &AssistContext<'_>, old_indent: IndentLevel, fun: &Function) - match &handler { FlowHandler::None => block, FlowHandler::Try { kind } => { - let block = with_default_tail_expr(block, make::expr_unit()); + let block = with_default_tail_expr(block, make::ext::expr_unit()); map_tail_expr(block, |tail_expr| { let constructor = match kind { TryKind::Option => "Some", @@ -1924,7 +1920,7 @@ fn make_body(ctx: &AssistContext<'_>, old_indent: IndentLevel, fun: &Function) - FlowHandler::If { .. } => { let controlflow_continue = make::expr_call( make::expr_path(make::path_from_text("ControlFlow::Continue")), - make::arg_list(iter::once(make::expr_unit())), + make::arg_list([make::ext::expr_unit()]), ); with_tail_expr(block, controlflow_continue) } @@ -2127,17 +2123,17 @@ fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Op FlowHandler::None | FlowHandler::Try { .. } => return None, FlowHandler::If { .. } => make::expr_call( make::expr_path(make::path_from_text("ControlFlow::Break")), - make::arg_list(iter::once(make::expr_unit())), + make::arg_list([make::ext::expr_unit()]), ), FlowHandler::IfOption { .. } => { - let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); - let args = make::arg_list(iter::once(expr)); + let expr = arg_expr.unwrap_or_else(make::ext::expr_unit); + let args = make::arg_list([expr]); make::expr_call(make::expr_path(make::ext::ident_path("Some")), args) } FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")), FlowHandler::MatchResult { .. } => { - let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new())); - let args = make::arg_list(iter::once(expr)); + let expr = arg_expr.unwrap_or_else(make::ext::expr_unit); + let args = make::arg_list([expr]); make::expr_call(make::expr_path(make::ext::ident_path("Err")), args) } }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs index 0cc807aff64..97321f4ec1e 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs @@ -4,6 +4,7 @@ use ide_db::{ syntax_helpers::{suggest_name, LexedStr}, }; use syntax::{ + algo::ancestors_at_offset, ast::{ self, edit::IndentLevel, edit_in_place::Indent, make, syntax_factory::SyntaxFactory, AstNode, @@ -68,7 +69,10 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let node = if ctx.has_empty_selection() { if let Some(t) = ctx.token_at_offset().find(|it| it.kind() == T![;]) { t.parent().and_then(ast::ExprStmt::cast)?.syntax().clone() - } else if let Some(expr) = ctx.find_node_at_offset::<ast::Expr>() { + } else if let Some(expr) = ancestors_at_offset(ctx.source_file().syntax(), ctx.offset()) + .next() + .and_then(ast::Expr::cast) + { expr.syntax().ancestors().find_map(valid_target_expr)?.syntax().clone() } else { return None; @@ -469,11 +473,11 @@ mod tests { extract_variable, r#" fn main() -> i32 { - if true { + if$0 true { 1 } else { 2 - }$0 + } } "#, r#" @@ -581,11 +585,11 @@ fn main() { extract_variable, r#" fn main() -> i32 { - if true { + if$0 true { 1 } else { 2 - }$0 + } } "#, r#" @@ -676,11 +680,11 @@ fn main() { extract_variable, r#" fn main() -> i32 { - if true { + if$0 true { 1 } else { 2 - }$0 + } } "#, r#" diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs index c879a4a3d95..ac58af62525 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter_or_setter.rs @@ -933,7 +933,7 @@ mod tests_setter { use super::*; - fn check_not_applicable(ra_fixture: &str) { + fn check_not_applicable(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_assist_not_applicable(generate_setter, ra_fixture) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs index d558ec3bec7..cd6f900ba15 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs @@ -38,21 +38,21 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; pub(crate) fn inline_macro(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let unexpanded = ctx.find_node_at_offset::<ast::MacroCall>()?; let macro_call = ctx.sema.to_def(&unexpanded)?; - let expanded = ctx.sema.parse_or_expand(macro_call.as_file()); - let span_map = ctx.sema.db.expansion_span_map(macro_call.as_macro_file()); - let expanded = prettify_macro_expansion( - ctx.db(), - expanded, - &span_map, - ctx.sema.file_to_module_def(ctx.file_id())?.krate().into(), - ); + let target_crate_id = ctx.sema.file_to_module_def(ctx.file_id())?.krate().into(); let text_range = unexpanded.syntax().text_range(); acc.add( AssistId("inline_macro", AssistKind::RefactorInline), "Inline macro".to_owned(), text_range, - |builder| builder.replace(text_range, expanded.to_string()), + |builder| { + let expanded = ctx.sema.parse_or_expand(macro_call.as_file()); + let span_map = ctx.sema.db.expansion_span_map(macro_call.as_macro_file()); + // Don't call `prettify_macro_expansion()` outside the actual assist action; it does some heavy rowan tree manipulation, + // which can be very costly for big macros when it is done *even without the assist being invoked*. + let expanded = prettify_macro_expansion(ctx.db(), expanded, &span_map, target_crate_id); + builder.replace(text_range, expanded.to_string()) + }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs index f0c96fe3cb8..a487960d8d4 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_guard.rs @@ -61,7 +61,7 @@ pub(crate) fn move_guard_to_arm_body(acc: &mut Assists, ctx: &AssistContext<'_>) }; edit.delete(guard.syntax().text_range()); - edit.replace_ast(arm_expr, if_expr); + edit.replace_ast(arm_expr, if_expr.into()); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs index 94274f6d17c..1f57f7d3d37 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs @@ -102,7 +102,7 @@ fn compute_dbg_replacement(macro_expr: ast::MacroExpr) -> Option<(TextRange, Opt }; (range, None) }, - _ => (macro_call.syntax().text_range(), Some(make::expr_unit())), + _ => (macro_call.syntax().text_range(), Some(make::ext::expr_unit())), } } } @@ -152,7 +152,7 @@ fn compute_dbg_replacement(macro_expr: ast::MacroExpr) -> Option<(TextRange, Opt exprs => { let exprs = exprs.iter().cloned().map(replace_nested_dbgs); let expr = make::expr_tuple(exprs); - (macro_call.syntax().text_range(), Some(expr)) + (macro_call.syntax().text_range(), Some(expr.into())) } }) } @@ -209,7 +209,10 @@ mod tests { use super::*; - fn check(ra_fixture_before: &str, ra_fixture_after: &str) { + fn check( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, + ) { check_assist( remove_dbg, &format!("fn main() {{\n{ra_fixture_before}\n}}"), diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs index b31d45e6d45..e324d6eaaad 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs @@ -1,4 +1,4 @@ -use std::iter::{self, successors}; +use std::iter::successors; use either::Either; use ide_db::{ @@ -8,11 +8,7 @@ use ide_db::{ RootDatabase, }; use syntax::{ - ast::{ - self, - edit::{AstNodeEdit, IndentLevel}, - make, HasName, - }, + ast::{self, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory, HasName}, AstNode, TextRange, T, }; @@ -108,53 +104,58 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<' AssistId("replace_if_let_with_match", AssistKind::RefactorRewrite), format!("Replace if{let_} with match"), available_range, - move |edit| { + move |builder| { + let make = SyntaxFactory::new(); let match_expr = { - let else_arm = make_else_arm(ctx, else_block, &cond_bodies); + let else_arm = make_else_arm(ctx, &make, else_block, &cond_bodies); let make_match_arm = |(pat, body): (_, ast::BlockExpr)| { - let body = body.reset_indent().indent(IndentLevel(1)); + let body = make.block_expr(body.statements(), body.tail_expr()); + body.indent(IndentLevel::from(1)); + let body = unwrap_trivial_block(body); match pat { - Either::Left(pat) => { - make::match_arm(iter::once(pat), None, unwrap_trivial_block(body)) + Either::Left(pat) => make.match_arm(pat, None, body), + Either::Right(_) if !pat_seen => { + make.match_arm(make.literal_pat("true").into(), None, body) } - Either::Right(_) if !pat_seen => make::match_arm( - iter::once(make::literal_pat("true").into()), - None, - unwrap_trivial_block(body), - ), - Either::Right(expr) => make::match_arm( - iter::once(make::wildcard_pat().into()), - Some(expr), - unwrap_trivial_block(body), + Either::Right(expr) => make.match_arm( + make.wildcard_pat().into(), + Some(make.match_guard(expr)), + body, ), } }; - let arms = cond_bodies.into_iter().map(make_match_arm).chain(iter::once(else_arm)); - let match_expr = make::expr_match(scrutinee_to_be_expr, make::match_arm_list(arms)); - match_expr.indent(IndentLevel::from_node(if_expr.syntax())) + let arms = cond_bodies.into_iter().map(make_match_arm).chain([else_arm]); + let match_expr = make.expr_match(scrutinee_to_be_expr, make.match_arm_list(arms)); + match_expr.indent(IndentLevel::from_node(if_expr.syntax())); + match_expr.into() }; let has_preceding_if_expr = if_expr.syntax().parent().is_some_and(|it| ast::IfExpr::can_cast(it.kind())); let expr = if has_preceding_if_expr { // make sure we replace the `else if let ...` with a block so we don't end up with `else expr` - make::block_expr(None, Some(match_expr)).into() + make.block_expr([], Some(match_expr)).into() } else { match_expr }; - edit.replace_ast::<ast::Expr>(if_expr.into(), expr); + + let mut editor = builder.make_editor(if_expr.syntax()); + editor.replace(if_expr.syntax(), expr.syntax()); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ) } fn make_else_arm( ctx: &AssistContext<'_>, + make: &SyntaxFactory, else_block: Option<ast::BlockExpr>, conditionals: &[(Either<ast::Pat, ast::Expr>, ast::BlockExpr)], ) -> ast::MatchArm { let (pattern, expr) = if let Some(else_block) = else_block { let pattern = match conditionals { - [(Either::Right(_), _)] => make::literal_pat("false").into(), + [(Either::Right(_), _)] => make.literal_pat("false").into(), [(Either::Left(pat), _)] => match ctx .sema .type_of_pat(pat) @@ -164,24 +165,24 @@ fn make_else_arm( if does_pat_match_variant(pat, &it.sad_pattern()) { it.happy_pattern_wildcard() } else if does_pat_variant_nested_or_literal(ctx, pat) { - make::wildcard_pat().into() + make.wildcard_pat().into() } else { it.sad_pattern() } } - None => make::wildcard_pat().into(), + None => make.wildcard_pat().into(), }, - _ => make::wildcard_pat().into(), + _ => make.wildcard_pat().into(), }; (pattern, unwrap_trivial_block(else_block)) } else { let pattern = match conditionals { - [(Either::Right(_), _)] => make::literal_pat("false").into(), - _ => make::wildcard_pat().into(), + [(Either::Right(_), _)] => make.literal_pat("false").into(), + _ => make.wildcard_pat().into(), }; - (pattern, make::expr_unit()) + (pattern, make.expr_unit()) }; - make::match_arm(iter::once(pattern), None, expr) + make.match_arm(pattern, None, expr) } // Assist: replace_match_with_if_let @@ -247,21 +248,21 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<' } _ => " let", }; - let target = match_expr.syntax().text_range(); acc.add( AssistId("replace_match_with_if_let", AssistKind::RefactorRewrite), format!("Replace match with if{let_}"), - target, - move |edit| { - fn make_block_expr(expr: ast::Expr) -> ast::BlockExpr { + match_expr.syntax().text_range(), + move |builder| { + let make = SyntaxFactory::new(); + let make_block_expr = |expr: ast::Expr| { // Blocks with modifiers (unsafe, async, etc.) are parsed as BlockExpr, but are // formatted without enclosing braces. If we encounter such block exprs, // wrap them in another BlockExpr. match expr { ast::Expr::BlockExpr(block) if block.modifier().is_none() => block, - expr => make::block_expr(iter::empty(), Some(expr)), + expr => make.block_expr([], Some(expr)), } - } + }; let condition = match if_let_pat { ast::Pat::LiteralPat(p) @@ -272,20 +273,25 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<' ast::Pat::LiteralPat(p) if p.literal().is_some_and(|it| it.token().kind() == T![false]) => { - make::expr_prefix(T![!], scrutinee) + make.expr_prefix(T![!], scrutinee).into() } - _ => make::expr_let(if_let_pat, scrutinee).into(), + _ => make.expr_let(if_let_pat, scrutinee).into(), }; - let then_block = make_block_expr(then_expr.reset_indent()); + let then_expr = then_expr.clone_for_update(); + then_expr.reindent_to(IndentLevel::single()); + let then_block = make_block_expr(then_expr); let else_expr = if is_empty_expr(&else_expr) { None } else { Some(else_expr) }; - let if_let_expr = make::expr_if( + let if_let_expr = make.expr_if( condition, then_block, else_expr.map(make_block_expr).map(ast::ElseBranch::Block), - ) - .indent(IndentLevel::from_node(match_expr.syntax())); + ); + if_let_expr.indent(IndentLevel::from_node(match_expr.syntax())); - edit.replace_ast::<ast::Expr>(match_expr.into(), if_let_expr); + let mut editor = builder.make_editor(match_expr.syntax()); + editor.replace(match_expr.syntax(), if_let_expr.syntax()); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs index c2be4593b97..c071d3022d2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_let_with_if_let.rs @@ -1,12 +1,6 @@ -use std::iter::once; - use ide_db::ty_filter::TryEnum; use syntax::{ - ast::{ - self, - edit::{AstNodeEdit, IndentLevel}, - make, - }, + ast::{self, edit::IndentLevel, edit_in_place::Indent, syntax_factory::SyntaxFactory}, AstNode, T, }; @@ -47,7 +41,9 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_> AssistId("replace_let_with_if_let", AssistKind::RefactorRewrite), "Replace let with if let", target, - |edit| { + |builder| { + let mut editor = builder.make_editor(let_stmt.syntax()); + let make = SyntaxFactory::new(); let ty = ctx.sema.type_of_expr(&init); let happy_variant = ty .and_then(|ty| TryEnum::from_ty(&ctx.sema, &ty.adjusted())) @@ -55,17 +51,18 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_> let pat = match happy_variant { None => original_pat, Some(var_name) => { - make::tuple_struct_pat(make::ext::ident_path(var_name), once(original_pat)) - .into() + make.tuple_struct_pat(make.ident_path(var_name), [original_pat]).into() } }; - let block = - make::ext::empty_block_expr().indent(IndentLevel::from_node(let_stmt.syntax())); - let if_ = make::expr_if(make::expr_let(pat, init).into(), block, None); - let stmt = make::expr_stmt(if_); + let block = make.block_expr([], None); + block.indent(IndentLevel::from_node(let_stmt.syntax())); + let if_expr = make.expr_if(make.expr_let(pat, init).into(), block, None); + let if_stmt = make.expr_stmt(if_expr.into()); - edit.replace_ast(ast::Stmt::from(let_stmt), ast::Stmt::from(stmt)); + editor.replace(let_stmt.syntax(), if_stmt.syntax()); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs index 2e26f59d030..88b50543dda 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_try_expr_with_match.rs @@ -71,19 +71,17 @@ pub(crate) fn replace_try_expr_with_match( }; let happy_arm = make::match_arm( - iter::once( - try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()), - ), + try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()), None, make::expr_path(make::ext::ident_path("it")), ); - let sad_arm = make::match_arm(iter::once(sad_pat), None, sad_expr); + let sad_arm = make::match_arm(sad_pat, None, sad_expr); let match_arm_list = make::match_arm_list([happy_arm, sad_arm]); let expr_match = make::expr_match(expr, match_arm_list) .indent(IndentLevel::from_node(qm_kw_parent.syntax())); - edit.replace_ast::<ast::Expr>(qm_kw_parent.into(), expr_match); + edit.replace_ast::<ast::Expr>(qm_kw_parent.into(), expr_match.into()); }, ) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs index c6cffb5434a..6b9f661d4de 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs @@ -54,13 +54,9 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let pats_after = pipe_token .siblings_with_tokens(Direction::Next) .filter_map(|it| ast::Pat::cast(it.into_node()?)); - // FIXME: We should add a leading pipe if the original arm has one. - let new_match_arm = make::match_arm( - pats_after, - match_arm.guard().and_then(|guard| guard.condition()), - match_arm_body, - ) - .clone_for_update(); + let new_pat = make::or_pat(pats_after, or_pat.leading_pipe().is_some()); + let new_match_arm = + make::match_arm(new_pat, match_arm.guard(), match_arm_body).clone_for_update(); let mut pipe_index = pipe_token.index(); if pipe_token diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs index f3e7f5f4167..fd37140e9c2 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_block.rs @@ -61,7 +61,7 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option } } None => { - let empty_tuple = make::expr_tuple([]); + let empty_tuple = make::ext::expr_unit(); make::let_stmt(pattern, ty, Some(empty_tuple)).to_string() } }; diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs index 64d5e2c9b82..f647b531b77 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_return_type.rs @@ -1,11 +1,11 @@ +use either::Either; use ide_db::{ famous_defs::FamousDefs, syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, }; -use itertools::Itertools; use syntax::{ - ast::{self, Expr, HasGenericArgs}, - match_ast, AstNode, NodeOrToken, SyntaxKind, TextRange, + ast::{self, syntax_factory::SyntaxFactory, HasArgList, HasGenericArgs}, + match_ast, AstNode, NodeOrToken, SyntaxKind, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -39,11 +39,11 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let ret_type = ctx.find_node_at_offset::<ast::RetType>()?; let parent = ret_type.syntax().parent()?; - let body = match_ast! { + let body_expr = match_ast! { match parent { - ast::Fn(func) => func.body()?, + ast::Fn(func) => func.body()?.into(), ast::ClosureExpr(closure) => match closure.body()? { - Expr::BlockExpr(block) => block, + ast::Expr::BlockExpr(block) => block.into(), // closures require a block when a return type is specified _ => return None, }, @@ -65,72 +65,110 @@ pub(crate) fn unwrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> let happy_type = extract_wrapped_type(type_ref)?; acc.add(kind.assist_id(), kind.label(), type_ref.syntax().text_range(), |builder| { - let body = ast::Expr::BlockExpr(body); + let mut editor = builder.make_editor(&parent); + let make = SyntaxFactory::new(); let mut exprs_to_unwrap = Vec::new(); let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_unwrap, e); - walk_expr(&body, &mut |expr| { - if let Expr::ReturnExpr(ret_expr) = expr { + walk_expr(&body_expr, &mut |expr| { + if let ast::Expr::ReturnExpr(ret_expr) = expr { if let Some(ret_expr_arg) = &ret_expr.expr() { for_each_tail_expr(ret_expr_arg, tail_cb); } } }); - for_each_tail_expr(&body, tail_cb); + for_each_tail_expr(&body_expr, tail_cb); let is_unit_type = is_unit_type(&happy_type); if is_unit_type { - let mut text_range = ret_type.syntax().text_range(); - if let Some(NodeOrToken::Token(token)) = ret_type.syntax().next_sibling_or_token() { if token.kind() == SyntaxKind::WHITESPACE { - text_range = TextRange::new(text_range.start(), token.text_range().end()); + editor.delete(token); } } - builder.delete(text_range); + editor.delete(ret_type.syntax()); } else { - builder.replace(type_ref.syntax().text_range(), happy_type.syntax().text()); + editor.replace(type_ref.syntax(), happy_type.syntax()); } - for ret_expr_arg in exprs_to_unwrap { - let ret_expr_str = ret_expr_arg.to_string(); - - let needs_replacing = match kind { - UnwrapperKind::Option => ret_expr_str.starts_with("Some("), - UnwrapperKind::Result => { - ret_expr_str.starts_with("Ok(") || ret_expr_str.starts_with("Err(") - } - }; + let mut final_placeholder = None; + for tail_expr in exprs_to_unwrap { + match &tail_expr { + ast::Expr::CallExpr(call_expr) => { + let ast::Expr::PathExpr(path_expr) = call_expr.expr().unwrap() else { + continue; + }; + + let path_str = path_expr.path().unwrap().to_string(); + let needs_replacing = match kind { + UnwrapperKind::Option => path_str == "Some", + UnwrapperKind::Result => path_str == "Ok" || path_str == "Err", + }; + + if !needs_replacing { + continue; + } - if needs_replacing { - let arg_list = ret_expr_arg.syntax().children().find_map(ast::ArgList::cast); - if let Some(arg_list) = arg_list { + let arg_list = call_expr.arg_list().unwrap(); if is_unit_type { - match ret_expr_arg.syntax().prev_sibling_or_token() { - // Useful to delete the entire line without leaving trailing whitespaces - Some(whitespace) => { - let new_range = TextRange::new( - whitespace.text_range().start(), - ret_expr_arg.syntax().text_range().end(), - ); - builder.delete(new_range); + let tail_parent = tail_expr + .syntax() + .parent() + .and_then(Either::<ast::ReturnExpr, ast::StmtList>::cast) + .unwrap(); + match tail_parent { + Either::Left(ret_expr) => { + editor.replace(ret_expr.syntax(), make.expr_return(None).syntax()) } - None => { - builder.delete(ret_expr_arg.syntax().text_range()); + Either::Right(stmt_list) => { + let new_block = if stmt_list.statements().next().is_none() { + make.expr_empty_block() + } else { + make.block_expr(stmt_list.statements(), None) + }; + editor.replace( + stmt_list.syntax(), + new_block.stmt_list().unwrap().syntax(), + ); } } - } else { - builder.replace( - ret_expr_arg.syntax().text_range(), - arg_list.args().join(", "), + } else if let Some(first_arg) = arg_list.args().next() { + editor.replace(tail_expr.syntax(), first_arg.syntax()); + } + } + ast::Expr::PathExpr(path_expr) => { + let UnwrapperKind::Option = kind else { + continue; + }; + + if path_expr.path().unwrap().to_string() != "None" { + continue; + } + + let new_tail_expr = make.expr_unit(); + editor.replace(path_expr.syntax(), new_tail_expr.syntax()); + if let Some(cap) = ctx.config.snippet_cap { + editor.add_annotation( + new_tail_expr.syntax(), + builder.make_placeholder_snippet(cap), ); + + final_placeholder = Some(new_tail_expr); } } - } else if matches!(kind, UnwrapperKind::Option if ret_expr_str == "None") { - builder.replace(ret_expr_arg.syntax().text_range(), "()"); + _ => (), } } + + if let Some(cap) = ctx.config.snippet_cap { + if let Some(final_placeholder) = final_placeholder { + editor.add_annotation(final_placeholder.syntax(), builder.make_tabstop_after(cap)); + } + } + + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }) } @@ -168,12 +206,12 @@ impl UnwrapperKind { fn tail_cb_impl(acc: &mut Vec<ast::Expr>, e: &ast::Expr) { match e { - Expr::BreakExpr(break_expr) => { + ast::Expr::BreakExpr(break_expr) => { if let Some(break_expr_arg) = break_expr.expr() { for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(acc, e)) } } - Expr::ReturnExpr(_) => { + ast::Expr::ReturnExpr(_) => { // all return expressions have already been handled by the walk loop } e => acc.push(e.clone()), @@ -238,8 +276,7 @@ fn foo() -> Option<()$0> { } "#, r#" -fn foo() { -} +fn foo() {} "#, "Unwrap Option return type", ); @@ -254,8 +291,7 @@ fn foo() -> Option<()$0>{ } "#, r#" -fn foo() { -} +fn foo() {} "#, "Unwrap Option return type", ); @@ -280,7 +316,42 @@ fn foo() -> i32 { if true { 42 } else { - () + ${1:()}$0 + } +} +"#, + "Unwrap Option return type", + ); + } + + #[test] + fn unwrap_option_return_type_multi_none() { + check_assist_by_label( + unwrap_return_type, + r#" +//- minicore: option +fn foo() -> Option<i3$02> { + if false { + return None; + } + + if true { + Some(42) + } else { + None + } +} +"#, + r#" +fn foo() -> i32 { + if false { + return ${1:()}; + } + + if true { + 42 + } else { + ${2:()}$0 } } "#, @@ -1262,8 +1333,7 @@ fn foo() -> Result<(), Box<dyn Error$0>> { } "#, r#" -fn foo() { -} +fn foo() {} "#, "Unwrap Result return type", ); @@ -1278,8 +1348,7 @@ fn foo() -> Result<(), Box<dyn Error$0>>{ } "#, r#" -fn foo() { -} +fn foo() {} "#, "Unwrap Result return type", ); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs index 658600cd2d0..0b145dcb06b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/wrap_return_type.rs @@ -6,10 +6,9 @@ use ide_db::{ famous_defs::FamousDefs, syntax_helpers::node_ext::{for_each_tail_expr, walk_expr}, }; -use itertools::Itertools; use syntax::{ - ast::{self, make, Expr, HasGenericParams}, - match_ast, ted, AstNode, ToSmolStr, + ast::{self, syntax_factory::SyntaxFactory, Expr, HasGenericArgs, HasGenericParams}, + match_ast, AstNode, }; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -43,11 +42,11 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { let ret_type = ctx.find_node_at_offset::<ast::RetType>()?; let parent = ret_type.syntax().parent()?; - let body = match_ast! { + let body_expr = match_ast! { match parent { - ast::Fn(func) => func.body()?, + ast::Fn(func) => func.body()?.into(), ast::ClosureExpr(closure) => match closure.body()? { - Expr::BlockExpr(block) => block, + Expr::BlockExpr(block) => block.into(), // closures require a block when a return type is specified _ => return None, }, @@ -75,56 +74,65 @@ pub(crate) fn wrap_return_type(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op kind.assist_id(), kind.label(), type_ref.syntax().text_range(), - |edit| { - let alias = wrapper_alias(ctx, &core_wrapper, type_ref, kind.symbol()); - let new_return_ty = - alias.unwrap_or_else(|| kind.wrap_type(type_ref)).clone_for_update(); - - let body = edit.make_mut(ast::Expr::BlockExpr(body.clone())); + |builder| { + let mut editor = builder.make_editor(&parent); + let make = SyntaxFactory::new(); + let alias = wrapper_alias(ctx, &make, &core_wrapper, type_ref, kind.symbol()); + let new_return_ty = alias.unwrap_or_else(|| match kind { + WrapperKind::Option => make.ty_option(type_ref.clone()), + WrapperKind::Result => make.ty_result(type_ref.clone(), make.ty_infer().into()), + }); let mut exprs_to_wrap = Vec::new(); let tail_cb = &mut |e: &_| tail_cb_impl(&mut exprs_to_wrap, e); - walk_expr(&body, &mut |expr| { + walk_expr(&body_expr, &mut |expr| { if let Expr::ReturnExpr(ret_expr) = expr { if let Some(ret_expr_arg) = &ret_expr.expr() { for_each_tail_expr(ret_expr_arg, tail_cb); } } }); - for_each_tail_expr(&body, tail_cb); + for_each_tail_expr(&body_expr, tail_cb); for ret_expr_arg in exprs_to_wrap { - let happy_wrapped = make::expr_call( - make::expr_path(make::ext::ident_path(kind.happy_ident())), - make::arg_list(iter::once(ret_expr_arg.clone())), - ) - .clone_for_update(); - ted::replace(ret_expr_arg.syntax(), happy_wrapped.syntax()); + let happy_wrapped = make.expr_call( + make.expr_path(make.ident_path(kind.happy_ident())), + make.arg_list(iter::once(ret_expr_arg.clone())), + ); + editor.replace(ret_expr_arg.syntax(), happy_wrapped.syntax()); } - let old_return_ty = edit.make_mut(type_ref.clone()); - ted::replace(old_return_ty.syntax(), new_return_ty.syntax()); + editor.replace(type_ref.syntax(), new_return_ty.syntax()); if let WrapperKind::Result = kind { // Add a placeholder snippet at the first generic argument that doesn't equal the return type. // This is normally the error type, but that may not be the case when we inserted a type alias. - let args = - new_return_ty.syntax().descendants().find_map(ast::GenericArgList::cast); - let error_type_arg = args.and_then(|list| { - list.generic_args().find(|arg| match arg { - ast::GenericArg::TypeArg(_) => { - arg.syntax().text() != type_ref.syntax().text() - } - ast::GenericArg::LifetimeArg(_) => false, - _ => true, - }) + let args = new_return_ty + .path() + .unwrap() + .segment() + .unwrap() + .generic_arg_list() + .unwrap(); + let error_type_arg = args.generic_args().find(|arg| match arg { + ast::GenericArg::TypeArg(_) => { + arg.syntax().text() != type_ref.syntax().text() + } + ast::GenericArg::LifetimeArg(_) => false, + _ => true, }); if let Some(error_type_arg) = error_type_arg { if let Some(cap) = ctx.config.snippet_cap { - edit.add_placeholder_snippet(cap, error_type_arg); + editor.add_annotation( + error_type_arg.syntax(), + builder.make_placeholder_snippet(cap), + ); } } } + + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ); } @@ -176,22 +184,16 @@ impl WrapperKind { WrapperKind::Result => hir::sym::Result.clone(), } } - - fn wrap_type(&self, type_ref: &ast::Type) -> ast::Type { - match self { - WrapperKind::Option => make::ext::ty_option(type_ref.clone()), - WrapperKind::Result => make::ext::ty_result(type_ref.clone(), make::ty_placeholder()), - } - } } // Try to find an wrapper type alias in the current scope (shadowing the default). fn wrapper_alias( ctx: &AssistContext<'_>, + make: &SyntaxFactory, core_wrapper: &hir::Enum, ret_type: &ast::Type, wrapper: hir::Symbol, -) -> Option<ast::Type> { +) -> Option<ast::PathType> { let wrapper_path = hir::ModPath::from_segments( hir::PathKind::Plain, iter::once(hir::Name::new_symbol_root(wrapper)), @@ -207,25 +209,28 @@ fn wrapper_alias( }) .find_map(|alias| { let mut inserted_ret_type = false; - let generic_params = alias - .source(ctx.db())? - .value - .generic_param_list()? - .generic_params() - .map(|param| match param { - // Replace the very first type parameter with the functions return type. - ast::GenericParam::TypeParam(_) if !inserted_ret_type => { - inserted_ret_type = true; - ret_type.to_smolstr() + let generic_args = + alias.source(ctx.db())?.value.generic_param_list()?.generic_params().map(|param| { + match param { + // Replace the very first type parameter with the function's return type. + ast::GenericParam::TypeParam(_) if !inserted_ret_type => { + inserted_ret_type = true; + make.type_arg(ret_type.clone()).into() + } + ast::GenericParam::LifetimeParam(_) => { + make.lifetime_arg(make.lifetime("'_")).into() + } + _ => make.type_arg(make.ty_infer().into()).into(), } - ast::GenericParam::LifetimeParam(_) => make::lifetime("'_").to_smolstr(), - _ => make::ty_placeholder().to_smolstr(), - }) - .join(", "); + }); let name = alias.name(ctx.db()); - let name = name.as_str(); - Some(make::ty(&format!("{name}<{generic_params}>"))) + let generic_arg_list = make.generic_arg_list(generic_args, false); + let path = make.path_unqualified( + make.path_segment_generics(make.name_ref(name.as_str()), generic_arg_list), + ); + + Some(make.ty_path(path)) }) }) } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs index 0b1ff87c5c2..48d2af6d3ff 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs @@ -77,7 +77,11 @@ pub(crate) fn with_single_file(text: &str) -> (RootDatabase, EditionedFileId) { } #[track_caller] -pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_after: &str) { +pub(crate) fn check_assist( + assist: Handler, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { let ra_fixture_after = trim_indent(ra_fixture_after); check(assist, ra_fixture_before, ExpectedResult::After(&ra_fixture_after), None); } @@ -85,8 +89,8 @@ pub(crate) fn check_assist(assist: Handler, ra_fixture_before: &str, ra_fixture_ #[track_caller] pub(crate) fn check_assist_no_snippet_cap( assist: Handler, - ra_fixture_before: &str, - ra_fixture_after: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, ) { let ra_fixture_after = trim_indent(ra_fixture_after); check_with_config( @@ -101,8 +105,8 @@ pub(crate) fn check_assist_no_snippet_cap( #[track_caller] pub(crate) fn check_assist_import_one( assist: Handler, - ra_fixture_before: &str, - ra_fixture_after: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, ) { let ra_fixture_after = trim_indent(ra_fixture_after); check_with_config( @@ -118,8 +122,8 @@ pub(crate) fn check_assist_import_one( // so this is here to allow you choose. pub(crate) fn check_assist_by_label( assist: Handler, - ra_fixture_before: &str, - ra_fixture_after: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, label: &str, ) { let ra_fixture_after = trim_indent(ra_fixture_after); @@ -130,22 +134,36 @@ pub(crate) fn check_assist_by_label( // `extract_ranges` and mark the target as `<target> </target>` in the // fixture? #[track_caller] -pub(crate) fn check_assist_target(assist: Handler, ra_fixture: &str, target: &str) { +pub(crate) fn check_assist_target( + assist: Handler, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + target: &str, +) { check(assist, ra_fixture, ExpectedResult::Target(target), None); } #[track_caller] -pub(crate) fn check_assist_not_applicable(assist: Handler, ra_fixture: &str) { +pub(crate) fn check_assist_not_applicable( + assist: Handler, + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) { check(assist, ra_fixture, ExpectedResult::NotApplicable, None); } #[track_caller] -pub(crate) fn check_assist_not_applicable_by_label(assist: Handler, ra_fixture: &str, label: &str) { +pub(crate) fn check_assist_not_applicable_by_label( + assist: Handler, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + label: &str, +) { check(assist, ra_fixture, ExpectedResult::NotApplicable, Some(label)); } #[track_caller] -pub(crate) fn check_assist_not_applicable_for_import_one(assist: Handler, ra_fixture: &str) { +pub(crate) fn check_assist_not_applicable_for_import_one( + assist: Handler, + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) { check_with_config( TEST_CONFIG_IMPORT_ONE, assist, @@ -157,7 +175,10 @@ pub(crate) fn check_assist_not_applicable_for_import_one(assist: Handler, ra_fix /// Check assist in unresolved state. Useful to check assists for lazy computation. #[track_caller] -pub(crate) fn check_assist_unresolved(assist: Handler, ra_fixture: &str) { +pub(crate) fn check_assist_unresolved( + assist: Handler, + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) { check(assist, ra_fixture, ExpectedResult::Unresolved, None); } diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs index e20c4ef09e8..78ff4417913 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs @@ -246,7 +246,7 @@ pub(crate) fn vis_offset(node: &SyntaxNode) -> TextSize { } pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr { - invert_special_case(&expr).unwrap_or_else(|| make::expr_prefix(T![!], expr)) + invert_special_case(&expr).unwrap_or_else(|| make::expr_prefix(T![!], expr).into()) } fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> { @@ -262,7 +262,7 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> { T![>] => T![<=], T![>=] => T![<], // Parenthesize other expressions before prefixing `!` - _ => return Some(make::expr_prefix(T![!], make::expr_paren(expr.clone()))), + _ => return Some(make::expr_prefix(T![!], make::expr_paren(expr.clone())).into()), }; ted::replace(op_token, make::token(rev_token)); Some(bin.into()) diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs index 75caf6d49f7..7a9bdfe1ecc 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs @@ -66,7 +66,7 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let pat = make::record_pat(variant_name.clone(), pats.into_iter()); let fields = make::record_expr_field_list(fields); let record_expr = make::record_expr(variant_name, fields).into(); - arms.push(make::match_arm(Some(pat.into()), None, record_expr)); + arms.push(make::match_arm(pat.into(), None, record_expr)); } // => match self { Self::Name(arg1) => Self::Name(arg1.clone()) } @@ -84,21 +84,21 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let pat = make::tuple_struct_pat(variant_name.clone(), pats.into_iter()); let struct_name = make::expr_path(variant_name); let tuple_expr = make::expr_call(struct_name, make::arg_list(fields)); - arms.push(make::match_arm(Some(pat.into()), None, tuple_expr)); + arms.push(make::match_arm(pat.into(), None, tuple_expr)); } // => match self { Self::Name => Self::Name } None => { let pattern = make::path_pat(variant_name.clone()); let variant_expr = make::expr_path(variant_name); - arms.push(make::match_arm(Some(pattern), None, variant_expr)); + arms.push(make::match_arm(pattern, None, variant_expr)); } } } let match_target = make::expr_path(make::ext::ident_path("self")); let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); - make::expr_match(match_target, list) + make::expr_match(match_target, list).into() } ast::Adt::Struct(strukt) => { match strukt.field_list() { @@ -190,7 +190,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { // => MyStruct { fields.. } => f.debug_struct("MyStruct")...finish(), let pat = make::record_pat(variant_name.clone(), pats.into_iter()); - arms.push(make::match_arm(Some(pat.into()), None, expr)); + arms.push(make::match_arm(pat.into(), None, expr)); } Some(ast::FieldList::TupleFieldList(list)) => { // => f.debug_tuple(name) @@ -223,7 +223,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { // => MyStruct (fields..) => f.debug_tuple("MyStruct")...finish(), let pat = make::tuple_struct_pat(variant_name.clone(), pats.into_iter()); - arms.push(make::match_arm(Some(pat.into()), None, expr)); + arms.push(make::match_arm(pat.into(), None, expr)); } None => { let fmt_string = make::expr_literal(&(format!("\"{name}\""))).into(); @@ -232,7 +232,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let macro_call = make::expr_macro_call(macro_name, args); let variant_name = make::path_pat(variant_name); - arms.push(make::match_arm(Some(variant_name), None, macro_call)); + arms.push(make::match_arm(variant_name, None, macro_call)); } } } @@ -241,7 +241,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> { let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); let match_expr = make::expr_match(match_target, list); - let body = make::block_expr(None, Some(match_expr)); + let body = make::block_expr(None, Some(match_expr.into())); let body = body.indent(ast::edit::IndentLevel(1)); ted::replace(func.body()?.syntax(), body.clone_for_update().syntax()); Some(()) @@ -485,7 +485,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) - let tuple = make::tuple_pat(vec![left.into(), right.into()]); if let Some(expr) = expr { - arms.push(make::match_arm(Some(tuple.into()), None, expr)); + arms.push(make::match_arm(tuple.into(), None, expr)); } } @@ -518,7 +518,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) - let tuple = make::tuple_pat(vec![left.into(), right.into()]); if let Some(expr) = expr { - arms.push(make::match_arm(Some(tuple.into()), None, expr)); + arms.push(make::match_arm(tuple.into(), None, expr)); } } None => continue, @@ -538,12 +538,12 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) - } else { eq_check }; - arms.push(make::match_arm(Some(lhs), None, rhs)); + arms.push(make::match_arm(lhs, None, rhs)); } - let match_target = make::expr_tuple(vec![lhs_name, rhs_name]); + let match_target = make::expr_tuple([lhs_name, rhs_name]).into(); let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); - make::expr_match(match_target, list) + make::expr_match(match_target, list).into() } }; @@ -599,15 +599,15 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) let variant_name = make::path_pat(make::ext::path_from_idents(["core", "cmp", "Ordering", "Equal"])?); let lhs = make::tuple_struct_pat(make::ext::path_from_idents(["Some"])?, [variant_name]); - arms.push(make::match_arm(Some(lhs.into()), None, make::expr_empty_block())); + arms.push(make::match_arm(lhs.into(), None, make::expr_empty_block().into())); arms.push(make::match_arm( - [make::ident_pat(false, false, make::name("ord")).into()], + make::ident_pat(false, false, make::name("ord")).into(), None, make::expr_return(Some(make::expr_path(make::ext::ident_path("ord")))), )); let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1)); - Some(make::expr_stmt(make::expr_match(match_target, list)).into()) + Some(make::expr_stmt(make::expr_match(match_target, list).into()).into()) } fn gen_partial_cmp_call(lhs: ast::Expr, rhs: ast::Expr) -> ast::Expr { diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs index e95b291dd71..d434872ea59 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/ref_field_expr.rs @@ -121,7 +121,7 @@ impl RefData { /// Derefs `expr` and wraps it in parens if necessary pub(crate) fn wrap_expr(&self, mut expr: ast::Expr) -> ast::Expr { if self.needs_deref { - expr = make::expr_prefix(T![*], expr); + expr = make::expr_prefix(T![*], expr).into(); } if self.needs_parentheses { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs index 414627fbaba..40669c65c57 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs @@ -329,7 +329,7 @@ impl Completions { ctx: &CompletionContext<'_>, dot_access: &DotAccess, func: hir::Function, - receiver: Option<hir::Name>, + receiver: Option<SmolStr>, local_name: Option<hir::Name>, ) { if !ctx.check_stability(Some(&func.attrs(ctx.db))) { @@ -475,7 +475,7 @@ impl Completions { &mut self, ctx: &CompletionContext<'_>, dot_access: &DotAccess, - receiver: Option<hir::Name>, + receiver: Option<SmolStr>, field: hir::Field, ty: &hir::Type, ) { @@ -533,7 +533,7 @@ impl Completions { pub(crate) fn add_tuple_field( &mut self, ctx: &CompletionContext<'_>, - receiver: Option<hir::Name>, + receiver: Option<SmolStr>, field: usize, ty: &hir::Type, ) { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs index 26074672ba9..7679d9076de 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs @@ -2,7 +2,7 @@ use std::ops::ControlFlow; -use hir::{sym, HasContainer, ItemContainer, MethodCandidateCallback, Name}; +use hir::{HasContainer, ItemContainer, MethodCandidateCallback, Name}; use ide_db::FxHashSet; use syntax::SmolStr; @@ -25,21 +25,49 @@ pub(crate) fn complete_dot( _ => return, }; + let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. }); + let is_method_access_with_parens = + matches!(dot_access.kind, DotAccessKind::Method { has_parens: true }); + let traits_in_scope = ctx.traits_in_scope(); + // Suggest .await syntax for types that implement Future trait - if receiver_ty.impls_into_future(ctx.db) { + if let Some(future_output) = receiver_ty.into_future_output(ctx.db) { + let await_str = SmolStr::new_static("await"); let mut item = CompletionItem::new( CompletionItemKind::Keyword, ctx.source_range(), - SmolStr::new_static("await"), + await_str.clone(), ctx.edition, ); item.detail("expr.await"); item.add_to(acc, ctx.db); - } - let is_field_access = matches!(dot_access.kind, DotAccessKind::Field { .. }); - let is_method_access_with_parens = - matches!(dot_access.kind, DotAccessKind::Method { has_parens: true }); + // Completions that skip `.await`, e.g. `.await.foo()`. + let dot_access_kind = match &dot_access.kind { + DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => { + DotAccessKind::Field { receiver_is_ambiguous_float_literal: false } + } + it @ DotAccessKind::Method { .. } => *it, + }; + let dot_access = DotAccess { + receiver: dot_access.receiver.clone(), + receiver_ty: Some(hir::TypeInfo { original: future_output.clone(), adjusted: None }), + kind: dot_access_kind, + ctx: dot_access.ctx, + }; + complete_fields( + acc, + ctx, + &future_output, + |acc, field, ty| acc.add_field(ctx, &dot_access, Some(await_str.clone()), field, &ty), + |acc, field, ty| acc.add_tuple_field(ctx, Some(await_str.clone()), field, &ty), + is_field_access, + is_method_access_with_parens, + ); + complete_methods(ctx, &future_output, &traits_in_scope, |func| { + acc.add_method(ctx, &dot_access, func, Some(await_str.clone()), None) + }); + } complete_fields( acc, @@ -50,8 +78,44 @@ pub(crate) fn complete_dot( is_field_access, is_method_access_with_parens, ); + complete_methods(ctx, receiver_ty, &traits_in_scope, |func| { + acc.add_method(ctx, dot_access, func, None, None) + }); - complete_methods(ctx, receiver_ty, |func| acc.add_method(ctx, dot_access, func, None, None)); + // FIXME: + // Checking for the existence of `iter()` is complicated in our setup, because we need to substitute + // its return type, so we instead check for `<&Self as IntoIterator>::IntoIter`. + // Does <&receiver_ty as IntoIterator>::IntoIter` exist? Assume `iter` is valid + let iter = receiver_ty + .strip_references() + .add_reference(hir::Mutability::Shared) + .into_iterator_iter(ctx.db) + .map(|ty| (ty, SmolStr::new_static("iter()"))); + // Does <receiver_ty as IntoIterator>::IntoIter` exist? + let into_iter = || { + receiver_ty + .clone() + .into_iterator_iter(ctx.db) + .map(|ty| (ty, SmolStr::new_static("into_iter()"))) + }; + if let Some((iter, iter_sym)) = iter.or_else(into_iter) { + // Skip iterators, e.g. complete `.iter().filter_map()`. + let dot_access_kind = match &dot_access.kind { + DotAccessKind::Field { receiver_is_ambiguous_float_literal: _ } => { + DotAccessKind::Field { receiver_is_ambiguous_float_literal: false } + } + it @ DotAccessKind::Method { .. } => *it, + }; + let dot_access = DotAccess { + receiver: dot_access.receiver.clone(), + receiver_ty: Some(hir::TypeInfo { original: iter.clone(), adjusted: None }), + kind: dot_access_kind, + ctx: dot_access.ctx, + }; + complete_methods(ctx, &iter, &traits_in_scope, |func| { + acc.add_method(ctx, &dot_access, func, Some(iter_sym.clone()), None) + }); + } } pub(crate) fn complete_undotted_self( @@ -94,18 +158,16 @@ pub(crate) fn complete_undotted_self( in_breakable: expr_ctx.in_breakable, }, }, - Some(Name::new_symbol_root(sym::self_.clone())), + Some(SmolStr::new_static("self")), field, &ty, ) }, - |acc, field, ty| { - acc.add_tuple_field(ctx, Some(Name::new_symbol_root(sym::self_.clone())), field, &ty) - }, + |acc, field, ty| acc.add_tuple_field(ctx, Some(SmolStr::new_static("self")), field, &ty), true, false, ); - complete_methods(ctx, &ty, |func| { + complete_methods(ctx, &ty, &ctx.traits_in_scope(), |func| { acc.add_method( ctx, &DotAccess { @@ -118,7 +180,7 @@ pub(crate) fn complete_undotted_self( }, }, func, - Some(Name::new_symbol_root(sym::self_.clone())), + Some(SmolStr::new_static("self")), None, ) }); @@ -160,6 +222,7 @@ fn complete_fields( fn complete_methods( ctx: &CompletionContext<'_>, receiver: &hir::Type, + traits_in_scope: &FxHashSet<hir::TraitId>, f: impl FnMut(hir::Function), ) { struct Callback<'a, F> { @@ -205,7 +268,7 @@ fn complete_methods( receiver.iterate_method_candidates_split_inherent( ctx.db, &ctx.scope, - &ctx.traits_in_scope(), + traits_in_scope, Some(ctx.module), None, Callback { ctx, f, seen_methods: FxHashSet::default() }, @@ -214,25 +277,13 @@ fn complete_methods( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::expect; - use crate::tests::{ - check_edit, completion_list_no_kw, completion_list_no_kw_with_private_editable, - }; - - fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list_no_kw(ra_fixture); - expect.assert_eq(&actual); - } - - fn check_with_private_editable(ra_fixture: &str, expect: Expect) { - let actual = completion_list_no_kw_with_private_editable(ra_fixture); - expect.assert_eq(&actual); - } + use crate::tests::{check_edit, check_no_kw, check_with_private_editable}; #[test] fn test_struct_field_and_method_completion() { - check( + check_no_kw( r#" struct S { foo: u32 } impl S { @@ -249,7 +300,7 @@ fn foo(s: S) { s.$0 } #[test] fn no_unstable_method_on_stable() { - check( + check_no_kw( r#" //- /main.rs crate:main deps:std fn foo(s: std::S) { s.$0 } @@ -266,7 +317,7 @@ impl S { #[test] fn unstable_method_on_nightly() { - check( + check_no_kw( r#" //- toolchain:nightly //- /main.rs crate:main deps:std @@ -286,7 +337,7 @@ impl S { #[test] fn test_struct_field_completion_self() { - check( + check_no_kw( r#" struct S { the_field: (u32,) } impl S { @@ -302,7 +353,7 @@ impl S { #[test] fn test_struct_field_completion_autoderef() { - check( + check_no_kw( r#" struct A { the_field: (u32, i32) } impl A { @@ -318,7 +369,7 @@ impl A { #[test] fn test_no_struct_field_completion_for_method_call() { - check( + check_no_kw( r#" struct A { the_field: u32 } fn foo(a: A) { a.$0() } @@ -329,7 +380,7 @@ fn foo(a: A) { a.$0() } #[test] fn test_visibility_filtering() { - check( + check_no_kw( r#" //- /lib.rs crate:lib new_source_root:local pub mod m { @@ -348,7 +399,7 @@ fn foo(a: lib::m::A) { a.$0 } "#]], ); - check( + check_no_kw( r#" //- /lib.rs crate:lib new_source_root:library pub mod m { @@ -367,7 +418,7 @@ fn foo(a: lib::m::A) { a.$0 } "#]], ); - check( + check_no_kw( r#" //- /lib.rs crate:lib new_source_root:library pub mod m { @@ -384,7 +435,7 @@ fn foo(a: lib::m::A) { a.$0 } "#]], ); - check( + check_no_kw( r#" //- /lib.rs crate:lib new_source_root:local pub struct A {} @@ -402,7 +453,7 @@ fn foo(a: lib::A) { a.$0 } me pub_method() fn(&self) "#]], ); - check( + check_no_kw( r#" //- /lib.rs crate:lib new_source_root:library pub struct A {} @@ -524,7 +575,7 @@ fn foo(a: lib::A) { a.$0 } #[test] fn test_local_impls() { - check( + check_no_kw( r#" pub struct A {} mod m { @@ -553,7 +604,7 @@ fn foo(a: A) { #[test] fn test_doc_hidden_filtering() { - check( + check_no_kw( r#" //- /lib.rs crate:lib deps:dep fn foo(a: dep::A) { a.$0 } @@ -580,7 +631,7 @@ impl A { #[test] fn test_union_field_completion() { - check( + check_no_kw( r#" union U { field: u8, other: u16 } fn foo(u: U) { u.$0 } @@ -594,7 +645,7 @@ fn foo(u: U) { u.$0 } #[test] fn test_method_completion_only_fitting_impls() { - check( + check_no_kw( r#" struct A<T> {} impl A<u32> { @@ -613,7 +664,7 @@ fn foo(a: A<u32>) { a.$0 } #[test] fn test_trait_method_completion() { - check( + check_no_kw( r#" struct A {} trait Trait { fn the_method(&self); } @@ -643,7 +694,7 @@ fn foo(a: A) { a.the_method();$0 } #[test] fn test_trait_method_completion_deduplicated() { - check( + check_no_kw( r" struct A {} trait Trait { fn the_method(&self); } @@ -658,7 +709,7 @@ fn foo(a: &A) { a.$0 } #[test] fn completes_trait_method_from_other_module() { - check( + check_no_kw( r" struct A {} mod m { @@ -676,7 +727,7 @@ fn foo(a: A) { a.$0 } #[test] fn test_no_non_self_method() { - check( + check_no_kw( r#" struct A {} impl A { @@ -692,7 +743,7 @@ fn foo(a: A) { #[test] fn test_tuple_field_completion() { - check( + check_no_kw( r#" fn foo() { let b = (0, 3.14); @@ -708,7 +759,7 @@ fn foo() { #[test] fn test_tuple_struct_field_completion() { - check( + check_no_kw( r#" struct S(i32, f64); fn foo() { @@ -725,7 +776,7 @@ fn foo() { #[test] fn test_tuple_field_inference() { - check( + check_no_kw( r#" pub struct S; impl S { pub fn blah(&self) {} } @@ -747,7 +798,7 @@ impl T { #[test] fn test_field_no_same_name() { - check( + check_no_kw( r#" //- minicore: deref struct A { field: u8 } @@ -770,7 +821,7 @@ fn test(a: A) { #[test] fn test_tuple_field_no_same_index() { - check( + check_no_kw( r#" //- minicore: deref struct A(u8); @@ -793,7 +844,7 @@ fn test(a: A) { #[test] fn test_tuple_struct_deref_to_tuple_no_same_index() { - check( + check_no_kw( r#" //- minicore: deref struct A(u8); @@ -815,7 +866,7 @@ fn test(a: A) { #[test] fn test_completion_works_in_consts() { - check( + check_no_kw( r#" struct A { the_field: u32 } const X: u32 = { @@ -830,7 +881,7 @@ const X: u32 = { #[test] fn works_in_simple_macro_1() { - check( + check_no_kw( r#" macro_rules! m { ($e:expr) => { $e } } struct A { the_field: u32 } @@ -847,7 +898,7 @@ fn foo(a: A) { #[test] fn works_in_simple_macro_2() { // this doesn't work yet because the macro doesn't expand without the token -- maybe it can be fixed with better recovery - check( + check_no_kw( r#" macro_rules! m { ($e:expr) => { $e } } struct A { the_field: u32 } @@ -863,7 +914,7 @@ fn foo(a: A) { #[test] fn works_in_simple_macro_recursive_1() { - check( + check_no_kw( r#" macro_rules! m { ($e:expr) => { $e } } struct A { the_field: u32 } @@ -879,7 +930,7 @@ fn foo(a: A) { #[test] fn macro_expansion_resilient() { - check( + check_no_kw( r#" macro_rules! d { () => {}; @@ -905,7 +956,7 @@ fn foo(a: A) { #[test] fn test_method_completion_issue_3547() { - check( + check_no_kw( r#" struct HashSet<T> {} impl<T> HashSet<T> { @@ -924,7 +975,7 @@ fn foo() { #[test] fn completes_method_call_when_receiver_is_a_macro_call() { - check( + check_no_kw( r#" struct S; impl S { fn foo(&self) {} } @@ -939,7 +990,7 @@ fn main() { make_s!().f$0; } #[test] fn completes_after_macro_call_in_submodule() { - check( + check_no_kw( r#" macro_rules! empty { () => {}; @@ -967,7 +1018,7 @@ mod foo { #[test] fn issue_8931() { - check( + check_no_kw( r#" //- minicore: fn struct S; @@ -994,7 +1045,7 @@ impl S { #[test] fn completes_bare_fields_and_methods_in_methods() { - check( + check_no_kw( r#" struct Foo { field: i32 } @@ -1008,7 +1059,7 @@ impl Foo { fn foo(&self) { $0 } }"#, bt u32 u32 "#]], ); - check( + check_no_kw( r#" struct Foo(i32); @@ -1026,7 +1077,7 @@ impl Foo { fn foo(&mut self) { $0 } }"#, #[test] fn macro_completion_after_dot() { - check( + check_no_kw( r#" macro_rules! m { ($e:expr) => { $e }; @@ -1051,7 +1102,7 @@ fn f() { #[test] fn completes_method_call_when_receiver_type_has_errors_issue_10297() { - check( + check_no_kw( r#" //- minicore: iterator, sized struct Vec<T>; @@ -1102,7 +1153,7 @@ fn main() { #[test] fn issue_12484() { - check( + check_no_kw( r#" //- minicore: sized trait SizeUser { @@ -1124,7 +1175,7 @@ fn test(thing: impl Encrypt) { #[test] fn only_consider_same_type_once() { - check( + check_no_kw( r#" //- minicore: deref struct A(u8); @@ -1150,7 +1201,7 @@ fn test(a: A) { #[test] fn no_inference_var_in_completion() { - check( + check_no_kw( r#" struct S<T>(T); fn test(s: S<Unknown>) { @@ -1165,7 +1216,7 @@ fn test(s: S<Unknown>) { #[test] fn assoc_impl_1() { - check( + check_no_kw( r#" //- minicore: deref fn main() { @@ -1206,7 +1257,7 @@ impl<F: core::ops::Deref<Target = impl Bar>> Foo<F> { #[test] fn assoc_impl_2() { - check( + check_no_kw( r#" //- minicore: deref fn main() { @@ -1242,7 +1293,7 @@ impl<B: Bar, F: core::ops::Deref<Target = B>> Foo<F> { #[test] fn test_struct_function_field_completion() { - check( + check_no_kw( r#" struct S { va_field: u32, fn_field: fn() } fn foo() { S { va_field: 0, fn_field: || {} }.fi$0() } @@ -1267,7 +1318,7 @@ fn foo() { (S { va_field: 0, fn_field: || {} }.fn_field)() } #[test] fn test_tuple_function_field_completion() { - check( + check_no_kw( r#" struct B(u32, fn()) fn foo() { @@ -1301,7 +1352,7 @@ fn foo() { #[test] fn test_fn_field_dot_access_method_has_parens_false() { - check( + check_no_kw( r#" struct Foo { baz: fn() } impl Foo { @@ -1318,4 +1369,101 @@ fn baz() { "#]], ); } + + #[test] + fn skip_iter() { + check_no_kw( + r#" + //- minicore: iterator + fn foo() { + [].$0 + } + "#, + expect![[r#" + me clone() (as Clone) fn(&self) -> Self + me into_iter() (as IntoIterator) fn(self) -> <Self as IntoIterator>::IntoIter + "#]], + ); + check_no_kw( + r#" +//- minicore: iterator +struct MyIntoIter; +impl IntoIterator for MyIntoIter { + type Item = (); + type IntoIter = MyIterator; + fn into_iter(self) -> Self::IntoIter { + MyIterator + } +} + +struct MyIterator; +impl Iterator for MyIterator { + type Item = (); + fn next(&mut self) -> Self::Item {} +} + +fn foo() { + MyIntoIter.$0 +} +"#, + expect![[r#" + me into_iter() (as IntoIterator) fn(self) -> <Self as IntoIterator>::IntoIter + me into_iter().by_ref() (as Iterator) fn(&mut self) -> &mut Self + me into_iter().into_iter() (as IntoIterator) fn(self) -> <Self as IntoIterator>::IntoIter + me into_iter().next() (as Iterator) fn(&mut self) -> Option<<Self as Iterator>::Item> + me into_iter().nth(…) (as Iterator) fn(&mut self, usize) -> Option<<Self as Iterator>::Item> + "#]], + ); + } + + #[test] + fn skip_await() { + check_no_kw( + r#" +//- minicore: future +struct Foo; +impl Foo { + fn foo(self) {} +} + +async fn foo() -> Foo { Foo } + +async fn bar() { + foo().$0 +} +"#, + expect![[r#" + me await.foo() fn(self) + me into_future() (use core::future::IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture +"#]], + ); + check_edit( + "foo", + r#" +//- minicore: future +struct Foo; +impl Foo { + fn foo(self) {} +} + +async fn foo() -> Foo { Foo } + +async fn bar() { + foo().$0 +} +"#, + r#" +struct Foo; +impl Foo { + fn foo(self) {} +} + +async fn foo() -> Foo { Foo } + +async fn bar() { + foo().await.foo();$0 +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs index 0b6790d42a6..40af5203e9c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs @@ -68,43 +68,40 @@ pub(crate) fn complete_cargo_env_vars( mod tests { use crate::tests::{check_edit, completion_list}; - fn check(macro_name: &str) { + #[test] + fn completes_env_variable_in_env() { check_edit( "CARGO_BIN_NAME", - &format!( - r#" - #[rustc_builtin_macro] - macro {macro_name} {{ - ($var:literal) => {{ 0 }} - }} - - fn main() {{ - let foo = {macro_name}!("CAR$0"); - }} - "# - ), - &format!( - r#" - #[rustc_builtin_macro] - macro {macro_name} {{ - ($var:literal) => {{ 0 }} - }} - - fn main() {{ - let foo = {macro_name}!("CARGO_BIN_NAME"); - }} - "# - ), + r#" +//- minicore: env +fn main() { + let foo = env!("CAR$0"); +} + "#, + r#" +fn main() { + let foo = env!("CARGO_BIN_NAME"); +} + "#, ); } - #[test] - fn completes_env_variable_in_env() { - check("env") - } #[test] fn completes_env_variable_in_option_env() { - check("option_env"); + check_edit( + "CARGO_BIN_NAME", + r#" +//- minicore: env +fn main() { + let foo = option_env!("CAR$0"); +} + "#, + r#" +fn main() { + let foo = option_env!("CARGO_BIN_NAME"); +} + "#, + ); } #[test] diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs index c2e5eefe101..db18b531d7c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs @@ -62,6 +62,7 @@ pub(crate) fn complete_expr_path( in_condition, incomplete_let, ref ref_expr_parent, + after_amp, ref is_func_update, ref innermost_ret_ty, ref impl_, @@ -69,8 +70,23 @@ pub(crate) fn complete_expr_path( .. } = expr_ctx; - let wants_mut_token = - ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false); + let (has_raw_token, has_const_token, has_mut_token) = ref_expr_parent + .as_ref() + .map(|it| (it.raw_token().is_some(), it.const_token().is_some(), it.mut_token().is_some())) + .unwrap_or((false, false, false)); + + let wants_raw_token = ref_expr_parent.is_some() && !has_raw_token && after_amp; + let wants_const_token = + ref_expr_parent.is_some() && has_raw_token && !has_const_token && !has_mut_token; + let wants_mut_token = if ref_expr_parent.is_some() { + if has_raw_token { + !has_const_token && !has_mut_token + } else { + !has_mut_token + } + } else { + false + }; let scope_def_applicable = |def| match def { ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => false, @@ -354,6 +370,12 @@ pub(crate) fn complete_expr_path( add_keyword("else if", "else if $1 {\n $0\n}"); } + if wants_raw_token { + add_keyword("raw", "raw "); + } + if wants_const_token { + add_keyword("const", "const "); + } if wants_mut_token { add_keyword("mut", "mut "); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs index bcfda928c4d..7c2cc2a6c1d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs @@ -65,18 +65,13 @@ pub(crate) fn complete_extern_abi( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::expect; - use crate::tests::{check_edit, completion_list_no_kw}; - - fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list_no_kw(ra_fixture); - expect.assert_eq(&actual); - } + use crate::tests::{check_edit, check_no_kw}; #[test] fn only_completes_in_string_literals() { - check( + check_no_kw( r#" $0 fn foo {} "#, @@ -86,7 +81,7 @@ $0 fn foo {} #[test] fn requires_extern_prefix() { - check( + check_no_kw( r#" "$0" fn foo {} "#, @@ -96,7 +91,7 @@ $0 fn foo {} #[test] fn works() { - check( + check_no_kw( r#" extern "$0" fn foo {} "#, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs index 3b2b2fd706e..73313eeaa6b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs @@ -5,7 +5,7 @@ use ide_db::imports::{ insert_use::ImportScope, }; use itertools::Itertools; -use syntax::{ast, AstNode, SyntaxNode, ToSmolStr, T}; +use syntax::{ast, AstNode, SyntaxNode, ToSmolStr}; use crate::{ config::AutoImportExclusionType, @@ -403,10 +403,11 @@ fn import_on_the_fly_method( fn import_name(ctx: &CompletionContext<'_>) -> String { let token_kind = ctx.token.kind(); - if matches!(token_kind, T![.] | T![::]) { - String::new() - } else { + + if token_kind.is_any_identifier() { ctx.token.to_string() + } else { + String::new() } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs index a87c60c694a..dcd40c3412c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs @@ -61,18 +61,13 @@ pub(crate) fn format_string( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::expect; - use crate::tests::{check_edit, completion_list_no_kw}; - - fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list_no_kw(ra_fixture); - expect.assert_eq(&actual); - } + use crate::tests::{check_edit, check_no_kw}; #[test] fn works_when_wrapped() { - check( + check_no_kw( r#" //- minicore: fmt macro_rules! print { @@ -89,7 +84,7 @@ fn main() { #[test] fn no_completion_without_brace() { - check( + check_no_kw( r#" //- minicore: fmt fn main() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs index 80d72b460f9..6d1945c4534 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs @@ -514,18 +514,13 @@ fn function_declaration( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::expect; - use crate::tests::{check_edit, completion_list_no_kw}; - - fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list_no_kw(ra_fixture); - expect.assert_eq(&actual) - } + use crate::tests::{check_edit, check_no_kw}; #[test] fn no_completion_inside_fn() { - check( + check_no_kw( r" trait Test { fn test(); fn test2(); } struct T; @@ -544,7 +539,7 @@ impl Test for T { "#]], ); - check( + check_no_kw( r" trait Test { fn test(); fn test2(); } struct T; @@ -558,7 +553,7 @@ impl Test for T { expect![[""]], ); - check( + check_no_kw( r" trait Test { fn test(); fn test2(); } struct T; @@ -573,7 +568,7 @@ impl Test for T { ); // https://github.com/rust-lang/rust-analyzer/pull/5976#issuecomment-692332191 - check( + check_no_kw( r" trait Test { fn test(); fn test2(); } struct T; @@ -587,7 +582,7 @@ impl Test for T { expect![[r#""#]], ); - check( + check_no_kw( r" trait Test { fn test(_: i32); fn test2(); } struct T; @@ -606,7 +601,7 @@ impl Test for T { "#]], ); - check( + check_no_kw( r" trait Test { fn test(_: fn()); fn test2(); } struct T; @@ -624,7 +619,7 @@ impl Test for T { #[test] fn no_completion_inside_const() { - check( + check_no_kw( r" trait Test { const TEST: fn(); const TEST2: u32; type Test; fn test(); } struct T; @@ -636,7 +631,7 @@ impl Test for T { expect![[r#""#]], ); - check( + check_no_kw( r" trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } struct T; @@ -653,7 +648,7 @@ impl Test for T { "#]], ); - check( + check_no_kw( r" trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } struct T; @@ -670,7 +665,7 @@ impl Test for T { "#]], ); - check( + check_no_kw( r" trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } struct T; @@ -689,7 +684,7 @@ impl Test for T { "#]], ); - check( + check_no_kw( r" trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } struct T; @@ -703,7 +698,7 @@ impl Test for T { expect![[""]], ); - check( + check_no_kw( r" trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); } struct T; @@ -720,7 +715,7 @@ impl Test for T { #[test] fn no_completion_inside_type() { - check( + check_no_kw( r" trait Test { type Test; type Test2; fn test(); } struct T; @@ -737,7 +732,7 @@ impl Test for T { "#]], ); - check( + check_no_kw( r" trait Test { type Test; type Test2; fn test(); } struct T; @@ -1263,7 +1258,7 @@ impl Foo<u32> for Bar { #[test] fn works_directly_in_impl() { - check( + check_no_kw( r#" trait Tr { fn required(); @@ -1277,7 +1272,7 @@ impl Tr for () { fn fn required() "#]], ); - check( + check_no_kw( r#" trait Tr { fn provided() {} diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs index 4700ed6c1ae..6541ee502d8 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs @@ -32,14 +32,9 @@ pub(crate) fn complete_for_and_where( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::expect; - use crate::tests::{check_edit, completion_list}; - - fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual) - } + use crate::tests::{check, check_edit}; #[test] fn test_else_edit_after_if() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs index 0692446381b..53a62fe49c5 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/lifetime.rs @@ -59,14 +59,9 @@ pub(crate) fn complete_label( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::expect; - use crate::tests::{check_edit, completion_list}; - - fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual); - } + use crate::tests::{check, check_edit}; #[test] fn check_lifetime_edit() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs index f12f011a6bd..bafe3294209 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/mod_.rs @@ -159,14 +159,9 @@ fn module_chain_to_containing_module_file( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::expect; - use crate::tests::completion_list; - - fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual); - } + use crate::tests::check; #[test] fn lib_module_completion() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs index 7b57eea0524..67ea05e002b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs @@ -303,7 +303,7 @@ fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) { resulting_element = ast::Expr::from(parent_deref_element); - new_element_opt = make::expr_prefix(syntax::T![*], new_element_opt); + new_element_opt = make::expr_prefix(syntax::T![*], new_element_opt).into(); } if let Some(first_ref_expr) = resulting_element.syntax().parent().and_then(ast::RefExpr::cast) { @@ -401,18 +401,13 @@ fn add_custom_postfix_completions( #[cfg(test)] mod tests { - use expect_test::{expect, Expect}; + use expect_test::expect; use crate::{ - tests::{check_edit, check_edit_with_config, completion_list, TEST_CONFIG}, + tests::{check, check_edit, check_edit_with_config, TEST_CONFIG}, CompletionConfig, Snippet, }; - fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual) - } - #[test] fn postfix_completion_works_for_trivial_path_expression() { check( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs index 3705e2c73d6..3a2a4a23a19 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs @@ -146,6 +146,7 @@ pub(crate) struct PathExprCtx { pub(crate) in_condition: bool, pub(crate) incomplete_let: bool, pub(crate) ref_expr_parent: Option<ast::RefExpr>, + pub(crate) after_amp: bool, /// The surrounding RecordExpression we are completing a functional update pub(crate) is_func_update: Option<ast::RecordExpr>, pub(crate) self_param: Option<hir::SelfParam>, @@ -390,7 +391,7 @@ pub(crate) struct DotAccess { pub(crate) ctx: DotAccessExprCtx, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub(crate) enum DotAccessKind { Field { /// True if the receiver is an integer and there is no ident in the original file after it yet @@ -402,7 +403,7 @@ pub(crate) enum DotAccessKind { }, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) struct DotAccessExprCtx { pub(crate) in_block_expr: bool, pub(crate) in_breakable: BreakableKind, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs index acce62a041c..3c4d489c0ff 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs @@ -123,10 +123,11 @@ fn expand( ) -> Option<ExpansionResult> { let _p = tracing::info_span!("CompletionContext::expand").entered(); + // Left biased since there may already be an identifier token there, and we appended to it. if !sema.might_be_inside_macro_call(&fake_ident_token) && original_file .token_at_offset(original_offset + relative_offset) - .right_biased() + .left_biased() .is_some_and(|original_token| !sema.might_be_inside_macro_call(&original_token)) { // Recursion base case. @@ -1150,6 +1151,9 @@ fn classify_name_ref( let after_if_expr = after_if_expr(it.clone()); let ref_expr_parent = path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast); + let after_amp = non_trivia_sibling(it.clone().into(), Direction::Prev) + .map(|it| it.kind() == SyntaxKind::AMP) + .unwrap_or(false); let (innermost_ret_ty, self_param) = { let find_ret_ty = |it: SyntaxNode| { if let Some(item) = ast::Item::cast(it.clone()) { @@ -1219,6 +1223,7 @@ fn classify_name_ref( after_if_expr, in_condition, ref_expr_parent, + after_amp, is_func_update, innermost_ret_ty, self_param, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs index 82a1c10c531..fc2bfc01e62 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs @@ -6,7 +6,7 @@ use crate::{ tests::{position, TEST_CONFIG}, }; -fn check_expected_type_and_name(ra_fixture: &str, expect: Expect) { +fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (db, pos) = position(ra_fixture); let config = TEST_CONFIG; let (completion_context, _analysis) = CompletionContext::new(&db, pos, &config).unwrap(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs index b91f915619d..dc2f9a76802 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs @@ -79,7 +79,7 @@ pub struct CompletionItem { // FIXME: We shouldn't expose Mutability here (that is HIR types at all), its fine for now though // until we have more splitting completions in which case we should think about // generalizing this. See https://github.com/rust-lang/rust-analyzer/issues/12571 - pub ref_match: Option<(Mutability, TextSize)>, + pub ref_match: Option<(CompletionItemRefMode, TextSize)>, /// The import data to add to completion's edits. /// (ImportPath, LastSegment) @@ -128,8 +128,15 @@ impl fmt::Debug for CompletionItem { s.field("relevance", &self.relevance); } - if let Some((mutability, offset)) = &self.ref_match { - s.field("ref_match", &format!("&{}@{offset:?}", mutability.as_keyword_for_ref())); + if let Some((ref_mode, offset)) = self.ref_match { + let prefix = match ref_mode { + CompletionItemRefMode::Reference(mutability) => match mutability { + Mutability::Shared => "&", + Mutability::Mut => "&mut ", + }, + CompletionItemRefMode::Dereference => "*", + }; + s.field("ref_match", &format!("{}@{offset:?}", prefix)); } if self.trigger_call_info { s.field("trigger_call_info", &true); @@ -400,6 +407,12 @@ impl CompletionItemKind { } } +#[derive(Copy, Clone, Debug)] +pub enum CompletionItemRefMode { + Reference(Mutability), + Dereference, +} + impl CompletionItem { pub(crate) fn new( kind: impl Into<CompletionItemKind>, @@ -441,15 +454,14 @@ impl CompletionItem { let mut relevance = self.relevance; relevance.type_match = Some(CompletionRelevanceTypeMatch::Exact); - self.ref_match.map(|(mutability, offset)| { - ( - format!("&{}{}", mutability.as_keyword_for_ref(), self.label.primary), - ide_db::text_edit::Indel::insert( - offset, - format!("&{}", mutability.as_keyword_for_ref()), - ), - relevance, - ) + self.ref_match.map(|(mode, offset)| { + let prefix = match mode { + CompletionItemRefMode::Reference(Mutability::Shared) => "&", + CompletionItemRefMode::Reference(Mutability::Mut) => "&mut ", + CompletionItemRefMode::Dereference => "*", + }; + let label = format!("{prefix}{}", self.label.primary); + (label, ide_db::text_edit::Indel::insert(offset, String::from(prefix)), relevance) }) } } @@ -473,7 +485,7 @@ pub(crate) struct Builder { deprecated: bool, trigger_call_info: bool, relevance: CompletionRelevance, - ref_match: Option<(Mutability, TextSize)>, + ref_match: Option<(CompletionItemRefMode, TextSize)>, edition: Edition, } @@ -657,8 +669,12 @@ impl Builder { self.imports_to_add.push(import_to_add); self } - pub(crate) fn ref_match(&mut self, mutability: Mutability, offset: TextSize) -> &mut Builder { - self.ref_match = Some((mutability, offset)); + pub(crate) fn ref_match( + &mut self, + ref_mode: CompletionItemRefMode, + offset: TextSize, + ) -> &mut Builder { + self.ref_match = Some((ref_mode, offset)); self } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs index ca6c9ad9f08..56d7eeaf8ea 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs @@ -33,8 +33,9 @@ use crate::{ pub use crate::{ config::{AutoImportExclusionType, CallableSnippets, CompletionConfig}, item::{ - CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch, - CompletionRelevanceReturnType, CompletionRelevanceTypeMatch, + CompletionItem, CompletionItemKind, CompletionItemRefMode, CompletionRelevance, + CompletionRelevancePostfixMatch, CompletionRelevanceReturnType, + CompletionRelevanceTypeMatch, }, snippet::{Snippet, SnippetScope}, }; diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs index c239ca512da..61e8114d381 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs @@ -18,7 +18,7 @@ use ide_db::{ imports::import_assets::LocatedImport, RootDatabase, SnippetCap, SymbolKind, }; -use syntax::{ast, format_smolstr, AstNode, Edition, SmolStr, SyntaxKind, TextRange, ToSmolStr}; +use syntax::{ast, format_smolstr, AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr}; use crate::{ context::{DotAccess, DotAccessKind, PathCompletionCtx, PathKind, PatternContext}, @@ -28,7 +28,8 @@ use crate::{ literal::render_variant_lit, macro_::{render_macro, render_macro_pat}, }, - CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance, + CompletionContext, CompletionItem, CompletionItemKind, CompletionItemRefMode, + CompletionRelevance, }; /// Interface for data and methods required for items rendering. #[derive(Debug, Clone)] @@ -122,7 +123,7 @@ impl<'a> RenderContext<'a> { pub(crate) fn render_field( ctx: RenderContext<'_>, dot_access: &DotAccess, - receiver: Option<hir::Name>, + receiver: Option<SmolStr>, field: hir::Field, ty: &hir::Type, ) -> CompletionItem { @@ -136,7 +137,7 @@ pub(crate) fn render_field( let mut item = CompletionItem::new( SymbolKind::Field, ctx.source_range(), - field_with_receiver(db, receiver.as_ref(), &name, ctx.completion.edition), + field_with_receiver(receiver.as_deref(), &name), ctx.completion.edition, ); item.set_relevance(CompletionRelevance { @@ -158,8 +159,7 @@ pub(crate) fn render_field( builder.replace( ctx.source_range(), - field_with_receiver(db, receiver.as_ref(), &escaped_name, ctx.completion.edition) - .into(), + field_with_receiver(receiver.as_deref(), &escaped_name).into(), ); let expected_fn_type = @@ -183,17 +183,12 @@ pub(crate) fn render_field( item.text_edit(builder.finish()); } else { - item.insert_text(field_with_receiver( - db, - receiver.as_ref(), - &escaped_name, - ctx.completion.edition, - )); + item.insert_text(field_with_receiver(receiver.as_deref(), &escaped_name)); } if let Some(receiver) = &dot_access.receiver { if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) { - if let Some(ref_match) = compute_ref_match(ctx.completion, ty) { - item.ref_match(ref_match, original.syntax().text_range().start()); + if let Some(ref_mode) = compute_ref_match(ctx.completion, ty) { + item.ref_match(ref_mode, original.syntax().text_range().start()); } } } @@ -201,33 +196,21 @@ pub(crate) fn render_field( item.build(db) } -fn field_with_receiver( - db: &RootDatabase, - receiver: Option<&hir::Name>, - field_name: &str, - edition: Edition, -) -> SmolStr { - receiver.map_or_else( - || field_name.into(), - |receiver| format_smolstr!("{}.{field_name}", receiver.display(db, edition)), - ) +fn field_with_receiver(receiver: Option<&str>, field_name: &str) -> SmolStr { + receiver + .map_or_else(|| field_name.into(), |receiver| format_smolstr!("{}.{field_name}", receiver)) } pub(crate) fn render_tuple_field( ctx: RenderContext<'_>, - receiver: Option<hir::Name>, + receiver: Option<SmolStr>, field: usize, ty: &hir::Type, ) -> CompletionItem { let mut item = CompletionItem::new( SymbolKind::Field, ctx.source_range(), - field_with_receiver( - ctx.db(), - receiver.as_ref(), - &field.to_string(), - ctx.completion.edition, - ), + field_with_receiver(receiver.as_deref(), &field.to_string()), ctx.completion.edition, ); item.detail(ty.display(ctx.db(), ctx.completion.edition).to_string()) @@ -440,7 +423,7 @@ fn render_resolution_path( let name = local_name.display_no_db(ctx.completion.edition).to_smolstr(); let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution); - if local_name.is_escaped(completion.edition) { + if local_name.needs_escape(completion.edition) { item.insert_text(local_name.display_no_db(completion.edition).to_smolstr()); } // Add `<>` for generic types @@ -638,20 +621,34 @@ fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) fn compute_ref_match( ctx: &CompletionContext<'_>, completion_ty: &hir::Type, -) -> Option<hir::Mutability> { +) -> Option<CompletionItemRefMode> { let expected_type = ctx.expected_type.as_ref()?; - if completion_ty != expected_type { - let expected_type_without_ref = expected_type.remove_ref()?; - if completion_ty.autoderef(ctx.db).any(|deref_ty| deref_ty == expected_type_without_ref) { + let expected_without_ref = expected_type.remove_ref(); + let completion_without_ref = completion_ty.remove_ref(); + + if completion_ty == expected_type { + return None; + } + + if let Some(expected_without_ref) = &expected_without_ref { + if completion_ty.autoderef(ctx.db).any(|ty| ty == *expected_without_ref) { cov_mark::hit!(suggest_ref); let mutability = if expected_type.is_mutable_reference() { hir::Mutability::Mut } else { hir::Mutability::Shared }; - return Some(mutability); - }; + return Some(CompletionItemRefMode::Reference(mutability)); + } + } + + if let Some(completion_without_ref) = completion_without_ref { + if completion_without_ref == *expected_type && completion_without_ref.is_copy(ctx.db) { + cov_mark::hit!(suggest_deref); + return Some(CompletionItemRefMode::Dereference); + } } + None } @@ -664,16 +661,16 @@ fn path_ref_match( if let Some(original_path) = &path_ctx.original_path { // At least one char was typed by the user already, in that case look for the original path if let Some(original_path) = completion.sema.original_ast_node(original_path.clone()) { - if let Some(ref_match) = compute_ref_match(completion, ty) { - item.ref_match(ref_match, original_path.syntax().text_range().start()); + if let Some(ref_mode) = compute_ref_match(completion, ty) { + item.ref_match(ref_mode, original_path.syntax().text_range().start()); } } } else { // completion requested on an empty identifier, there is no path here yet. // FIXME: This might create inconsistent completions where we show a ref match in macro inputs // as long as nothing was typed yet - if let Some(ref_match) = compute_ref_match(completion, ty) { - item.ref_match(ref_match, completion.position.offset); + if let Some(ref_mode) = compute_ref_match(completion, ty) { + item.ref_match(ref_mode, completion.position.offset); } } } @@ -693,20 +690,28 @@ mod tests { }; #[track_caller] - fn check(ra_fixture: &str, kind: impl Into<CompletionItemKind>, expect: Expect) { + fn check( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + kind: impl Into<CompletionItemKind>, + expect: Expect, + ) { let actual = do_completion(ra_fixture, kind.into()); expect.assert_debug_eq(&actual); } #[track_caller] - fn check_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) { + fn check_kinds( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + kinds: &[CompletionItemKind], + expect: Expect, + ) { let actual: Vec<_> = kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect(); expect.assert_debug_eq(&actual); } #[track_caller] - fn check_function_relevance(ra_fixture: &str, expect: Expect) { + fn check_function_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let actual: Vec<_> = do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method)) .into_iter() @@ -717,7 +722,11 @@ mod tests { } #[track_caller] - fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) { + fn check_relevance_for_kinds( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + kinds: &[CompletionItemKind], + expect: Expect, + ) { let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None); actual.retain(|it| kinds.contains(&it.kind)); actual.sort_by_key(|it| cmp::Reverse(it.relevance.score())); @@ -725,7 +734,7 @@ mod tests { } #[track_caller] - fn check_relevance(ra_fixture: &str, expect: Expect) { + fn check_relevance(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None); actual.retain(|it| it.kind != CompletionItemKind::Snippet); actual.retain(|it| it.kind != CompletionItemKind::Keyword); @@ -2053,7 +2062,42 @@ fn main() { } #[test] - fn suggest_deref() { + fn suggest_deref_copy() { + cov_mark::check!(suggest_deref); + check_relevance( + r#" +//- minicore: copy +struct Foo; + +impl Copy for Foo {} +impl Clone for Foo { + fn clone(&self) -> Self { *self } +} + +fn bar(x: Foo) {} + +fn main() { + let foo = &Foo; + bar($0); +} +"#, + expect![[r#" + st Foo Foo [type] + st Foo Foo [type] + ex Foo [type] + lc foo &Foo [local] + lc *foo [type+local] + fn bar(…) fn(Foo) [] + fn main() fn() [] + md core [] + tt Clone [] + tt Copy [] + "#]], + ); + } + + #[test] + fn suggest_deref_trait() { check_relevance( r#" //- minicore: deref diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs index a859d79e243..3b97d67169e 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs @@ -23,7 +23,7 @@ use crate::{ #[derive(Debug)] enum FuncKind<'ctx> { Function(&'ctx PathCompletionCtx), - Method(&'ctx DotAccess, Option<hir::Name>), + Method(&'ctx DotAccess, Option<SmolStr>), } pub(crate) fn render_fn( @@ -39,7 +39,7 @@ pub(crate) fn render_fn( pub(crate) fn render_method( ctx: RenderContext<'_>, dot_access: &DotAccess, - receiver: Option<hir::Name>, + receiver: Option<SmolStr>, local_name: Option<hir::Name>, func: hir::Function, ) -> Builder { @@ -59,16 +59,8 @@ fn render( let (call, escaped_call) = match &func_kind { FuncKind::Method(_, Some(receiver)) => ( - format_smolstr!( - "{}.{}", - receiver.unescaped().display(ctx.db()), - name.unescaped().display(ctx.db()) - ), - format_smolstr!( - "{}.{}", - receiver.display(ctx.db(), completion.edition), - name.display(ctx.db(), completion.edition) - ), + format_smolstr!("{}.{}", receiver, name.unescaped().display(ctx.db())), + format_smolstr!("{}.{}", receiver, name.display(ctx.db(), completion.edition)), ), _ => ( name.unescaped().display(db).to_smolstr(), @@ -143,8 +135,8 @@ fn render( } FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => { if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone()) { - if let Some(ref_match) = compute_ref_match(completion, &ret_type) { - item.ref_match(ref_match, original_expr.syntax().text_range().start()); + if let Some(ref_mode) = compute_ref_match(completion, &ret_type) { + item.ref_match(ref_mode, original_expr.syntax().text_range().start()); } } } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs index 1815f340532..b7dbf0a6306 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs @@ -89,22 +89,24 @@ pub(crate) const TEST_CONFIG: CompletionConfig<'_> = CompletionConfig { exclude_traits: &[], }; -pub(crate) fn completion_list(ra_fixture: &str) -> String { +pub(crate) fn completion_list(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String { completion_list_with_config(TEST_CONFIG, ra_fixture, true, None) } -pub(crate) fn completion_list_no_kw(ra_fixture: &str) -> String { +pub(crate) fn completion_list_no_kw(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> String { completion_list_with_config(TEST_CONFIG, ra_fixture, false, None) } -pub(crate) fn completion_list_no_kw_with_private_editable(ra_fixture: &str) -> String { +pub(crate) fn completion_list_no_kw_with_private_editable( + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) -> String { let mut config = TEST_CONFIG; config.enable_private_editable = true; completion_list_with_config(config, ra_fixture, false, None) } pub(crate) fn completion_list_with_trigger_character( - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, trigger_character: Option<char>, ) -> String { completion_list_with_config(TEST_CONFIG, ra_fixture, true, trigger_character) @@ -112,7 +114,7 @@ pub(crate) fn completion_list_with_trigger_character( fn completion_list_with_config_raw( config: CompletionConfig<'_>, - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, include_keywords: bool, trigger_character: Option<char>, ) -> Vec<CompletionItem> { @@ -135,7 +137,7 @@ fn completion_list_with_config_raw( fn completion_list_with_config( config: CompletionConfig<'_>, - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, include_keywords: bool, trigger_character: Option<char>, ) -> String { @@ -148,7 +150,9 @@ fn completion_list_with_config( } /// Creates analysis from a multi-file fixture, returns positions marked with $0. -pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { +pub(crate) fn position( + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) -> (RootDatabase, FilePosition) { let change_fixture = ChangeFixture::parse(ra_fixture); let mut database = RootDatabase::default(); database.enable_proc_attr_macros(); @@ -216,7 +220,11 @@ fn render_completion_list(completions: Vec<CompletionItem>) -> String { } #[track_caller] -pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { +pub(crate) fn check_edit( + what: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { check_edit_with_config(TEST_CONFIG, what, ra_fixture_before, ra_fixture_after) } @@ -253,11 +261,40 @@ pub(crate) fn check_edit_with_config( assert_eq_text!(&ra_fixture_after, &actual) } -fn check_empty(ra_fixture: &str, expect: Expect) { +pub(crate) fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let actual = completion_list(ra_fixture); expect.assert_eq(&actual); } +pub(crate) fn check_with_base_items( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, +) { + check(&format!("{BASE_ITEMS_FIXTURE}{ra_fixture}"), expect) +} + +pub(crate) fn check_no_kw(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { + let actual = completion_list_no_kw(ra_fixture); + expect.assert_eq(&actual) +} + +pub(crate) fn check_with_private_editable( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, +) { + let actual = completion_list_no_kw_with_private_editable(ra_fixture); + expect.assert_eq(&actual); +} + +pub(crate) fn check_with_trigger_character( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + trigger_character: Option<char>, + expect: Expect, +) { + let actual = completion_list_with_trigger_character(ra_fixture, trigger_character); + expect.assert_eq(&actual) +} + pub(crate) fn get_all_items( config: CompletionConfig<'_>, code: &str, diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs index ebf35820570..32d3b50f237 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs @@ -1,12 +1,7 @@ //! Completion tests for attributes. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::{check_edit, completion_list}; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual); -} +use crate::tests::{check, check_edit}; #[test] fn derive_helpers() { @@ -788,14 +783,9 @@ mod cfg { mod derive { use super::*; - fn check_derive(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual); - } - #[test] fn no_completion_for_incorrect_derive() { - check_derive( + check( r#" //- minicore: derive, copy, clone, ord, eq, default, fmt #[derive{$0)] struct Test; @@ -806,7 +796,7 @@ mod derive { #[test] fn empty_derive() { - check_derive( + check( r#" //- minicore: derive, copy, clone, ord, eq, default, fmt #[derive($0)] struct Test; @@ -828,7 +818,7 @@ mod derive { #[test] fn derive_with_input_before() { - check_derive( + check( r#" //- minicore: derive, copy, clone, ord, eq, default, fmt #[derive(serde::Serialize, PartialEq, $0)] struct Test; @@ -849,7 +839,7 @@ mod derive { #[test] fn derive_with_input_after() { - check_derive( + check( r#" //- minicore: derive, copy, clone, ord, eq, default, fmt #[derive($0 serde::Serialize, PartialEq)] struct Test; @@ -870,7 +860,7 @@ mod derive { #[test] fn derive_with_existing_derives() { - check_derive( + check( r#" //- minicore: derive, copy, clone, ord, eq, default, fmt #[derive(PartialEq, Eq, Or$0)] struct Test; @@ -890,7 +880,7 @@ mod derive { #[test] fn derive_flyimport() { - check_derive( + check( r#" //- proc_macros: derive_identity //- minicore: derive @@ -904,7 +894,7 @@ mod derive { kw self:: "#]], ); - check_derive( + check( r#" //- proc_macros: derive_identity //- minicore: derive @@ -940,7 +930,7 @@ use proc_macros::DeriveIdentity; #[test] fn qualified() { - check_derive( + check( r#" //- proc_macros: derive_identity //- minicore: derive, copy, clone @@ -950,7 +940,7 @@ use proc_macros::DeriveIdentity; de DeriveIdentity proc_macro DeriveIdentity "#]], ); - check_derive( + check( r#" //- proc_macros: derive_identity //- minicore: derive, copy, clone @@ -1056,19 +1046,14 @@ mod lint { mod repr { use super::*; - fn check_repr(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual); - } - #[test] fn no_completion_for_incorrect_repr() { - check_repr(r#"#[repr{$0)] struct Test;"#, expect![[]]) + check(r#"#[repr{$0)] struct Test;"#, expect![[]]) } #[test] fn empty() { - check_repr( + check( r#"#[repr($0)] struct Test;"#, expect![[r#" ba C @@ -1093,12 +1078,12 @@ mod repr { #[test] fn transparent() { - check_repr(r#"#[repr(transparent, $0)] struct Test;"#, expect![[r#""#]]); + check(r#"#[repr(transparent, $0)] struct Test;"#, expect![[r#""#]]); } #[test] fn align() { - check_repr( + check( r#"#[repr(align(1), $0)] struct Test;"#, expect![[r#" ba C @@ -1121,7 +1106,7 @@ mod repr { #[test] fn packed() { - check_repr( + check( r#"#[repr(packed, $0)] struct Test;"#, expect![[r#" ba C @@ -1144,7 +1129,7 @@ mod repr { #[test] fn c() { - check_repr( + check( r#"#[repr(C, $0)] struct Test;"#, expect![[r#" ba align($0) @@ -1167,7 +1152,7 @@ mod repr { #[test] fn prim() { - check_repr( + check( r#"#[repr(usize, $0)] struct Test;"#, expect![[r#" ba C diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs index 30466148686..e117dbf4bdf 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs @@ -4,18 +4,17 @@ use expect_test::{expect, Expect}; use crate::{ config::AutoImportExclusionType, tests::{ - check_edit, check_empty, completion_list, completion_list_with_config, BASE_ITEMS_FIXTURE, + check, check_edit, check_with_base_items, completion_list_with_config, BASE_ITEMS_FIXTURE, TEST_CONFIG, }, CompletionConfig, }; -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}{ra_fixture}")); - expect.assert_eq(&actual) -} - -fn check_with_config(config: CompletionConfig<'_>, ra_fixture: &str, expect: Expect) { +fn check_with_config( + config: CompletionConfig<'_>, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, +) { let actual = completion_list_with_config( config, &format!("{BASE_ITEMS_FIXTURE}{ra_fixture}"), @@ -28,7 +27,7 @@ fn check_with_config(config: CompletionConfig<'_>, ra_fixture: &str, expect: Exp #[test] fn complete_literal_struct_with_a_private_field() { // `FooDesc.bar` is private, the completion should not be triggered. - check( + check_with_base_items( r#" mod _69latrick { pub struct FooDesc { pub six: bool, pub neuf: Vec<String>, bar: bool } @@ -67,6 +66,7 @@ fn baz() { kw loop kw match kw mut + kw raw kw return kw self:: kw true @@ -79,7 +79,7 @@ fn baz() { #[test] fn completes_various_bindings() { - check_empty( + check( r#" fn func(param0 @ (param1, param2): (i32, i32)) { let letlocal = 92; @@ -125,7 +125,7 @@ fn func(param0 @ (param1, param2): (i32, i32)) { #[test] fn completes_all_the_things_in_fn_body() { - check( + check_with_base_items( r#" use non_existent::Unresolved; mod qualified { pub enum Enum { Variant } } @@ -191,7 +191,7 @@ impl Unit { ?? Unresolved "#]], ); - check( + check_with_base_items( r#" use non_existent::Unresolved; mod qualified { pub enum Enum { Variant } } @@ -224,7 +224,7 @@ impl Unit { #[test] fn complete_in_block() { - check_empty( + check( r#" fn foo() { if true { @@ -273,7 +273,7 @@ fn complete_in_block() { #[test] fn complete_after_if_expr() { - check_empty( + check( r#" fn foo() { if true {} @@ -321,7 +321,7 @@ fn complete_after_if_expr() { #[test] fn complete_in_match_arm() { - check_empty( + check( r#" fn foo() { match () { @@ -351,7 +351,7 @@ fn complete_in_match_arm() { #[test] fn completes_in_loop_ctx() { - check_empty( + check( r"fn my() { loop { $0 } }", expect![[r#" fn my() fn() @@ -390,7 +390,7 @@ fn completes_in_loop_ctx() { sn ppd "#]], ); - check_empty( + check( r"fn my() { loop { foo.$0 } }", expect![[r#" sn box Box::new(expr) @@ -415,7 +415,7 @@ fn completes_in_loop_ctx() { #[test] fn completes_in_let_initializer() { - check_empty( + check( r#"fn main() { let _ = $0 }"#, expect![[r#" fn main() fn() @@ -438,8 +438,116 @@ fn completes_in_let_initializer() { } #[test] +fn completes_after_ref_expr() { + check( + r#"fn main() { let _ = &$0 }"#, + expect![[r#" + fn main() fn() + bt u32 u32 + kw crate:: + kw false + kw for + kw if + kw if let + kw loop + kw match + kw mut + kw raw + kw return + kw self:: + kw true + kw unsafe + kw while + kw while let + "#]], + ); + check( + r#"fn main() { let _ = &raw $0 }"#, + expect![[r#" + fn main() fn() + bt u32 u32 + kw const + kw crate:: + kw false + kw for + kw if + kw if let + kw loop + kw match + kw mut + kw return + kw self:: + kw true + kw unsafe + kw while + kw while let + "#]], + ); + check( + r#"fn main() { let _ = &raw const $0 }"#, + expect![[r#" + fn main() fn() + bt u32 u32 + kw crate:: + kw false + kw for + kw if + kw if let + kw loop + kw match + kw return + kw self:: + kw true + kw unsafe + kw while + kw while let + "#]], + ); + check( + r#"fn main() { let _ = &raw mut $0 }"#, + expect![[r#" + fn main() fn() + bt u32 u32 + kw crate:: + kw false + kw for + kw if + kw if let + kw loop + kw match + kw return + kw self:: + kw true + kw unsafe + kw while + kw while let + "#]], + ); + check( + r#"fn main() { let _ = &mut $0 }"#, + expect![[r#" + fn main() fn() + bt u32 u32 + kw crate:: + kw false + kw for + kw if + kw if let + kw loop + kw match + kw return + kw self:: + kw true + kw unsafe + kw while + kw while let + "#]], + ) +} + +#[test] fn struct_initializer_field_expr() { - check_empty( + check( r#" struct Foo { pub f: i32, @@ -475,7 +583,7 @@ fn foo() { fn shadowing_shows_single_completion() { cov_mark::check!(shadowing_shows_single_completion); - check_empty( + check( r#" fn foo() { let bar = 92; @@ -508,7 +616,7 @@ fn foo() { #[test] fn in_macro_expr_frag() { - check_empty( + check( r#" macro_rules! m { ($e:expr) => { $e } } fn quux(x: i32) { @@ -535,7 +643,7 @@ fn quux(x: i32) { kw while let "#]], ); - check_empty( + check( r" macro_rules! m { ($e:expr) => { $e } } fn quux(x: i32) { @@ -562,7 +670,7 @@ fn quux(x: i32) { kw while let "#]], ); - check_empty( + check( r#" macro_rules! m { ($e:expr) => { $e } } fn quux(x: i32) { @@ -595,7 +703,7 @@ fn quux(x: i32) { #[test] fn enum_qualified() { - check( + check_with_base_items( r#" impl Enum { type AssocType = (); @@ -619,7 +727,7 @@ fn func() { #[test] fn ty_qualified_no_drop() { - check_empty( + check( r#" //- minicore: drop struct Foo; @@ -636,7 +744,7 @@ fn func() { #[test] fn with_parens() { - check_empty( + check( r#" enum Enum { Variant() @@ -657,7 +765,7 @@ fn func() { #[test] fn detail_impl_trait_in_return_position() { - check_empty( + check( r" //- minicore: sized trait Trait<T> {} @@ -676,7 +784,7 @@ fn main() { #[test] fn detail_async_fn() { - check_empty( + check( r#" //- minicore: future, sized trait Trait<T> {} @@ -697,7 +805,7 @@ fn main() { #[test] fn detail_impl_trait_in_argument_position() { - check_empty( + check( r" //- minicore: sized trait Trait<T> {} @@ -717,7 +825,7 @@ fn main() { #[test] fn complete_record_expr_path() { - check( + check_with_base_items( r#" struct Zulu; impl Zulu { @@ -738,7 +846,7 @@ fn main() { #[test] fn variant_with_struct() { - check_empty( + check( r#" pub struct YoloVariant { pub f: usize @@ -813,7 +921,7 @@ fn return_value_no_block() { #[test] fn else_completion_after_if() { - check_empty( + check( r#" fn foo() { if foo {} $0 } "#, @@ -854,7 +962,7 @@ fn foo() { if foo {} $0 } sn ppd "#]], ); - check_empty( + check( r#" fn foo() { if foo {} el$0 } "#, @@ -895,7 +1003,7 @@ fn foo() { if foo {} el$0 } sn ppd "#]], ); - check_empty( + check( r#" fn foo() { bar(if foo {} $0) } "#, @@ -919,7 +1027,7 @@ fn foo() { bar(if foo {} $0) } kw while let "#]], ); - check_empty( + check( r#" fn foo() { bar(if foo {} el$0) } "#, @@ -943,7 +1051,7 @@ fn foo() { bar(if foo {} el$0) } kw while let "#]], ); - check_empty( + check( r#" fn foo() { if foo {} $0 let x = 92; } "#, @@ -984,7 +1092,7 @@ fn foo() { if foo {} $0 let x = 92; } sn ppd "#]], ); - check_empty( + check( r#" fn foo() { if foo {} el$0 let x = 92; } "#, @@ -1025,7 +1133,7 @@ fn foo() { if foo {} el$0 let x = 92; } sn ppd "#]], ); - check_empty( + check( r#" fn foo() { if foo {} el$0 { let x = 92; } } "#, @@ -1070,7 +1178,7 @@ fn foo() { if foo {} el$0 { let x = 92; } } #[test] fn expr_no_unstable_item_on_stable() { - check_empty( + check( r#" //- /main.rs crate:main deps:std use std::*; @@ -1121,7 +1229,7 @@ pub struct UnstableThisShouldNotBeListed; #[test] fn expr_unstable_item_on_nightly() { - check_empty( + check( r#" //- toolchain:nightly //- /main.rs crate:main deps:std @@ -1174,7 +1282,7 @@ pub struct UnstableButWeAreOnNightlyAnyway; #[test] fn inside_format_args_completions_work() { - check_empty( + check( r#" //- minicore: fmt struct Foo; @@ -1200,7 +1308,7 @@ fn main() { sn unsafe unsafe {} "#]], ); - check_empty( + check( r#" //- minicore: fmt struct Foo; @@ -1230,7 +1338,7 @@ fn main() { #[test] fn inside_faulty_format_args_completions_work() { - check_empty( + check( r#" //- minicore: fmt struct Foo; @@ -1256,7 +1364,7 @@ fn main() { sn unsafe unsafe {} "#]], ); - check_empty( + check( r#" //- minicore: fmt struct Foo; @@ -1282,7 +1390,7 @@ fn main() { sn unsafe unsafe {} "#]], ); - check_empty( + check( r#" //- minicore: fmt struct Foo; @@ -1308,7 +1416,7 @@ fn main() { sn unsafe unsafe {} "#]], ); - check_empty( + check( r#" //- minicore: fmt struct Foo; @@ -1340,7 +1448,7 @@ fn main() { #[test] fn macro_that_ignores_completion_marker() { - check( + check_with_base_items( r#" macro_rules! helper { ($v:ident) => {}; @@ -1788,7 +1896,7 @@ fn foo<T: ExcludedTrait>() { #[test] fn hide_ragennew_synthetic_identifiers() { - check_empty( + check( r#" //- minicore: iterator fn bar() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index d413977f7c8..d491e438fef 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs @@ -6,11 +6,15 @@ use crate::{ CompletionConfig, }; -fn check(ra_fixture: &str, expect: Expect) { +fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { check_with_config(TEST_CONFIG, ra_fixture, expect); } -fn check_with_config(config: CompletionConfig<'_>, ra_fixture: &str, expect: Expect) { +fn check_with_config( + config: CompletionConfig<'_>, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, +) { let (db, position) = crate::tests::position(ra_fixture); let (ctx, analysis) = crate::context::CompletionContext::new(&db, position, &config).unwrap(); @@ -1742,7 +1746,7 @@ fn intrinsics() { fn function() { transmute$0 } - "#, +"#, expect![[r#" fn transmute(…) (use core::mem::transmute) unsafe fn(Src) -> Dst "#]], @@ -1763,7 +1767,9 @@ fn function() { mem::transmute$0 } "#, - expect![""], + expect![[r#" + fn transmute(…) (use core::mem) unsafe fn(Src) -> Dst + "#]], ); } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs index 4a89f874e15..451ce07c745 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/fn_param.rs @@ -1,16 +1,6 @@ -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::{completion_list, completion_list_with_trigger_character}; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual); -} - -fn check_with_trigger_character(ra_fixture: &str, trigger_character: char, expect: Expect) { - let actual = completion_list_with_trigger_character(ra_fixture, Some(trigger_character)); - expect.assert_eq(&actual) -} +use crate::tests::{check, check_with_trigger_character}; #[test] fn only_param() { @@ -124,7 +114,7 @@ fn trigger_by_l_paren() { r#" fn foo($0) "#, - '(', + Some('('), expect![[]], ) } diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs index 79561a0419f..bea6d60769c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs @@ -2,20 +2,13 @@ //! //! Except for use items which are tested in [super::use_tree] and mod declarations with are tested //! in [crate::completions::mod_]. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::{completion_list, BASE_ITEMS_FIXTURE}; - -use super::check_edit; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}{ra_fixture}")); - expect.assert_eq(&actual) -} +use crate::tests::{check_edit, check_with_base_items}; #[test] fn target_type_or_trait_in_impl_block() { - check( + check_with_base_items( r#" impl Tra$0 "#, @@ -37,7 +30,7 @@ impl Tra$0 #[test] fn target_type_in_trait_impl_block() { - check( + check_with_base_items( r#" impl Trait for Str$0 "#, @@ -59,7 +52,7 @@ impl Trait for Str$0 #[test] fn after_trait_name_in_trait_def() { - check( + check_with_base_items( r"trait A $0", expect![[r#" kw where @@ -69,21 +62,21 @@ fn after_trait_name_in_trait_def() { #[test] fn after_target_name_in_impl() { - check( + check_with_base_items( r"impl Trait $0", expect![[r#" kw for kw where "#]], ); - check( + check_with_base_items( r"impl Trait f$0", expect![[r#" kw for kw where "#]], ); - check( + check_with_base_items( r"impl Trait for Type $0", expect![[r#" kw where @@ -93,44 +86,44 @@ fn after_target_name_in_impl() { #[test] fn completes_where() { - check( + check_with_base_items( r"struct Struct $0", expect![[r#" kw where "#]], ); - check( + check_with_base_items( r"struct Struct $0 {}", expect![[r#" kw where "#]], ); // FIXME: This shouldn't be completed here - check( + check_with_base_items( r"struct Struct $0 ()", expect![[r#" kw where "#]], ); - check( + check_with_base_items( r"fn func() $0", expect![[r#" kw where "#]], ); - check( + check_with_base_items( r"enum Enum $0", expect![[r#" kw where "#]], ); - check( + check_with_base_items( r"enum Enum $0 {}", expect![[r#" kw where "#]], ); - check( + check_with_base_items( r"trait Trait $0 {}", expect![[r#" kw where @@ -140,7 +133,7 @@ fn completes_where() { #[test] fn before_record_field() { - check( + check_with_base_items( r#" struct Foo { $0 @@ -244,7 +237,7 @@ impl Copy for S where $0 #[test] fn test_is_not_considered_macro() { - check( + check_with_base_items( r#" #[rustc_builtin] pub macro test($item:item) { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs index d3d52dc6dfc..841c42123a0 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item_list.rs @@ -1,16 +1,11 @@ //! Completion tests for item list position. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::{check_edit, check_empty, completion_list, BASE_ITEMS_FIXTURE}; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}{ra_fixture}")); - expect.assert_eq(&actual) -} +use crate::tests::{check, check_edit, check_with_base_items}; #[test] fn in_mod_item_list() { - check( + check_with_base_items( r#"mod tests { $0 }"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -43,7 +38,7 @@ fn in_mod_item_list() { #[test] fn in_source_file_item_list() { - check( + check_with_base_items( r#"$0"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -76,7 +71,7 @@ fn in_source_file_item_list() { #[test] fn in_item_list_after_attr() { - check( + check_with_base_items( r#"#[attr] $0"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -109,7 +104,7 @@ fn in_item_list_after_attr() { #[test] fn in_qualified_path() { - check( + check_with_base_items( r#"crate::$0"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -120,7 +115,7 @@ fn in_qualified_path() { #[test] fn after_unsafe_token() { - check( + check_with_base_items( r#"unsafe $0"#, expect![[r#" kw async @@ -134,7 +129,7 @@ fn after_unsafe_token() { #[test] fn after_async_token() { - check( + check_with_base_items( r#"async $0"#, expect![[r#" kw fn @@ -145,7 +140,7 @@ fn after_async_token() { #[test] fn after_visibility() { - check( + check_with_base_items( r#"pub $0"#, expect![[r#" kw async @@ -167,7 +162,7 @@ fn after_visibility() { #[test] fn after_visibility_unsafe() { - check( + check_with_base_items( r#"pub unsafe $0"#, expect![[r#" kw async @@ -179,7 +174,7 @@ fn after_visibility_unsafe() { #[test] fn in_impl_assoc_item_list() { - check( + check_with_base_items( r#"impl Struct { $0 }"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -199,7 +194,7 @@ fn in_impl_assoc_item_list() { #[test] fn in_impl_assoc_item_list_after_attr() { - check( + check_with_base_items( r#"impl Struct { #[attr] $0 }"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -219,7 +214,7 @@ fn in_impl_assoc_item_list_after_attr() { #[test] fn in_trait_assoc_item_list() { - check( + check_with_base_items( r"trait Foo { $0 }", expect![[r#" ma makro!(…) macro_rules! makro @@ -237,7 +232,7 @@ fn in_trait_assoc_item_list() { #[test] fn in_trait_assoc_fn_missing_body() { - check( + check_with_base_items( r#"trait Foo { fn function(); $0 }"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -255,7 +250,7 @@ fn in_trait_assoc_fn_missing_body() { #[test] fn in_trait_assoc_const_missing_body() { - check( + check_with_base_items( r#"trait Foo { const CONST: (); $0 }"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -273,7 +268,7 @@ fn in_trait_assoc_const_missing_body() { #[test] fn in_trait_assoc_type_aliases_missing_ty() { - check( + check_with_base_items( r#"trait Foo { type Type; $0 }"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -291,7 +286,7 @@ fn in_trait_assoc_type_aliases_missing_ty() { #[test] fn in_trait_impl_assoc_item_list() { - check( + check_with_base_items( r#" trait Test { type Type0; @@ -326,7 +321,7 @@ impl Test for () { #[test] fn in_trait_impl_no_unstable_item_on_stable() { - check_empty( + check( r#" trait Test { #[unstable] @@ -350,7 +345,7 @@ impl Test for () { #[test] fn in_trait_impl_unstable_item_on_nightly() { - check_empty( + check( r#" //- toolchain:nightly trait Test { @@ -378,7 +373,7 @@ impl Test for () { #[test] fn after_unit_struct() { - check( + check_with_base_items( r#"struct S; f$0"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -500,7 +495,7 @@ type O = $0; #[test] fn inside_extern_blocks() { // Should suggest `fn`, `static`, `unsafe` - check( + check_with_base_items( r#"extern { $0 }"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -517,7 +512,7 @@ fn inside_extern_blocks() { ); // Should suggest `fn`, `static`, `safe`, `unsafe` - check( + check_with_base_items( r#"unsafe extern { $0 }"#, expect![[r#" ma makro!(…) macro_rules! makro @@ -534,7 +529,7 @@ fn inside_extern_blocks() { "#]], ); - check( + check_with_base_items( r#"unsafe extern { pub safe $0 }"#, expect![[r#" kw fn @@ -542,7 +537,7 @@ fn inside_extern_blocks() { "#]], ); - check( + check_with_base_items( r#"unsafe extern { pub unsafe $0 }"#, expect![[r#" kw fn diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs index 2f1f555e524..9ec27252fd7 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs @@ -1,16 +1,11 @@ //! Completion tests for pattern position. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::{check_edit, check_empty, completion_list, BASE_ITEMS_FIXTURE}; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}\n{ra_fixture}")); - expect.assert_eq(&actual) -} +use crate::tests::{check, check_edit, check_with_base_items}; #[test] fn wildcard() { - check( + check_with_base_items( r#" fn quux() { let _$0 @@ -22,7 +17,7 @@ fn quux() { #[test] fn ident_rebind_pat() { - check_empty( + check( r#" fn quux() { let en$0 @ x @@ -37,7 +32,7 @@ fn quux() { #[test] fn ident_ref_pat() { - check_empty( + check( r#" fn quux() { let ref en$0 @@ -47,7 +42,7 @@ fn quux() { kw mut "#]], ); - check_empty( + check( r#" fn quux() { let ref en$0 @ x @@ -61,7 +56,7 @@ fn quux() { #[test] fn ident_ref_mut_pat() { - check_empty( + check( r#" fn quux() { let ref mut en$0 @@ -69,7 +64,7 @@ fn quux() { "#, expect![[r#""#]], ); - check_empty( + check( r#" fn quux() { let ref mut en$0 @ x @@ -81,7 +76,7 @@ fn quux() { #[test] fn ref_pat() { - check_empty( + check( r#" fn quux() { let &en$0 @@ -91,7 +86,7 @@ fn quux() { kw mut "#]], ); - check_empty( + check( r#" fn quux() { let &mut en$0 @@ -99,7 +94,7 @@ fn quux() { "#, expect![[r#""#]], ); - check_empty( + check( r#" fn foo() { for &$0 in () {} @@ -113,7 +108,7 @@ fn foo() { #[test] fn refutable() { - check( + check_with_base_items( r#" fn foo() { if let a$0 @@ -139,7 +134,7 @@ fn foo() { #[test] fn irrefutable() { - check( + check_with_base_items( r#" enum SingleVariantEnum { Variant @@ -168,7 +163,7 @@ fn foo() { #[test] fn in_param() { - check( + check_with_base_items( r#" fn foo(a$0) { } @@ -185,7 +180,7 @@ fn foo(a$0) { kw ref "#]], ); - check( + check_with_base_items( r#" fn foo(a$0: Tuple) { } @@ -207,7 +202,7 @@ fn foo(a$0: Tuple) { #[test] fn only_fn_like_macros() { - check_empty( + check( r#" macro_rules! m { ($e:expr) => { $e } } @@ -228,7 +223,7 @@ fn foo() { #[test] fn in_simple_macro_call() { - check_empty( + check( r#" macro_rules! m { ($e:expr) => { $e } } enum E { X } @@ -249,7 +244,7 @@ fn foo() { #[test] fn omits_private_fields_pat() { - check_empty( + check( r#" mod foo { pub struct Record { pub field: i32, _field: i32 } @@ -277,7 +272,7 @@ fn outer() { #[test] fn completes_self_pats() { - check_empty( + check( r#" struct Foo(i32); impl Foo { @@ -301,7 +296,7 @@ impl Foo { #[test] fn enum_qualified() { - check( + check_with_base_items( r#" impl Enum { type AssocType = (); @@ -323,7 +318,7 @@ fn func() { #[test] fn completes_in_record_field_pat() { - check_empty( + check( r#" struct Foo { bar: Bar } struct Bar(u32); @@ -342,7 +337,7 @@ fn outer(Foo { bar: $0 }: Foo) {} #[test] fn skips_in_record_field_pat_name() { - check_empty( + check( r#" struct Foo { bar: Bar } struct Bar(u32); @@ -357,7 +352,7 @@ fn outer(Foo { bar$0 }: Foo) {} #[test] fn completes_in_record_field_pat_with_generic_type_alias() { - check_empty( + check( r#" type Wrap<T> = T; @@ -386,7 +381,7 @@ fn main() { #[test] fn completes_in_fn_param() { - check_empty( + check( r#" struct Foo { bar: Bar } struct Bar(u32); @@ -405,7 +400,7 @@ fn foo($0) {} #[test] fn completes_in_closure_param() { - check_empty( + check( r#" struct Foo { bar: Bar } struct Bar(u32); @@ -426,7 +421,7 @@ fn foo() { #[test] fn completes_no_delims_if_existing() { - check_empty( + check( r#" struct Bar(u32); fn foo() { @@ -441,7 +436,7 @@ fn foo() { kw self:: "#]], ); - check_empty( + check( r#" struct Foo { bar: u32 } fn foo() { @@ -456,7 +451,7 @@ fn foo() { kw self:: "#]], ); - check_empty( + check( r#" enum Enum { TupleVariant(u32) @@ -471,7 +466,7 @@ fn foo() { bn TupleVariant TupleVariant "#]], ); - check_empty( + check( r#" enum Enum { RecordVariant { field: u32 } @@ -519,7 +514,7 @@ fn foo() { #[test] fn completes_enum_variant_pat_escape() { cov_mark::check!(enum_variant_pattern_path); - check_empty( + check( r#" enum Enum { A, @@ -544,7 +539,7 @@ fn foo() { "#]], ); - check_empty( + check( r#" enum Enum { A, @@ -569,7 +564,7 @@ fn foo() { #[test] fn completes_associated_const() { - check_empty( + check( r#" #[derive(PartialEq, Eq)] struct Ty(u8); @@ -590,7 +585,7 @@ fn f(t: Ty) { "#]], ); - check_empty( + check( r#" enum MyEnum {} @@ -612,7 +607,7 @@ fn f(e: MyEnum) { "#]], ); - check_empty( + check( r#" union U { i: i32, @@ -637,7 +632,7 @@ fn f(u: U) { "#]], ); - check_empty( + check( r#" #![rustc_coherence_is_core] #[lang = "u32"] @@ -659,7 +654,7 @@ fn f(v: u32) { #[test] fn in_method_param() { - check_empty( + check( r#" struct Ty(u8); @@ -680,7 +675,7 @@ impl Ty { kw ref "#]], ); - check_empty( + check( r#" struct Ty(u8); @@ -701,7 +696,7 @@ impl Ty { kw ref "#]], ); - check_empty( + check( r#" struct Ty(u8); @@ -722,7 +717,7 @@ impl Ty { kw ref "#]], ); - check_empty( + check( r#" struct Ty(u8); @@ -743,7 +738,7 @@ impl Ty { #[test] fn through_alias() { - check_empty( + check( r#" enum Enum<T> { Unit, @@ -770,7 +765,7 @@ fn f(x: EnumAlias<u8>) { #[test] fn pat_no_unstable_item_on_stable() { - check_empty( + check( r#" //- /main.rs crate:main deps:std use std::*; @@ -795,7 +790,7 @@ pub enum Enum { #[test] fn pat_unstable_item_on_nightly() { - check_empty( + check( r#" //- toolchain:nightly //- /main.rs crate:main deps:std @@ -908,7 +903,7 @@ fn foo() { ); // Do not suggest reserved keywords - check_empty( + check( r#" struct Struct; @@ -926,7 +921,7 @@ fn foo() { #[test] fn private_item_in_module_in_function_body() { - check_empty( + check( r#" fn main() { mod foo { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs index c1926359efc..65036f6a224 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs @@ -1,17 +1,12 @@ //! Completion tests for predicates and bounds. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::{check_empty, completion_list, BASE_ITEMS_FIXTURE}; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}\n{ra_fixture}")); - expect.assert_eq(&actual) -} +use crate::tests::{check, check_with_base_items}; #[test] fn predicate_start() { // FIXME: `for` kw - check( + check_with_base_items( r#" struct Foo<'lt, T, const C: usize> where $0 {} "#, @@ -34,7 +29,7 @@ struct Foo<'lt, T, const C: usize> where $0 {} #[test] fn bound_for_type_pred() { - check( + check_with_base_items( r#" struct Foo<'lt, T, const C: usize> where T: $0 {} "#, @@ -52,7 +47,7 @@ struct Foo<'lt, T, const C: usize> where T: $0 {} fn bound_for_lifetime_pred() { // FIXME: should only show lifetimes here, that is we shouldn't get any completions here when not typing // a `'` - check( + check_with_base_items( r#" struct Foo<'lt, T, const C: usize> where 'lt: $0 {} "#, @@ -68,7 +63,7 @@ struct Foo<'lt, T, const C: usize> where 'lt: $0 {} #[test] fn bound_for_for_pred() { - check( + check_with_base_items( r#" struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {} "#, @@ -84,7 +79,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> T: $0 {} #[test] fn param_list_for_for_pred() { - check( + check_with_base_items( r#" struct Foo<'lt, T, const C: usize> where for<'a> $0 {} "#, @@ -107,7 +102,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {} #[test] fn pred_on_fn_in_impl() { - check( + check_with_base_items( r#" impl Record { fn method(self) where $0 {} @@ -132,7 +127,7 @@ impl Record { #[test] fn pred_no_unstable_item_on_stable() { - check_empty( + check( r#" //- /main.rs crate:main deps:std use std::*; @@ -151,7 +146,7 @@ pub trait Trait {} #[test] fn pred_unstable_item_on_nightly() { - check_empty( + check( r#" //- toolchain:nightly //- /main.rs crate:main deps:std diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs index afc286b6fb4..6b1dfe366ce 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/proc_macros.rs @@ -1,12 +1,7 @@ //! Completion tests for expressions. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::completion_list; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual) -} +use crate::tests::check; #[test] fn complete_dot_in_attr() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs index d81b3d697aa..9ab66243b5c 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/raw_identifiers.rs @@ -4,7 +4,7 @@ use itertools::Itertools; use crate::tests::{completion_list_with_config_raw, position, TEST_CONFIG}; -fn check(ra_fixture: &str, expect: Expect) { +fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let completions = completion_list_with_config_raw(TEST_CONFIG, ra_fixture, true, None); let (db, position) = position(ra_fixture); let mut actual = db.file_text(position.file_id).to_string(); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs index a9c9f604e07..a1013b86548 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs @@ -1,14 +1,9 @@ -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::completion_list; +use crate::tests::check; use super::check_edit; -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual); -} - #[test] fn without_default_impl() { check( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs index 6cfb2231a99..2b05184bdbe 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs @@ -5,32 +5,12 @@ use ide_db::SymbolKind; use crate::{ tests::{ - check_edit, completion_list, completion_list_no_kw, completion_list_with_trigger_character, + check, check_edit, check_no_kw, check_with_trigger_character, do_completion_with_config, + TEST_CONFIG, }, CompletionItemKind, }; -use super::{do_completion_with_config, TEST_CONFIG}; - -fn check_no_kw(ra_fixture: &str, expect: Expect) { - let actual = completion_list_no_kw(ra_fixture); - expect.assert_eq(&actual) -} - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual) -} - -pub(crate) fn check_with_trigger_character( - ra_fixture: &str, - trigger_character: Option<char>, - expect: Expect, -) { - let actual = completion_list_with_trigger_character(ra_fixture, trigger_character); - expect.assert_eq(&actual) -} - #[test] fn completes_if_prefix_is_keyword() { check_edit( diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs index 9ea262bcc59..c7e2d058257 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs @@ -1,16 +1,11 @@ //! Completion tests for type position. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::{check_empty, completion_list, BASE_ITEMS_FIXTURE}; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}\n{ra_fixture}")); - expect.assert_eq(&actual) -} +use crate::tests::{check, check_with_base_items}; #[test] fn record_field_ty() { - check( + check_with_base_items( r#" struct Foo<'lt, T, const C: usize> { f: $0 @@ -37,7 +32,7 @@ struct Foo<'lt, T, const C: usize> { #[test] fn tuple_struct_field() { - check( + check_with_base_items( r#" struct Foo<'lt, T, const C: usize>(f$0); "#, @@ -65,7 +60,7 @@ struct Foo<'lt, T, const C: usize>(f$0); #[test] fn fn_return_type() { - check( + check_with_base_items( r#" fn x<'lt, T, const C: usize>() -> $0 "#, @@ -88,7 +83,7 @@ fn x<'lt, T, const C: usize>() -> $0 #[test] fn fn_return_type_no_local_items() { - check( + check_with_base_items( r#" fn foo() -> B$0 { struct Bar; @@ -118,7 +113,7 @@ fn foo() -> B$0 { #[test] fn inferred_type_const() { - check( + check_with_base_items( r#" struct Foo<T>(T); const FOO: $0 = Foo(2); @@ -143,7 +138,7 @@ const FOO: $0 = Foo(2); #[test] fn inferred_type_closure_param() { - check( + check_with_base_items( r#" fn f1(f: fn(i32) -> i32) {} fn f2() { @@ -169,7 +164,7 @@ fn f2() { #[test] fn inferred_type_closure_return() { - check( + check_with_base_items( r#" fn f1(f: fn(u64) -> u64) {} fn f2() { @@ -197,7 +192,7 @@ fn f2() { #[test] fn inferred_type_fn_return() { - check( + check_with_base_items( r#" fn f2(x: u64) -> $0 { x + 5 @@ -222,7 +217,7 @@ fn f2(x: u64) -> $0 { #[test] fn inferred_type_fn_param() { - check( + check_with_base_items( r#" fn f1(x: i32) {} fn f2(x: $0) { @@ -248,7 +243,7 @@ fn f2(x: $0) { #[test] fn inferred_type_not_in_the_scope() { - check( + check_with_base_items( r#" mod a { pub struct Foo<T>(T); @@ -282,7 +277,7 @@ fn foo<'lt, T, const C: usize>() { #[test] fn inferred_type_let() { - check( + check_with_base_items( r#" struct Foo<T>(T); fn foo<'lt, T, const C: usize>() { @@ -311,7 +306,7 @@ fn foo<'lt, T, const C: usize>() { #[test] fn body_type_pos() { - check( + check_with_base_items( r#" fn foo<'lt, T, const C: usize>() { let local = (); @@ -333,7 +328,7 @@ fn foo<'lt, T, const C: usize>() { kw self:: "#]], ); - check( + check_with_base_items( r#" fn foo<'lt, T, const C: usize>() { let local = (); @@ -356,7 +351,7 @@ fn foo<'lt, T, const C: usize>() { #[test] fn completes_types_and_const_in_arg_list() { cov_mark::check!(complete_assoc_type_in_generics_list); - check( + check_with_base_items( r#" trait Trait1 { type Super; @@ -372,7 +367,7 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} ta Super = (as Trait1) type Super "#]], ); - check( + check_with_base_items( r#" trait Trait1 { type Super; @@ -400,7 +395,7 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {} kw self:: "#]], ); - check( + check_with_base_items( r#" trait Trait2<T> { type Foo; @@ -424,7 +419,7 @@ fn foo<'lt, T: Trait2<self::$0>, const CONST_PARAM: usize>(_: T) {} #[test] fn no_assoc_completion_outside_type_bounds() { - check( + check_with_base_items( r#" struct S; trait Tr<T> { @@ -454,7 +449,7 @@ impl Tr<$0 #[test] fn enum_qualified() { - check( + check_with_base_items( r#" impl Enum { type AssocType = (); @@ -471,7 +466,7 @@ fn func(_: Enum::$0) {} #[test] fn completes_type_parameter_or_associated_type() { - check( + check_with_base_items( r#" trait MyTrait<T, U> { type Item1; @@ -496,7 +491,7 @@ fn f(t: impl MyTrait<u$0 "#]], ); - check( + check_with_base_items( r#" trait MyTrait<T, U> { type Item1; @@ -521,7 +516,7 @@ fn f(t: impl MyTrait<u8, u$0 "#]], ); - check( + check_with_base_items( r#" trait MyTrait<T, U> { type Item1; @@ -539,7 +534,7 @@ fn f(t: impl MyTrait<u8, u8, I$0 #[test] fn completes_type_parameter_or_associated_type_with_default_value() { - check( + check_with_base_items( r#" trait MyTrait<T, U = u8> { type Item1; @@ -564,7 +559,7 @@ fn f(t: impl MyTrait<u$0 "#]], ); - check( + check_with_base_items( r#" trait MyTrait<T, U = u8> { type Item1; @@ -591,7 +586,7 @@ fn f(t: impl MyTrait<u8, u$0 "#]], ); - check( + check_with_base_items( r#" trait MyTrait<T, U = u8> { type Item1; @@ -609,7 +604,7 @@ fn f(t: impl MyTrait<u8, u8, I$0 #[test] fn completes_types_after_associated_type() { - check( + check_with_base_items( r#" trait MyTrait { type Item1; @@ -634,7 +629,7 @@ fn f(t: impl MyTrait<Item1 = $0 "#]], ); - check( + check_with_base_items( r#" trait MyTrait { type Item1; @@ -659,7 +654,7 @@ fn f(t: impl MyTrait<Item1 = u8, Item2 = $0 "#]], ); - check( + check_with_base_items( r#" trait MyTrait { const C: usize; @@ -678,7 +673,7 @@ fn f(t: impl MyTrait<C = $0 #[test] fn type_pos_no_unstable_type_on_stable() { - check_empty( + check( r#" //- /main.rs crate:main deps:std use std::*; @@ -702,7 +697,7 @@ pub struct S; #[test] fn type_pos_unstable_type_on_nightly() { - check_empty( + check( r#" //- toolchain:nightly //- /main.rs crate:main deps:std @@ -729,7 +724,7 @@ pub struct S; #[test] fn completes_const_and_type_generics_separately() { // Function generic params - check( + check_with_base_items( r#" struct Foo; const X: usize = 0; @@ -756,7 +751,7 @@ fn completes_const_and_type_generics_separately() { // FIXME: This should probably also suggest completions for types, at least those that have // associated constants usable in this position. For example, a user could be typing // `foo::<_, { usize::MAX }>()`, but we currently don't suggest `usize` in constant position. - check( + check_with_base_items( r#" struct Foo; const X: usize = 0; @@ -775,7 +770,7 @@ fn completes_const_and_type_generics_separately() { ); // Method generic params - check( + check_with_base_items( r#" const X: usize = 0; struct Foo; @@ -799,7 +794,7 @@ fn completes_const_and_type_generics_separately() { kw self:: "#]], ); - check( + check_with_base_items( r#" const X: usize = 0; struct Foo; @@ -818,7 +813,7 @@ fn completes_const_and_type_generics_separately() { ); // Associated type generic params - check( + check_with_base_items( r#" const X: usize = 0; struct Foo; @@ -843,7 +838,7 @@ fn completes_const_and_type_generics_separately() { kw self:: "#]], ); - check( + check_with_base_items( r#" const X: usize = 0; struct Foo; @@ -862,7 +857,7 @@ fn completes_const_and_type_generics_separately() { ); // Type generic params - check( + check_with_base_items( r#" const X: usize = 0; struct Foo<T, const N: usize>(T); @@ -880,7 +875,7 @@ fn completes_const_and_type_generics_separately() { ); // Type alias generic params - check( + check_with_base_items( r#" const X: usize = 0; struct Foo<T, const N: usize>(T); @@ -899,7 +894,7 @@ fn completes_const_and_type_generics_separately() { ); // Enum variant params - check( + check_with_base_items( r#" const X: usize = 0; enum Foo<T, const N: usize> { A(T), B } @@ -917,7 +912,7 @@ fn completes_const_and_type_generics_separately() { ); // Trait params - check( + check_with_base_items( r#" const X: usize = 0; trait Foo<T, const N: usize> {} @@ -933,7 +928,7 @@ fn completes_const_and_type_generics_separately() { ); // Trait alias params - check( + check_with_base_items( r#" #![feature(trait_alias)] const X: usize = 0; @@ -951,7 +946,7 @@ fn completes_const_and_type_generics_separately() { ); // Omitted lifetime params - check( + check_with_base_items( r#" struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); fn foo<'a>() { S::<F$0, _>; } @@ -964,7 +959,7 @@ fn foo<'a>() { S::<F$0, _>; } "#]], ); // Explicit lifetime params - check( + check_with_base_items( r#" struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); fn foo<'a>() { S::<'static, 'static, F$0, _>; } @@ -976,7 +971,7 @@ fn foo<'a>() { S::<'static, 'static, F$0, _>; } kw self:: "#]], ); - check( + check_with_base_items( r#" struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>); fn foo<'a>() { S::<'static, F$0, _, _>; } @@ -992,7 +987,7 @@ fn foo<'a>() { S::<'static, F$0, _, _>; } #[test] fn complete_traits_on_impl_trait_block() { - check( + check_with_base_items( r#" trait Foo {} @@ -1012,7 +1007,7 @@ impl $0 for Bar { } #[test] fn complete_traits_with_path_on_impl_trait_block() { - check( + check_with_base_items( r#" mod outer { pub trait Foo {} diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs index 2ea2e4e4c96..04b3a47a64d 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/use_tree.rs @@ -1,12 +1,7 @@ //! Completion tests for use trees. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::completion_list; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual) -} +use crate::tests::check; #[test] fn use_tree_completion() { diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/visibility.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/visibility.rs index c18d6e66dd6..4b5a0ac1c2b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/visibility.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/visibility.rs @@ -1,17 +1,7 @@ //! Completion tests for visibility modifiers. -use expect_test::{expect, Expect}; +use expect_test::expect; -use crate::tests::{completion_list, completion_list_with_trigger_character}; - -fn check(ra_fixture: &str, expect: Expect) { - let actual = completion_list(ra_fixture); - expect.assert_eq(&actual) -} - -fn check_with_trigger_character(ra_fixture: &str, trigger_character: char, expect: Expect) { - let actual = completion_list_with_trigger_character(ra_fixture, Some(trigger_character)); - expect.assert_eq(&actual) -} +use crate::tests::{check, check_with_trigger_character}; #[test] fn empty_pub() { @@ -20,7 +10,7 @@ fn empty_pub() { r#" pub($0) "#, - '(', + Some('('), expect![[r#" kw crate kw in diff --git a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs index 7482491fc63..11808fed3be 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs @@ -4,7 +4,7 @@ use either::Either; use hir::{InFile, Semantics, Type}; use parser::T; use syntax::{ - ast::{self, HasArgList, HasName}, + ast::{self, AstChildren, HasArgList, HasAttrs, HasName}, match_ast, AstNode, NodeOrToken, SyntaxToken, }; @@ -37,6 +37,10 @@ impl ActiveParameter { _ => None, }) } + + pub fn attrs(&self) -> Option<AstChildren<ast::Attr>> { + self.src.as_ref().and_then(|param| Some(param.value.as_ref().right()?.attrs())) + } } /// Returns a [`hir::Callable`] this token is a part of and its argument index of said callable. diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs index 2d30bb41273..49d26dfe25c 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs @@ -32,6 +32,7 @@ pub enum Definition { Field(Field), TupleField(TupleField), Module(Module), + Crate(Crate), Function(Function), Adt(Adt), Variant(Variant), @@ -62,14 +63,19 @@ impl Definition { pub fn krate(&self, db: &RootDatabase) -> Option<Crate> { Some(match self { Definition::Module(m) => m.krate(), + &Definition::Crate(it) => it, _ => self.module(db)?.krate(), }) } + /// Returns the module this definition resides in. + /// + /// As such, for modules themselves this will return the parent module. pub fn module(&self, db: &RootDatabase) -> Option<Module> { let module = match self { Definition::Macro(it) => it.module(db), Definition::Module(it) => it.parent(db)?, + Definition::Crate(_) => return None, Definition::Field(it) => it.parent_def(db).module(db), Definition::Function(it) => it.module(db), Definition::Adt(it) => it.module(db), @@ -86,11 +92,11 @@ impl Definition { Definition::ExternCrateDecl(it) => it.module(db), Definition::DeriveHelper(it) => it.derive().module(db), Definition::InlineAsmOperand(it) => it.parent(db).module(db), + Definition::ToolModule(t) => t.krate().root_module(), Definition::BuiltinAttr(_) | Definition::BuiltinType(_) | Definition::BuiltinLifetime(_) | Definition::TupleField(_) - | Definition::ToolModule(_) | Definition::InlineAsmRegOrRegClass(_) => return None, }; Some(module) @@ -108,6 +114,7 @@ impl Definition { match self { Definition::Macro(it) => Some(it.module(db).into()), Definition::Module(it) => it.parent(db).map(Definition::Module), + Definition::Crate(_) => None, Definition::Field(it) => Some(it.parent_def(db).into()), Definition::Function(it) => container_to_definition(it.container(db)), Definition::Adt(it) => Some(it.module(db).into()), @@ -137,6 +144,7 @@ impl Definition { let vis = match self { Definition::Field(sf) => sf.visibility(db), Definition::Module(it) => it.visibility(db), + Definition::Crate(_) => return None, Definition::Function(it) => it.visibility(db), Definition::Adt(it) => it.visibility(db), Definition::Const(it) => it.visibility(db), @@ -146,8 +154,8 @@ impl Definition { Definition::TypeAlias(it) => it.visibility(db), Definition::Variant(it) => it.visibility(db), Definition::ExternCrateDecl(it) => it.visibility(db), + Definition::Macro(it) => it.visibility(db), Definition::BuiltinType(_) | Definition::TupleField(_) => Visibility::Public, - Definition::Macro(_) => return None, Definition::BuiltinAttr(_) | Definition::BuiltinLifetime(_) | Definition::ToolModule(_) @@ -167,6 +175,9 @@ impl Definition { Definition::Macro(it) => it.name(db), Definition::Field(it) => it.name(db), Definition::Module(it) => it.name(db)?, + Definition::Crate(it) => { + Name::new_symbol_root(it.display_name(db)?.crate_name().symbol().clone()) + } Definition::Function(it) => it.name(db), Definition::Adt(it) => it.name(db), Definition::Variant(it) => it.name(db), @@ -202,6 +213,7 @@ impl Definition { Definition::Macro(it) => it.docs(db), Definition::Field(it) => it.docs(db), Definition::Module(it) => it.docs(db), + Definition::Crate(it) => it.docs(db), Definition::Function(it) => it.docs(db), Definition::Adt(it) => it.docs(db), Definition::Variant(it) => it.docs(db), @@ -282,6 +294,7 @@ impl Definition { Definition::Field(it) => it.display(db, edition).to_string(), Definition::TupleField(it) => it.display(db, edition).to_string(), Definition::Module(it) => it.display(db, edition).to_string(), + Definition::Crate(it) => it.display(db, edition).to_string(), Definition::Function(it) => it.display(db, edition).to_string(), Definition::Adt(it) => it.display(db, edition).to_string(), Definition::Variant(it) => it.display(db, edition).to_string(), @@ -415,7 +428,7 @@ impl IdentClass { } IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { decl, krate }) => { res.push((Definition::ExternCrateDecl(decl), None)); - res.push((Definition::Module(krate.root_module()), None)); + res.push((Definition::Crate(krate), None)); } IdentClass::Operator( OperatorClass::Await(func) @@ -456,7 +469,7 @@ impl IdentClass { } IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { decl, krate }) => { res.push(Definition::ExternCrateDecl(decl)); - res.push(Definition::Module(krate.root_module())); + res.push(Definition::Crate(krate)); } IdentClass::Operator(_) => (), } @@ -800,7 +813,7 @@ impl NameRefClass { let extern_crate = sema.to_def(&extern_crate_ast)?; let krate = extern_crate.resolved_crate(sema.db)?; Some(if extern_crate_ast.rename().is_some() { - NameRefClass::Definition(Definition::Module(krate.root_module()), None) + NameRefClass::Definition(Definition::Crate(krate), None) } else { NameRefClass::ExternCrateShorthand { krate, decl: extern_crate } }) @@ -976,3 +989,19 @@ impl From<GenericDef> for Definition { } } } + +impl TryFrom<Definition> for GenericDef { + type Error = (); + fn try_from(def: Definition) -> Result<Self, Self::Error> { + match def { + Definition::Function(it) => Ok(it.into()), + Definition::Adt(it) => Ok(it.into()), + Definition::Trait(it) => Ok(it.into()), + Definition::TraitAlias(it) => Ok(it.into()), + Definition::TypeAlias(it) => Ok(it.into()), + Definition::SelfType(it) => Ok(it.into()), + Definition::Const(it) => Ok(it.into()), + _ => Err(()), + } + } +} diff --git a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs index a0ef0f90a65..b83efcd02f7 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs @@ -178,7 +178,7 @@ macro_rules! impl_has_docs { impl_has_docs![ Variant, Field, Static, Const, Trait, TraitAlias, TypeAlias, Macro, Function, Adt, Module, - Impl, + Impl, Crate, ]; macro_rules! impl_has_docs_enum { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs index ba6e50abf65..9e3506d6f53 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/famous_defs.rs @@ -106,6 +106,10 @@ impl FamousDefs<'_, '_> { self.find_trait("core:marker:Copy") } + pub fn core_marker_Sized(&self) -> Option<Trait> { + self.find_trait("core:marker:Sized") + } + pub fn core_future_Future(&self) -> Option<Trait> { self.find_trait("core:future:Future") } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs index 8f0be1d9035..ad86d855b55 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs @@ -1,15 +1,17 @@ //! Look up accessible paths for items. +use std::ops::ControlFlow; + use hir::{ db::HirDatabase, AsAssocItem, AssocItem, AssocItemContainer, Crate, HasCrate, ImportPathConfig, - ItemInNs, ModPath, Module, ModuleDef, PathResolution, PrefixKind, ScopeDef, Semantics, + ItemInNs, ModPath, Module, ModuleDef, Name, PathResolution, PrefixKind, ScopeDef, Semantics, SemanticsScope, Trait, TyFingerprint, Type, }; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ ast::{self, make, HasName}, - AstNode, SmolStr, SyntaxNode, + AstNode, SyntaxNode, }; use crate::{ @@ -51,7 +53,7 @@ pub struct TraitImportCandidate { #[derive(Debug)] pub struct PathImportCandidate { /// Optional qualifier before name. - pub qualifier: Vec<SmolStr>, + pub qualifier: Vec<Name>, /// The name the item (struct, trait, enum, etc.) should have. pub name: NameToImport, } @@ -70,10 +72,18 @@ pub enum NameToImport { impl NameToImport { pub fn exact_case_sensitive(s: String) -> NameToImport { + let s = match s.strip_prefix("r#") { + Some(s) => s.to_owned(), + None => s, + }; NameToImport::Exact(s, true) } pub fn fuzzy(s: String) -> NameToImport { + let s = match s.strip_prefix("r#") { + Some(s) => s.to_owned(), + None => s, + }; // unless all chars are lowercase, we do a case sensitive search let case_sensitive = s.chars().any(|c| c.is_uppercase()); NameToImport::Fuzzy(s, case_sensitive) @@ -350,21 +360,27 @@ fn path_applicable_imports( .take(DEFAULT_QUERY_SEARCH_LIMIT.inner()) .collect() } + // we have some unresolved qualifier that we search an import for + // The key here is that whatever we import must form a resolved path for the remainder of + // what follows + // FIXME: This doesn't handle visibility [first_qsegment, qualifier_rest @ ..] => items_locator::items_with_name( sema, current_crate, - NameToImport::Exact(first_qsegment.to_string(), true), + NameToImport::Exact(first_qsegment.as_str().to_owned(), true), AssocSearchMode::Exclude, ) .filter_map(|item| { - import_for_item( + // we found imports for `first_qsegment`, now we need to filter these imports by whether + // they result in resolving the rest of the path successfully + validate_resolvable( sema, scope, mod_path, + scope_filter, &path_candidate.name, item, qualifier_rest, - scope_filter, ) }) .take(DEFAULT_QUERY_SEARCH_LIMIT.inner()) @@ -372,14 +388,16 @@ fn path_applicable_imports( } } -fn import_for_item( +/// Validates and builds an import for `resolved_qualifier` if the `unresolved_qualifier` appended +/// to it resolves and there is a validate `candidate` after that. +fn validate_resolvable( sema: &Semantics<'_, RootDatabase>, scope: &SemanticsScope<'_>, mod_path: impl Fn(ItemInNs) -> Option<ModPath>, + scope_filter: impl Fn(ItemInNs) -> bool, candidate: &NameToImport, resolved_qualifier: ItemInNs, - unresolved_qualifier: &[SmolStr], - scope_filter: impl Fn(ItemInNs) -> bool, + unresolved_qualifier: &[Name], ) -> Option<LocatedImport> { let _p = tracing::info_span!("ImportAssets::import_for_item").entered(); @@ -410,8 +428,11 @@ fn import_for_item( module, candidate.clone(), AssocSearchMode::Exclude, + |it| match scope_filter(it) { + true => ControlFlow::Break(it), + false => ControlFlow::Continue(()), + }, ) - .find(|&it| scope_filter(it)) .map(|item| LocatedImport::new(import_path_candidate, resolved_qualifier, item)) } // FIXME @@ -709,7 +730,7 @@ fn path_import_candidate( if qualifier.first_qualifier().is_none_or(|it| sema.resolve_path(&it).is_none()) { let qualifier = qualifier .segments() - .map(|seg| seg.name_ref().map(|name| SmolStr::new(name.text()))) + .map(|seg| seg.name_ref().map(|name| Name::new_root(&name.text()))) .collect::<Option<Vec<_>>>()?; ImportCandidate::Path(PathImportCandidate { qualifier, name }) } else { diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs index 81604b55272..decb0ea9d8a 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use/tests.rs @@ -1244,8 +1244,8 @@ use ::ext::foo::Foo; fn check_with_config( path: &str, - ra_fixture_before: &str, - ra_fixture_after: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, config: &InsertUseConfig, ) { let (db, file_id, pos) = if ra_fixture_before.contains(CURSOR_MARKER) { @@ -1277,8 +1277,8 @@ fn check_with_config( fn check( path: &str, - ra_fixture_before: &str, - ra_fixture_after: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, granularity: ImportGranularity, ) { check_with_config( @@ -1295,19 +1295,35 @@ fn check( ) } -fn check_crate(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { +fn check_crate( + path: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Crate) } -fn check_module(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { +fn check_module( + path: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Module) } -fn check_none(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { +fn check_none( + path: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::Item) } -fn check_one(path: &str, ra_fixture_before: &str, ra_fixture_after: &str) { +fn check_one( + path: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { check(path, ra_fixture_before, ra_fixture_after, ImportGranularity::One) } @@ -1330,7 +1346,7 @@ fn check_merge_only_fail(ra_fixture0: &str, ra_fixture1: &str, mb: MergeBehavior assert_eq!(result.map(|u| u.to_string()), None); } -fn check_guess(ra_fixture: &str, expected: ImportGranularityGuess) { +fn check_guess(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: ImportGranularityGuess) { let syntax = ast::SourceFile::parse(ra_fixture, span::Edition::CURRENT).tree().syntax().clone(); let file = ImportScope::from(syntax).unwrap(); assert_eq!(super::guess_granularity_from_scope(&file), expected); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs index 7f66ea0c103..a2062f36d3f 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/items_locator.rs @@ -2,6 +2,8 @@ //! by its name and a few criteria. //! The main reason for this module to exist is the fact that project's items and dependencies' items //! are located in different caches, with different APIs. +use std::ops::ControlFlow; + use either::Either; use hir::{import_map, Crate, ItemInNs, Module, Semantics}; use limit::Limit; @@ -17,6 +19,7 @@ pub static DEFAULT_QUERY_SEARCH_LIMIT: Limit = Limit::new(100); pub use import_map::AssocSearchMode; +// FIXME: Do callbacks instead to avoid allocations. /// Searches for importable items with the given name in the crate and its dependencies. pub fn items_with_name<'a>( sema: &'a Semantics<'_, RootDatabase>, @@ -70,12 +73,13 @@ pub fn items_with_name<'a>( } /// Searches for importable items with the given name in the crate and its dependencies. -pub fn items_with_name_in_module<'a>( - sema: &'a Semantics<'_, RootDatabase>, +pub fn items_with_name_in_module<T>( + sema: &Semantics<'_, RootDatabase>, module: Module, name: NameToImport, assoc_item_search: AssocSearchMode, -) -> impl Iterator<Item = ItemInNs> + 'a { + mut cb: impl FnMut(ItemInNs) -> ControlFlow<T>, +) -> Option<T> { let _p = tracing::info_span!("items_with_name_in", name = name.text(), assoc_item_search = ?assoc_item_search, ?module) .entered(); @@ -107,14 +111,12 @@ pub fn items_with_name_in_module<'a>( local_query } }; - let mut local_results = Vec::new(); local_query.search(&[sema.db.module_symbols(module)], |local_candidate| { - local_results.push(match local_candidate.def { + cb(match local_candidate.def { hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def), def => ItemInNs::from(def), }) - }); - local_results.into_iter() + }) } fn find_items<'a>( @@ -142,7 +144,8 @@ fn find_items<'a>( local_results.push(match local_candidate.def { hir::ModuleDef::Macro(macro_def) => ItemInNs::Macros(macro_def), def => ItemInNs::from(def), - }) + }); + ControlFlow::<()>::Continue(()) }); local_results.into_iter().chain(external_importables) } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs index b3105e6524d..3a29232d331 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs @@ -260,23 +260,23 @@ impl From<hir::MacroKind> for SymbolKind { } } -impl From<hir::ModuleDefId> for SymbolKind { - fn from(it: hir::ModuleDefId) -> Self { +impl From<hir::ModuleDef> for SymbolKind { + fn from(it: hir::ModuleDef) -> Self { match it { - hir::ModuleDefId::ConstId(..) => SymbolKind::Const, - hir::ModuleDefId::EnumVariantId(..) => SymbolKind::Variant, - hir::ModuleDefId::FunctionId(..) => SymbolKind::Function, - hir::ModuleDefId::MacroId(hir::MacroId::ProcMacroId(..)) => SymbolKind::ProcMacro, - hir::ModuleDefId::MacroId(..) => SymbolKind::Macro, - hir::ModuleDefId::ModuleId(..) => SymbolKind::Module, - hir::ModuleDefId::StaticId(..) => SymbolKind::Static, - hir::ModuleDefId::AdtId(hir::AdtId::StructId(..)) => SymbolKind::Struct, - hir::ModuleDefId::AdtId(hir::AdtId::EnumId(..)) => SymbolKind::Enum, - hir::ModuleDefId::AdtId(hir::AdtId::UnionId(..)) => SymbolKind::Union, - hir::ModuleDefId::TraitId(..) => SymbolKind::Trait, - hir::ModuleDefId::TraitAliasId(..) => SymbolKind::TraitAlias, - hir::ModuleDefId::TypeAliasId(..) => SymbolKind::TypeAlias, - hir::ModuleDefId::BuiltinType(..) => SymbolKind::TypeAlias, + hir::ModuleDef::Const(..) => SymbolKind::Const, + hir::ModuleDef::Variant(..) => SymbolKind::Variant, + hir::ModuleDef::Function(..) => SymbolKind::Function, + hir::ModuleDef::Macro(mac) if mac.is_proc_macro() => SymbolKind::ProcMacro, + hir::ModuleDef::Macro(..) => SymbolKind::Macro, + hir::ModuleDef::Module(..) => SymbolKind::Module, + hir::ModuleDef::Static(..) => SymbolKind::Static, + hir::ModuleDef::Adt(hir::Adt::Struct(..)) => SymbolKind::Struct, + hir::ModuleDef::Adt(hir::Adt::Enum(..)) => SymbolKind::Enum, + hir::ModuleDef::Adt(hir::Adt::Union(..)) => SymbolKind::Union, + hir::ModuleDef::Trait(..) => SymbolKind::Trait, + hir::ModuleDef::TraitAlias(..) => SymbolKind::TraitAlias, + hir::ModuleDef::TypeAlias(..) => SymbolKind::TypeAlias, + hir::ModuleDef::BuiltinType(..) => SymbolKind::TypeAlias, } } } diff --git a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs index 1d1679c3ff8..42efbd68e33 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/rename.rs @@ -134,6 +134,7 @@ impl Definition { FieldSource::Pos(_) => None, } } + Definition::Crate(_) => None, Definition::Module(module) => { let src = module.declaration_source(sema.db)?; let name = src.value.name()?; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs index 68199dd8711..a75aba137be 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs @@ -953,14 +953,19 @@ impl<'a> FindUsages<'a> { // Search for occurrences of the items name for offset in Self::match_indices(&text, finder, search_range) { - tree.token_at_offset(offset).for_each(|token| { - let Some(str_token) = ast::String::cast(token.clone()) else { return }; + let ret = tree.token_at_offset(offset).any(|token| { + let Some(str_token) = ast::String::cast(token.clone()) else { return false }; if let Some((range, Some(nameres))) = sema.check_for_format_args_template(token, offset) { - if self.found_format_args_ref(file_id, range, str_token, nameres, sink) {} + return self + .found_format_args_ref(file_id, range, str_token, nameres, sink); } + false }); + if ret { + return; + } for name in Self::find_nodes(sema, name, &tree, offset).filter_map(ast::NameLike::cast) diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs index 94d354d28e5..c94644eeb89 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs @@ -25,6 +25,7 @@ use std::{ fmt, hash::{Hash, Hasher}, mem, + ops::ControlFlow, }; use base_db::{ @@ -136,16 +137,13 @@ fn library_symbols(db: &dyn SymbolsDatabase, source_root_id: SourceRootId) -> Ar // the module or crate indices for those in salsa unless we need to. .for_each(|module| symbol_collector.collect(module)); - let mut symbols = symbol_collector.finish(); - symbols.shrink_to_fit(); - Arc::new(SymbolIndex::new(symbols)) + Arc::new(SymbolIndex::new(symbol_collector.finish())) } fn module_symbols(db: &dyn SymbolsDatabase, module: Module) -> Arc<SymbolIndex> { let _p = tracing::info_span!("module_symbols").entered(); - let symbols = SymbolCollector::collect_module(db.upcast(), module); - Arc::new(SymbolIndex::new(symbols)) + Arc::new(SymbolIndex::new(SymbolCollector::collect_module(db.upcast(), module))) } pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolIndex>]> { @@ -222,13 +220,16 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> { }; let mut res = vec![]; - query.search(&indices, |f| res.push(f.clone())); + query.search::<()>(&indices, |f| { + res.push(f.clone()); + ControlFlow::Continue(()) + }); res } #[derive(Default)] pub struct SymbolIndex { - symbols: Vec<FileSymbol>, + symbols: Box<[FileSymbol]>, map: fst::Map<Vec<u8>>, } @@ -253,10 +254,10 @@ impl Hash for SymbolIndex { } impl SymbolIndex { - fn new(mut symbols: Vec<FileSymbol>) -> SymbolIndex { + fn new(mut symbols: Box<[FileSymbol]>) -> SymbolIndex { fn cmp(lhs: &FileSymbol, rhs: &FileSymbol) -> Ordering { - let lhs_chars = lhs.name.chars().map(|c| c.to_ascii_lowercase()); - let rhs_chars = rhs.name.chars().map(|c| c.to_ascii_lowercase()); + let lhs_chars = lhs.name.as_str().chars().map(|c| c.to_ascii_lowercase()); + let rhs_chars = rhs.name.as_str().chars().map(|c| c.to_ascii_lowercase()); lhs_chars.cmp(rhs_chars) } @@ -316,11 +317,11 @@ impl SymbolIndex { } impl Query { - pub(crate) fn search<'sym>( + pub(crate) fn search<'sym, T>( self, indices: &'sym [Arc<SymbolIndex>], - cb: impl FnMut(&'sym FileSymbol), - ) { + cb: impl FnMut(&'sym FileSymbol) -> ControlFlow<T>, + ) -> Option<T> { let _p = tracing::info_span!("symbol_index::Query::search").entered(); let mut op = fst::map::OpBuilder::new(); match self.mode { @@ -351,12 +352,12 @@ impl Query { } } - fn search_maps<'sym>( + fn search_maps<'sym, T>( &self, indices: &'sym [Arc<SymbolIndex>], mut stream: fst::map::Union<'_>, - mut cb: impl FnMut(&'sym FileSymbol), - ) { + mut cb: impl FnMut(&'sym FileSymbol) -> ControlFlow<T>, + ) -> Option<T> { let ignore_underscore_prefixed = !self.query.starts_with("__"); while let Some((_, indexed_values)) = stream.next() { for &IndexedValue { index, value } in indexed_values { @@ -377,15 +378,19 @@ impl Query { continue; } // Hide symbols that start with `__` unless the query starts with `__` - if ignore_underscore_prefixed && symbol.name.starts_with("__") { + let symbol_name = symbol.name.as_str(); + if ignore_underscore_prefixed && symbol_name.starts_with("__") { continue; } - if self.mode.check(&self.query, self.case_sensitive, &symbol.name) { - cb(symbol); + if self.mode.check(&self.query, self.case_sensitive, symbol_name) { + if let Some(b) = cb(symbol).break_value() { + return Some(b); + } } } } } + None } fn matches_assoc_mode(&self, is_trait_assoc_item: bool) -> bool { @@ -476,9 +481,9 @@ use Macro as ItemLikeMacro; use Macro as Trait; // overlay namespaces //- /b_mod.rs struct StructInModB; -use super::Macro as SuperItemLikeMacro; -use crate::b_mod::StructInModB as ThisStruct; -use crate::Trait as IsThisJustATrait; +pub(self) use super::Macro as SuperItemLikeMacro; +pub(self) use crate::b_mod::StructInModB as ThisStruct; +pub(self) use crate::Trait as IsThisJustATrait; "#, ); @@ -487,7 +492,7 @@ use crate::Trait as IsThisJustATrait; .into_iter() .map(|module_id| { let mut symbols = SymbolCollector::collect_module(&db, module_id); - symbols.sort_by_key(|it| it.name.clone()); + symbols.sort_by_key(|it| it.name.as_str().to_owned()); (module_id, symbols) }) .collect(); @@ -514,7 +519,7 @@ struct Duplicate; .into_iter() .map(|module_id| { let mut symbols = SymbolCollector::collect_module(&db, module_id); - symbols.sort_by_key(|it| it.name.clone()); + symbols.sort_by_key(|it| it.name.as_str().to_owned()); (module_id, symbols) }) .collect(); diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs index 365d726d2a9..557c95f704b 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs @@ -421,7 +421,7 @@ mod tests { use super::*; #[track_caller] - fn check(ra_fixture: &str, expected: &str) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: &str) { let (db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture); let frange = FileRange { file_id, range: range_or_offset.into() }; diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt index 9d70942199c..535777dfcbe 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt +++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt @@ -631,7 +631,7 @@ def: Function( Function { id: FunctionId( - 3, + 2, ), }, ), @@ -664,7 +664,7 @@ def: Function( Function { id: FunctionId( - 2, + 1, ), }, ), @@ -794,7 +794,7 @@ def: Function( Function { id: FunctionId( - 1, + 3, ), }, ), @@ -879,12 +879,10 @@ [ FileSymbol { name: "IsThisJustATrait", - def: Macro( - Macro { - id: Macro2Id( - Macro2Id( - 0, - ), + def: Trait( + Trait { + id: TraitId( + 0, ), }, ), @@ -897,12 +895,12 @@ ), ptr: SyntaxNodePtr { kind: USE_TREE, - range: 111..143, + range: 141..173, }, name_ptr: AstPtr( SyntaxNodePtr { kind: NAME, - range: 127..143, + range: 157..173, }, ), }, @@ -911,40 +909,7 @@ is_assoc: false, }, FileSymbol { - name: "StructInModB", - def: Adt( - Struct( - Struct { - id: StructId( - 4, - ), - }, - ), - ), - loc: DeclarationLocation { - hir_file_id: EditionedFileId( - FileId( - 1, - ), - Edition2021, - ), - ptr: SyntaxNodePtr { - kind: STRUCT, - range: 0..20, - }, - name_ptr: AstPtr( - SyntaxNodePtr { - kind: NAME, - range: 7..19, - }, - ), - }, - container_name: None, - is_alias: false, - is_assoc: false, - }, - FileSymbol { - name: "SuperItemLikeMacro", + name: "IsThisJustATrait", def: Macro( Macro { id: Macro2Id( @@ -963,12 +928,12 @@ ), ptr: SyntaxNodePtr { kind: USE_TREE, - range: 25..59, + range: 141..173, }, name_ptr: AstPtr( SyntaxNodePtr { kind: NAME, - range: 41..59, + range: 157..173, }, ), }, @@ -977,7 +942,7 @@ is_assoc: false, }, FileSymbol { - name: "ThisStruct", + name: "StructInModB", def: Adt( Struct( Struct { @@ -995,13 +960,13 @@ Edition2021, ), ptr: SyntaxNodePtr { - kind: USE_TREE, - range: 65..105, + kind: STRUCT, + range: 0..20, }, name_ptr: AstPtr( SyntaxNodePtr { kind: NAME, - range: 95..105, + range: 7..19, }, ), }, @@ -1010,15 +975,15 @@ is_assoc: false, }, FileSymbol { - name: "ThisStruct", - def: Adt( - Struct( - Struct { - id: StructId( - 4, + name: "SuperItemLikeMacro", + def: Macro( + Macro { + id: Macro2Id( + Macro2Id( + 0, ), - }, - ), + ), + }, ), loc: DeclarationLocation { hir_file_id: EditionedFileId( @@ -1029,12 +994,12 @@ ), ptr: SyntaxNodePtr { kind: USE_TREE, - range: 65..105, + range: 35..69, }, name_ptr: AstPtr( SyntaxNodePtr { kind: NAME, - range: 95..105, + range: 51..69, }, ), }, diff --git a/src/tools/rust-analyzer/crates/ide-db/src/traits.rs b/src/tools/rust-analyzer/crates/ide-db/src/traits.rs index 82aca50d039..0f67496d098 100644 --- a/src/tools/rust-analyzer/crates/ide-db/src/traits.rs +++ b/src/tools/rust-analyzer/crates/ide-db/src/traits.rs @@ -123,7 +123,9 @@ mod tests { use crate::RootDatabase; /// Creates analysis from a multi-file fixture, returns positions marked with $0. - pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { + pub(crate) fn position( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + ) -> (RootDatabase, FilePosition) { let change_fixture = ChangeFixture::parse(ra_fixture); let mut database = RootDatabase::default(); database.apply_change(change_fixture.change); @@ -133,7 +135,7 @@ mod tests { (database, FilePosition { file_id, offset }) } - fn check_trait(ra_fixture: &str, expect: Expect) { + fn check_trait(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (db, position) = position(ra_fixture); let sema = Semantics::new(&db); let file = sema.parse(position.file_id); @@ -147,7 +149,7 @@ mod tests { expect.assert_eq(&actual); } - fn check_missing_assoc(ra_fixture: &str, expect: Expect) { + fn check_missing_assoc(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (db, position) = position(ra_fixture); let sema = Semantics::new(&db); let file = sema.parse(position.file_id); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs index 2b59c1a22f6..7d62daf716c 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs @@ -604,4 +604,23 @@ fn bar() { "#, ); } + + #[test] + fn enum_variant_type_ns() { + check_diagnostics( + r#" +enum KvnDeserializerErr<I> { + UnexpectedKeyword { found: I, expected: I }, +} + +fn foo() { + let _x: KvnDeserializerErr<()> = + KvnDeserializerErr::<()>::UnexpectedKeyword { found: (), expected: () }; + let _x: KvnDeserializerErr<()> = + KvnDeserializerErr::<()>::UnexpectedKeyword::<()> { found: (), expected: () }; + // ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both +} + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs index 4c0c685e550..96a368eb0ea 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs @@ -41,7 +41,7 @@ pub(crate) fn inactive_code( mod tests { use crate::{tests::check_diagnostics_with_config, DiagnosticsConfig}; - pub(crate) fn check(ra_fixture: &str) { + pub(crate) fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let config = DiagnosticsConfig { disabled: std::iter::once("unlinked-file".to_owned()).collect(), ..DiagnosticsConfig::test_sample() diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs index e177b72e4d4..99894fefef3 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs @@ -4,13 +4,13 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext, Severity}; // // This diagnostic is shown for macro expansion errors. -// Diagnostic: proc-macros-disabled +// Diagnostic: attribute-expansion-disabled // -// This diagnostic is shown for proc macros where proc macros have been disabled. +// This diagnostic is shown for attribute proc macros when attribute expansions have been disabled. // Diagnostic: proc-macro-disabled // -// This diagnostic is shown for proc macros that has been specifically disabled via `rust-analyzer.procMacro.ignored`. +// This diagnostic is shown for proc macros that have been specifically disabled via `rust-analyzer.procMacro.ignored`. pub(crate) fn macro_error(ctx: &DiagnosticsContext<'_>, d: &hir::MacroError) -> Diagnostic { // Use more accurate position if available. let display_range = ctx.resolve_precise_location(&d.node, d.precise_location); @@ -291,4 +291,30 @@ mod prim_never {} "#, ); } + + #[test] + fn no_stack_overflow_for_missing_binding() { + check_diagnostics( + r#" +#[macro_export] +macro_rules! boom { + ( + $($code:literal),+, + $(param: $param:expr,)? + ) => {{ + let _ = $crate::boom!(@param $($param)*); + }}; + (@param) => { () }; + (@param $param:expr) => { $param }; +} + +fn it_works() { + // NOTE: there is an error, but RA crashes before showing it + boom!("RAND", param: c7.clone()); + // ^^^^^ error: expected literal +} + + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs index 08e6e7dced9..0bf600e5dfa 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs @@ -26,7 +26,7 @@ mod tests { use test_utils::skip_slow_tests; #[track_caller] - fn check_diagnostics_no_bails(ra_fixture: &str) { + fn check_diagnostics_no_bails(#[rust_analyzer::rust_fixture] ra_fixture: &str) { cov_mark::check_count!(validate_match_bailed_out, 0); crate::tests::check_diagnostics(ra_fixture) } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs index e5d871975b6..0f126a1a656 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/no_such_field.rs @@ -399,4 +399,38 @@ fn f(s@m::Struct { "#, ) } + + #[test] + fn editions_between_macros() { + check_diagnostics( + r#" +//- /edition2015.rs crate:edition2015 edition:2015 +#[macro_export] +macro_rules! pass_expr_thorough { + ($e:expr) => { $e }; +} + +//- /edition2018.rs crate:edition2018 deps:edition2015 edition:2018 +async fn bar() {} +async fn foo() { + edition2015::pass_expr_thorough!(bar().await); +} + "#, + ); + check_diagnostics( + r#" +//- /edition2018.rs crate:edition2018 edition:2018 +pub async fn bar() {} +#[macro_export] +macro_rules! make_await { + () => { async { $crate::bar().await }; }; +} + +//- /edition2015.rs crate:edition2015 deps:edition2018 edition:2015 +fn foo() { + edition2018::make_await!(); +} + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs index f481365f2a5..4aff446de60 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/replace_filter_map_next_with_find_map.rs @@ -61,7 +61,7 @@ mod tests { }; #[track_caller] - pub(crate) fn check_diagnostics(ra_fixture: &str) { + pub(crate) fn check_diagnostics(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let mut config = DiagnosticsConfig::test_sample(); config.disabled.insert("inactive-code".to_owned()); config.disabled.insert("E0599".to_owned()); diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs index bfdda537405..56afb38cc81 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs @@ -1164,6 +1164,37 @@ struct Bar { } #[test] + fn trait_upcast_ok() { + check_diagnostics( + r#" +//- minicore: coerce_unsized +trait A: B {} +trait B {} + +fn test(a: &dyn A) -> &dyn B { + a +} +"#, + ); + } + + #[test] + fn trait_upcast_err() { + check_diagnostics( + r#" +//- minicore: coerce_unsized +trait A {} // `A` does not have `B` as a supertrait, so no upcast :c +trait B {} + +fn test(a: &dyn A) -> &dyn B { + a + //^ error: expected &dyn B, found &dyn A +} +"#, + ); + } + + #[test] fn return_no_value() { check_diagnostics_with_disabled( r#" diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs index ec74640a54d..fc2a7db7174 100644 --- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs @@ -1,5 +1,7 @@ #![allow(clippy::print_stderr)] +mod overly_long_real_world_cases; + use ide_db::{ assists::AssistResolveStrategy, base_db::SourceDatabase, LineIndexDatabase, RootDatabase, }; @@ -16,7 +18,10 @@ use crate::{DiagnosticsConfig, ExprFillDefaultMode, Severity}; /// * the first diagnostic fix trigger range touches the input cursor position /// * that the contents of the file containing the cursor match `after` after the diagnostic fix is applied #[track_caller] -pub(crate) fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { +pub(crate) fn check_fix( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { check_nth_fix(0, ra_fixture_before, ra_fixture_after); } /// Takes a multi-file input fixture with annotated cursor positions, @@ -24,14 +29,21 @@ pub(crate) fn check_fix(ra_fixture_before: &str, ra_fixture_after: &str) { /// * a diagnostic is produced /// * every diagnostic fixes trigger range touches the input cursor position /// * that the contents of the file containing the cursor match `after` after each diagnostic fix is applied -pub(crate) fn check_fixes(ra_fixture_before: &str, ra_fixtures_after: Vec<&str>) { +pub(crate) fn check_fixes( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + ra_fixtures_after: Vec<&str>, +) { for (i, ra_fixture_after) in ra_fixtures_after.iter().enumerate() { check_nth_fix(i, ra_fixture_before, ra_fixture_after) } } #[track_caller] -fn check_nth_fix(nth: usize, ra_fixture_before: &str, ra_fixture_after: &str) { +fn check_nth_fix( + nth: usize, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { let mut config = DiagnosticsConfig::test_sample(); config.expr_fill_default = ExprFillDefaultMode::Default; check_nth_fix_with_config(config, nth, ra_fixture_before, ra_fixture_after) @@ -39,8 +51,8 @@ fn check_nth_fix(nth: usize, ra_fixture_before: &str, ra_fixture_after: &str) { #[track_caller] pub(crate) fn check_fix_with_disabled( - ra_fixture_before: &str, - ra_fixture_after: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, disabled: impl Iterator<Item = String>, ) { let mut config = DiagnosticsConfig::test_sample(); @@ -53,8 +65,8 @@ pub(crate) fn check_fix_with_disabled( fn check_nth_fix_with_config( config: DiagnosticsConfig, nth: usize, - ra_fixture_before: &str, - ra_fixture_after: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, ) { let after = trim_indent(ra_fixture_after); @@ -93,14 +105,20 @@ fn check_nth_fix_with_config( assert_eq_text!(&after, &actual); } -pub(crate) fn check_fixes_unordered(ra_fixture_before: &str, ra_fixtures_after: Vec<&str>) { +pub(crate) fn check_fixes_unordered( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + ra_fixtures_after: Vec<&str>, +) { for ra_fixture_after in ra_fixtures_after.iter() { check_has_fix(ra_fixture_before, ra_fixture_after) } } #[track_caller] -pub(crate) fn check_has_fix(ra_fixture_before: &str, ra_fixture_after: &str) { +pub(crate) fn check_has_fix( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { let after = trim_indent(ra_fixture_after); let (db, file_position) = RootDatabase::with_position(ra_fixture_before); @@ -143,7 +161,10 @@ pub(crate) fn check_has_fix(ra_fixture_before: &str, ra_fixture_after: &str) { } #[track_caller] -pub(crate) fn check_has_single_fix(ra_fixture_before: &str, ra_fixture_after: &str) { +pub(crate) fn check_has_single_fix( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, +) { let after = trim_indent(ra_fixture_after); let (db, file_position) = RootDatabase::with_position(ra_fixture_before); @@ -189,7 +210,7 @@ pub(crate) fn check_has_single_fix(ra_fixture_before: &str, ra_fixture_after: &s } /// Checks that there's a diagnostic *without* fix at `$0`. -pub(crate) fn check_no_fix(ra_fixture: &str) { +pub(crate) fn check_no_fix(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (db, file_position) = RootDatabase::with_position(ra_fixture); let diagnostic = super::full_diagnostics( &db, @@ -203,21 +224,27 @@ pub(crate) fn check_no_fix(ra_fixture: &str) { } #[track_caller] -pub(crate) fn check_diagnostics(ra_fixture: &str) { +pub(crate) fn check_diagnostics(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let mut config = DiagnosticsConfig::test_sample(); config.disabled.insert("inactive-code".to_owned()); check_diagnostics_with_config(config, ra_fixture) } #[track_caller] -pub(crate) fn check_diagnostics_with_disabled(ra_fixture: &str, disabled: &[&str]) { +pub(crate) fn check_diagnostics_with_disabled( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + disabled: &[&str], +) { let mut config = DiagnosticsConfig::test_sample(); config.disabled.extend(disabled.iter().map(|&s| s.to_owned())); check_diagnostics_with_config(config, ra_fixture) } #[track_caller] -pub(crate) fn check_diagnostics_with_config(config: DiagnosticsConfig, ra_fixture: &str) { +pub(crate) fn check_diagnostics_with_config( + config: DiagnosticsConfig, + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) { let (db, files) = RootDatabase::with_many_files(ra_fixture); let mut annotations = files .iter() diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests/overly_long_real_world_cases.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests/overly_long_real_world_cases.rs new file mode 100644 index 00000000000..c6831d818aa --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests/overly_long_real_world_cases.rs @@ -0,0 +1,2726 @@ +//! Overly long excerpts of failures from real world cases, that I was too lazy to minimize. + +use crate::tests::check_diagnostics_with_disabled; + +#[test] +fn tracing_infinite_repeat() { + check_diagnostics_with_disabled( + r#" +//- /core.rs crate:core +#[rustc_builtin_macro] +#[macro_export] +macro_rules! concat { +($($e:expr),* $(,)?) => {{ /* compiler built-in */ }}; +} +#[rustc_builtin_macro] +#[macro_export] +macro_rules! file { +() => { + /* compiler built-in */ +}; +} +#[allow_internal_unsafe] +#[allow_internal_unstable(fmt_internals)] +#[rustc_builtin_macro] +#[macro_export] +macro_rules! format_args { +($fmt:expr) => {{ /* compiler built-in */ }}; +($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; +} +#[rustc_builtin_macro] +#[macro_export] +macro_rules! line { +() => { + /* compiler built-in */ +}; +} + +//- /tracing_core.rs crate:tracing_core deps:core +#[macro_export] +macro_rules! identify_callsite { +($callsite:expr) => { + $crate::callsite::Identifier($callsite) +}; +} + +#[macro_export] +macro_rules! metadata { +( + name: $name:expr, + target: $target:expr, + level: $level:expr, + fields: $fields:expr, + callsite: $callsite:expr, + kind: $kind:expr +) => { + $crate::metadata! { + name: $name, + target: $target, + level: $level, + fields: $fields, + callsite: $callsite, + kind: $kind, + } +}; +( + name: $name:expr, + target: $target:expr, + level: $level:expr, + fields: $fields:expr, + callsite: $callsite:expr, + kind: $kind:expr, +) => { + $crate::metadata::Metadata::new( + $name, + $target, + $level, + $crate::__macro_support::Option::Some($crate::__macro_support::file!()), + $crate::__macro_support::Option::Some($crate::__macro_support::line!()), + $crate::__macro_support::Option::Some($crate::__macro_support::module_path!()), + $crate::field::FieldSet::new($fields, $crate::identify_callsite!($callsite)), + $kind, + ) +}; +} + +//- /tracing.rs crate:tracing deps:core,tracing_core +#[doc(hidden)] +pub mod __macro_support { +// Re-export the `core` functions that are used in macros. This allows +// a crate to be named `core` and avoid name clashes. +// See here: https://github.com/tokio-rs/tracing/issues/2761 +pub use core::{concat, file, format_args, iter::Iterator, line, option::Option}; +} + +#[macro_export] +macro_rules! span { +(target: $target:expr, parent: $parent:expr, $lvl:expr, $name:expr) => { + $crate::span!(target: $target, parent: $parent, $lvl, $name,) +}; +(target: $target:expr, parent: $parent:expr, $lvl:expr, $name:expr, $($fields:tt)*) => { + { + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + name: $name, + kind: $crate::metadata::Kind::SPAN, + target: $target, + level: $lvl, + fields: $($fields)* + }; + let mut interest = $crate::subscriber::Interest::never(); + if $crate::level_enabled!($lvl) + && { interest = __CALLSITE.interest(); !interest.is_never() } + && $crate::__macro_support::__is_enabled(__CALLSITE.metadata(), interest) + { + let meta = __CALLSITE.metadata(); + // span with explicit parent + $crate::Span::child_of( + $parent, + meta, + &$crate::valueset!(meta.fields(), $($fields)*), + ) + } else { + let span = $crate::__macro_support::__disabled_span(__CALLSITE.metadata()); + $crate::if_log_enabled! { $lvl, { + span.record_all(&$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + }}; + span + } + } +}; +(target: $target:expr, $lvl:expr, $name:expr, $($fields:tt)*) => { + { + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! { + name: $name, + kind: $crate::metadata::Kind::SPAN, + target: $target, + level: $lvl, + fields: $($fields)* + }; + let mut interest = $crate::subscriber::Interest::never(); + if $crate::level_enabled!($lvl) + && { interest = __CALLSITE.interest(); !interest.is_never() } + && $crate::__macro_support::__is_enabled(__CALLSITE.metadata(), interest) + { + let meta = __CALLSITE.metadata(); + // span with contextual parent + $crate::Span::new( + meta, + &$crate::valueset!(meta.fields(), $($fields)*), + ) + } else { + let span = $crate::__macro_support::__disabled_span(__CALLSITE.metadata()); + $crate::if_log_enabled! { $lvl, { + span.record_all(&$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + }}; + span + } + } +}; +(target: $target:expr, parent: $parent:expr, $lvl:expr, $name:expr) => { + $crate::span!(target: $target, parent: $parent, $lvl, $name,) +}; +(parent: $parent:expr, $lvl:expr, $name:expr, $($fields:tt)*) => { + $crate::span!( + target: module_path!(), + parent: $parent, + $lvl, + $name, + $($fields)* + ) +}; +(parent: $parent:expr, $lvl:expr, $name:expr) => { + $crate::span!( + target: module_path!(), + parent: $parent, + $lvl, + $name, + ) +}; +(target: $target:expr, $lvl:expr, $name:expr, $($fields:tt)*) => { + $crate::span!( + target: $target, + $lvl, + $name, + $($fields)* + ) +}; +(target: $target:expr, $lvl:expr, $name:expr) => { + $crate::span!(target: $target, $lvl, $name,) +}; +($lvl:expr, $name:expr, $($fields:tt)*) => { + $crate::span!( + target: module_path!(), + $lvl, + $name, + $($fields)* + ) +}; +($lvl:expr, $name:expr) => { + $crate::span!( + target: module_path!(), + $lvl, + $name, + ) +}; +} + +#[macro_export] +macro_rules! trace_span { +(target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + parent: $parent, + $crate::Level::TRACE, + $name, + $($field)* + ) +}; +(target: $target:expr, parent: $parent:expr, $name:expr) => { + $crate::trace_span!(target: $target, parent: $parent, $name,) +}; +(parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + $name, + $($field)* + ) +}; +(parent: $parent:expr, $name:expr) => { + $crate::trace_span!(parent: $parent, $name,) +}; +(target: $target:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + $crate::Level::TRACE, + $name, + $($field)* + ) +}; +(target: $target:expr, $name:expr) => { + $crate::trace_span!(target: $target, $name,) +}; +($name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + $crate::Level::TRACE, + $name, + $($field)* + ) +}; +($name:expr) => { $crate::trace_span!($name,) }; +} + +#[macro_export] +macro_rules! debug_span { +(target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + parent: $parent, + $crate::Level::DEBUG, + $name, + $($field)* + ) +}; +(target: $target:expr, parent: $parent:expr, $name:expr) => { + $crate::debug_span!(target: $target, parent: $parent, $name,) +}; +(parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + $name, + $($field)* + ) +}; +(parent: $parent:expr, $name:expr) => { + $crate::debug_span!(parent: $parent, $name,) +}; +(target: $target:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + $crate::Level::DEBUG, + $name, + $($field)* + ) +}; +(target: $target:expr, $name:expr) => { + $crate::debug_span!(target: $target, $name,) +}; +($name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + $crate::Level::DEBUG, + $name, + $($field)* + ) +}; +($name:expr) => {$crate::debug_span!($name,)}; +} + +#[macro_export] +macro_rules! info_span { +(target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + parent: $parent, + $crate::Level::INFO, + $name, + $($field)* + ) +}; +(target: $target:expr, parent: $parent:expr, $name:expr) => { + $crate::info_span!(target: $target, parent: $parent, $name,) +}; +(parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + $name, + $($field)* + ) +}; +(parent: $parent:expr, $name:expr) => { + $crate::info_span!(parent: $parent, $name,) +}; +(target: $target:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + $crate::Level::INFO, + $name, + $($field)* + ) +}; +(target: $target:expr, $name:expr) => { + $crate::info_span!(target: $target, $name,) +}; +($name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + $crate::Level::INFO, + $name, + $($field)* + ) +}; +($name:expr) => {$crate::info_span!($name,)}; +} + +#[macro_export] +macro_rules! warn_span { +(target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + parent: $parent, + $crate::Level::WARN, + $name, + $($field)* + ) +}; +(target: $target:expr, parent: $parent:expr, $name:expr) => { + $crate::warn_span!(target: $target, parent: $parent, $name,) +}; +(parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + $name, + $($field)* + ) +}; +(parent: $parent:expr, $name:expr) => { + $crate::warn_span!(parent: $parent, $name,) +}; +(target: $target:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + $crate::Level::WARN, + $name, + $($field)* + ) +}; +(target: $target:expr, $name:expr) => { + $crate::warn_span!(target: $target, $name,) +}; +($name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + $crate::Level::WARN, + $name, + $($field)* + ) +}; +($name:expr) => {$crate::warn_span!($name,)}; +} + +#[macro_export] +macro_rules! error_span { +(target: $target:expr, parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + parent: $parent, + $crate::Level::ERROR, + $name, + $($field)* + ) +}; +(target: $target:expr, parent: $parent:expr, $name:expr) => { + $crate::error_span!(target: $target, parent: $parent, $name,) +}; +(parent: $parent:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + $name, + $($field)* + ) +}; +(parent: $parent:expr, $name:expr) => { + $crate::error_span!(parent: $parent, $name,) +}; +(target: $target:expr, $name:expr, $($field:tt)*) => { + $crate::span!( + target: $target, + $crate::Level::ERROR, + $name, + $($field)* + ) +}; +(target: $target:expr, $name:expr) => { + $crate::error_span!(target: $target, $name,) +}; +($name:expr, $($field:tt)*) => { + $crate::span!( + target: module_path!(), + $crate::Level::ERROR, + $name, + $($field)* + ) +}; +($name:expr) => {$crate::error_span!($name,)}; +} + +#[macro_export] +macro_rules! event { +// Name / target / parent. +(name: $name:expr, target: $target:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + name: $name, + kind: $crate::metadata::Kind::EVENT, + target: $target, + level: $lvl, + fields: $($fields)* + }; + + let enabled = $crate::level_enabled!($lvl) && { + let interest = __CALLSITE.interest(); + !interest.is_never() && $crate::__macro_support::__is_enabled(__CALLSITE.metadata(), interest) + }; + if enabled { + (|value_set: $crate::field::ValueSet| { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &value_set + ); + let meta = __CALLSITE.metadata(); + // event with explicit parent + $crate::Event::child_of( + $parent, + meta, + &value_set + ); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + } else { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + ); + } +}); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + name: $name, + target: $target, + parent: $parent, + $lvl, + { message = $crate::__macro_support::format_args!($($arg)+), $($fields)* } + ) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $lvl:expr, $($k:ident).+ = $($fields:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $lvl, { $($k).+ = $($fields)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $lvl:expr, $($arg:tt)+) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $lvl, { $($arg)+ }) +); + +// Name / target. +(name: $name:expr, target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + name: $name, + kind: $crate::metadata::Kind::EVENT, + target: $target, + level: $lvl, + fields: $($fields)* + }; + let enabled = $crate::level_enabled!($lvl) && { + let interest = __CALLSITE.interest(); + !interest.is_never() && $crate::__macro_support::__is_enabled(__CALLSITE.metadata(), interest) + }; + if enabled { + (|value_set: $crate::field::ValueSet| { + let meta = __CALLSITE.metadata(); + // event with contextual parent + $crate::Event::dispatch( + meta, + &value_set + ); + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &value_set + ); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + } else { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + ); + } +}); +(name: $name:expr, target: $target:expr, $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + name: $name, + target: $target, + $lvl, + { message = $crate::__macro_support::format_args!($($arg)+), $($fields)* } + ) +); +(name: $name:expr, target: $target:expr, $lvl:expr, $($k:ident).+ = $($fields:tt)* ) => ( + $crate::event!(name: $name, target: $target, $lvl, { $($k).+ = $($fields)* }) +); +(name: $name:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ( + $crate::event!(name: $name, target: $target, $lvl, { $($arg)+ }) +); + +// Target / parent. +(target: $target:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! { + name: $crate::__macro_support::concat!( + "event ", + $crate::__macro_support::file!(), + ":", + $crate::__macro_support::line!() + ), + kind: $crate::metadata::Kind::EVENT, + target: $target, + level: $lvl, + fields: $($fields)* + }; + + let enabled = $crate::level_enabled!($lvl) && { + let interest = __CALLSITE.interest(); + !interest.is_never() && $crate::__macro_support::__is_enabled(__CALLSITE.metadata(), interest) + }; + if enabled { + (|value_set: $crate::field::ValueSet| { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &value_set + ); + let meta = __CALLSITE.metadata(); + // event with explicit parent + $crate::Event::child_of( + $parent, + meta, + &value_set + ); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + } else { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + ); + } +}); +(target: $target:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + target: $target, + parent: $parent, + $lvl, + { message = $crate::__macro_support::format_args!($($arg)+), $($fields)* } + ) +); +(target: $target:expr, parent: $parent:expr, $lvl:expr, $($k:ident).+ = $($fields:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $lvl, { $($k).+ = $($fields)* }) +); +(target: $target:expr, parent: $parent:expr, $lvl:expr, $($arg:tt)+) => ( + $crate::event!(target: $target, parent: $parent, $lvl, { $($arg)+ }) +); + +// Name / parent. +(name: $name:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + name: $name, + kind: $crate::metadata::Kind::EVENT, + target: module_path!(), + level: $lvl, + fields: $($fields)* + }; + + let enabled = $crate::level_enabled!($lvl) && { + let interest = __CALLSITE.interest(); + !interest.is_never() && __CALLSITE.is_enabled(interest) + }; + if enabled { + (|value_set: $crate::field::ValueSet| { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &value_set + ); + let meta = __CALLSITE.metadata(); + // event with explicit parent + $crate::Event::child_of( + $parent, + meta, + &value_set + ); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + } else { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + ); + } +}); +(name: $name:expr, parent: $parent:expr, $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + name: $name, + parent: $parent, + $lvl, + { message = $crate::__macro_support::format_args!($($arg)+), $($fields)* } + ) +); +(name: $name:expr, parent: $parent:expr, $lvl:expr, $($k:ident).+ = $($fields:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $lvl, { $($k).+ = $($fields)* }) +); +(name: $name:expr, parent: $parent:expr, $lvl:expr, $($arg:tt)+) => ( + $crate::event!(name: $name, parent: $parent, $lvl, { $($arg)+ }) +); + +// Name. +(name: $name:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::__macro_support::MacroCallsite = $crate::callsite2! { + name: $name, + kind: $crate::metadata::Kind::EVENT, + target: module_path!(), + level: $lvl, + fields: $($fields)* + }; + let enabled = $crate::level_enabled!($lvl) && { + let interest = __CALLSITE.interest(); + !interest.is_never() && $crate::__macro_support::__is_enabled(__CALLSITE.metadata(), interest) + }; + if enabled { + (|value_set: $crate::field::ValueSet| { + let meta = __CALLSITE.metadata(); + // event with contextual parent + $crate::Event::dispatch( + meta, + &value_set + ); + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &value_set + ); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + } else { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + ); + } +}); +(name: $name:expr, $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + name: $name, + $lvl, + { message = $crate::__macro_support::format_args!($($arg)+), $($fields)* } + ) +); +(name: $name:expr, $lvl:expr, $($k:ident).+ = $($fields:tt)* ) => ( + $crate::event!(name: $name, $lvl, { $($k).+ = $($fields)* }) +); +(name: $name:expr, $lvl:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, $lvl, { $($arg)+ }) +); + +// Target. +(target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! { + name: $crate::__macro_support::concat!( + "event ", + $crate::__macro_support::file!(), + ":", + $crate::__macro_support::line!() + ), + kind: $crate::metadata::Kind::EVENT, + target: $target, + level: $lvl, + fields: $($fields)* + }; + let enabled = $crate::level_enabled!($lvl) && { + let interest = __CALLSITE.interest(); + !interest.is_never() && $crate::__macro_support::__is_enabled(__CALLSITE.metadata(), interest) + }; + if enabled { + (|value_set: $crate::field::ValueSet| { + let meta = __CALLSITE.metadata(); + // event with contextual parent + $crate::Event::dispatch( + meta, + &value_set + ); + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &value_set + ); + })($crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*)); + } else { + $crate::__tracing_log!( + $lvl, + __CALLSITE, + &$crate::valueset!(__CALLSITE.metadata().fields(), $($fields)*) + ); + } +}); +(target: $target:expr, $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + target: $target, + $lvl, + { message = $crate::__macro_support::format_args!($($arg)+), $($fields)* } + ) +); +(target: $target:expr, $lvl:expr, $($k:ident).+ = $($fields:tt)* ) => ( + $crate::event!(target: $target, $lvl, { $($k).+ = $($fields)* }) +); +(target: $target:expr, $lvl:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, $lvl, { $($arg)+ }) +); + +// Parent. +(parent: $parent:expr, $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $lvl, + { message = $crate::__macro_support::format_args!($($arg)+), $($fields)* } + ) +); +(parent: $parent:expr, $lvl:expr, $($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $lvl, + { $($k).+ = $($field)*} + ) +); +(parent: $parent:expr, $lvl:expr, ?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $lvl, + { ?$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, $lvl:expr, %$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $lvl, + { %$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, $lvl:expr, $($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $lvl, + { $($k).+, $($field)*} + ) +); +(parent: $parent:expr, $lvl:expr, %$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $lvl, + { %$($k).+, $($field)*} + ) +); +(parent: $parent:expr, $lvl:expr, ?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $lvl, + { ?$($k).+, $($field)*} + ) +); +(parent: $parent:expr, $lvl:expr, $($arg:tt)+ ) => ( + $crate::event!(target: module_path!(), parent: $parent, $lvl, { $($arg)+ }) +); + +// ... +( $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + $lvl, + { message = $crate::__macro_support::format_args!($($arg)+), $($fields)* } + ) +); +( $lvl:expr, { $($fields:tt)* }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + $lvl, + { message = format_args!($($arg)+), $($fields)* } + ) +); +($lvl:expr, $($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $lvl, + { $($k).+ = $($field)*} + ) +); +($lvl:expr, $($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $lvl, + { $($k).+, $($field)*} + ) +); +($lvl:expr, ?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $lvl, + { ?$($k).+, $($field)*} + ) +); +($lvl:expr, %$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $lvl, + { %$($k).+, $($field)*} + ) +); +($lvl:expr, ?$($k:ident).+) => ( + $crate::event!($lvl, ?$($k).+,) +); +($lvl:expr, %$($k:ident).+) => ( + $crate::event!($lvl, %$($k).+,) +); +($lvl:expr, $($k:ident).+) => ( + $crate::event!($lvl, $($k).+,) +); +( $lvl:expr, $($arg:tt)+ ) => ( + $crate::event!(target: module_path!(), $lvl, { $($arg)+ }) +); +} + +#[macro_export] +macro_rules! event_enabled { +($($rest:tt)*)=> ( + $crate::enabled!(kind: $crate::metadata::Kind::EVENT, $($rest)*) +) +} + +#[macro_export] +macro_rules! span_enabled { +($($rest:tt)*)=> ( + $crate::enabled!(kind: $crate::metadata::Kind::SPAN, $($rest)*) +) +} + +#[macro_export] +macro_rules! enabled { +(kind: $kind:expr, target: $target:expr, $lvl:expr, { $($fields:tt)* } )=> ({ + if $crate::level_enabled!($lvl) { + use $crate::__macro_support::Callsite as _; + static __CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite2! { + name: $crate::__macro_support::concat!( + "enabled ", + $crate::__macro_support::file!(), + ":", + $crate::__macro_support::line!() + ), + kind: $kind.hint(), + target: $target, + level: $lvl, + fields: $($fields)* + }; + let interest = __CALLSITE.interest(); + if !interest.is_never() && $crate::__macro_support::__is_enabled(__CALLSITE.metadata(), interest) { + let meta = __CALLSITE.metadata(); + $crate::dispatcher::get_default(|current| current.enabled(meta)) + } else { + false + } + } else { + false + } +}); +// Just target and level +(kind: $kind:expr, target: $target:expr, $lvl:expr ) => ( + $crate::enabled!(kind: $kind, target: $target, $lvl, { }) +); +(target: $target:expr, $lvl:expr ) => ( + $crate::enabled!(kind: $crate::metadata::Kind::HINT, target: $target, $lvl, { }) +); + +// These four cases handle fields with no values +(kind: $kind:expr, target: $target:expr, $lvl:expr, $($field:tt)*) => ( + $crate::enabled!( + kind: $kind, + target: $target, + $lvl, + { $($field)*} + ) +); +(target: $target:expr, $lvl:expr, $($field:tt)*) => ( + $crate::enabled!( + kind: $crate::metadata::Kind::HINT, + target: $target, + $lvl, + { $($field)*} + ) +); + +// Level and field case +(kind: $kind:expr, $lvl:expr, $($field:tt)*) => ( + $crate::enabled!( + kind: $kind, + target: module_path!(), + $lvl, + { $($field)*} + ) +); + +// Simplest `enabled!` case +(kind: $kind:expr, $lvl:expr) => ( + $crate::enabled!(kind: $kind, target: module_path!(), $lvl, { }) +); +($lvl:expr) => ( + $crate::enabled!(kind: $crate::metadata::Kind::HINT, target: module_path!(), $lvl, { }) +); + +// Fallthrough from above +($lvl:expr, $($field:tt)*) => ( + $crate::enabled!( + kind: $crate::metadata::Kind::HINT, + target: module_path!(), + $lvl, + { $($field)*} + ) +); +} + +#[macro_export] +macro_rules! trace { +// Name / target / parent. +(name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::TRACE, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::TRACE, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::TRACE, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::TRACE, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::TRACE, {}, $($arg)+) +); + +// Name / target. +(name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::TRACE, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::TRACE, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::TRACE, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::TRACE, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::TRACE, {}, $($arg)+) +); + +// Target / parent. +(target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::TRACE, { $($field)* }, $($arg)*) +); +(target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::TRACE, { $($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::TRACE, { ?$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::TRACE, { %$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::TRACE, {}, $($arg)+) +); + +// Name / parent. +(name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::TRACE, { $($field)* }, $($arg)*) +); +(name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::TRACE, { $($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::TRACE, { ?$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::TRACE, { %$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::TRACE, {}, $($arg)+) +); + +// Name. +(name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::TRACE, { $($field)* }, $($arg)*) +); +(name: $name:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::TRACE, { $($k).+ $($field)* }) +); +(name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::TRACE, { ?$($k).+ $($field)* }) +); +(name: $name:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::TRACE, { %$($k).+ $($field)* }) +); +(name: $name:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, $crate::Level::TRACE, {}, $($arg)+) +); + +// Target. +(target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::TRACE, { $($field)* }, $($arg)*) +); +(target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::TRACE, { $($k).+ $($field)* }) +); +(target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::TRACE, { ?$($k).+ $($field)* }) +); +(target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::TRACE, { %$($k).+ $($field)* }) +); +(target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, $crate::Level::TRACE, {}, $($arg)+) +); + +// Parent. +(parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + { $($field)+ }, + $($arg)+ + ) +); +(parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + { $($k).+ = $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + { ?$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + { %$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + { $($k).+, $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + { ?$($k).+, $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + { %$($k).+, $($field)*} + ) +); +(parent: $parent:expr, $($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::TRACE, + {}, + $($arg)+ + ) +); + +// ... +({ $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { $($field)+ }, + $($arg)+ + ) +); +($($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { $($k).+ = $($field)*} + ) +); +(?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { ?$($k).+ = $($field)*} + ) +); +(%$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { %$($k).+ = $($field)*} + ) +); +($($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { $($k).+, $($field)*} + ) +); +(?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { ?$($k).+, $($field)*} + ) +); +(%$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { %$($k).+, $($field)*} + ) +); +(?$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { ?$($k).+ } + ) +); +(%$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { %$($k).+ } + ) +); +($($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + { $($k).+ } + ) +); +($($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::TRACE, + $($arg)+ + ) +); +} + +#[macro_export] +macro_rules! debug { +// Name / target / parent. +(name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::DEBUG, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::DEBUG, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::DEBUG, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::DEBUG, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::DEBUG, {}, $($arg)+) +); + +// Name / target. +(name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::DEBUG, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::DEBUG, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::DEBUG, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::DEBUG, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::DEBUG, {}, $($arg)+) +); + +// Target / parent. +(target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::DEBUG, { $($field)* }, $($arg)*) +); +(target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::DEBUG, { $($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::DEBUG, { ?$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::DEBUG, { %$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::DEBUG, {}, $($arg)+) +); + +// Name / parent. +(name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::DEBUG, { $($field)* }, $($arg)*) +); +(name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::DEBUG, { $($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::DEBUG, { ?$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::DEBUG, { %$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::DEBUG, {}, $($arg)+) +); + +// Name. +(name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::DEBUG, { $($field)* }, $($arg)*) +); +(name: $name:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::DEBUG, { $($k).+ $($field)* }) +); +(name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::DEBUG, { ?$($k).+ $($field)* }) +); +(name: $name:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::DEBUG, { %$($k).+ $($field)* }) +); +(name: $name:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, $crate::Level::DEBUG, {}, $($arg)+) +); + +// Target. +(target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::DEBUG, { $($field)* }, $($arg)*) +); +(target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::DEBUG, { $($k).+ $($field)* }) +); +(target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::DEBUG, { ?$($k).+ $($field)* }) +); +(target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::DEBUG, { %$($k).+ $($field)* }) +); +(target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, $crate::Level::DEBUG, {}, $($arg)+) +); + +// Parent. +(parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + { $($field)+ }, + $($arg)+ + ) +); +(parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + { $($k).+ = $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + { ?$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + { %$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + { $($k).+, $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + { ?$($k).+, $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + { %$($k).+, $($field)*} + ) +); +(parent: $parent:expr, $($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::DEBUG, + {}, + $($arg)+ + ) +); + +// ... +({ $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { $($field)+ }, + $($arg)+ + ) +); +($($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { $($k).+ = $($field)*} + ) +); +(?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { ?$($k).+ = $($field)*} + ) +); +(%$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { %$($k).+ = $($field)*} + ) +); +($($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { $($k).+, $($field)*} + ) +); +(?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { ?$($k).+, $($field)*} + ) +); +(%$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { %$($k).+, $($field)*} + ) +); +(?$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { ?$($k).+ } + ) +); +(%$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { %$($k).+ } + ) +); +($($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + { $($k).+ } + ) +); +($($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::DEBUG, + $($arg)+ + ) +); +} + +#[macro_export] +macro_rules! info { +// Name / target / parent. +(name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::INFO, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::INFO, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::INFO, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::INFO, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::INFO, {}, $($arg)+) +); + +// Name / target. +(name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::INFO, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::INFO, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::INFO, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::INFO, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::INFO, {}, $($arg)+) +); + +// Target / parent. +(target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::INFO, { $($field)* }, $($arg)*) +); +(target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::INFO, { $($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::INFO, { ?$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::INFO, { %$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::INFO, {}, $($arg)+) +); + +// Name / parent. +(name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::INFO, { $($field)* }, $($arg)*) +); +(name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::INFO, { $($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::INFO, { ?$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::INFO, { %$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::INFO, {}, $($arg)+) +); + +// Name. +(name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::INFO, { $($field)* }, $($arg)*) +); +(name: $name:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::INFO, { $($k).+ $($field)* }) +); +(name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::INFO, { ?$($k).+ $($field)* }) +); +(name: $name:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::INFO, { %$($k).+ $($field)* }) +); +(name: $name:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, $crate::Level::INFO, {}, $($arg)+) +); + +// Target. +(target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::INFO, { $($field)* }, $($arg)*) +); +(target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::INFO, { $($k).+ $($field)* }) +); +(target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::INFO, { ?$($k).+ $($field)* }) +); +(target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::INFO, { %$($k).+ $($field)* }) +); +(target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, $crate::Level::INFO, {}, $($arg)+) +); + +// Parent. +(parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + { $($field)+ }, + $($arg)+ + ) +); +(parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + { $($k).+ = $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + { ?$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + { %$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + { $($k).+, $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + { ?$($k).+, $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + { %$($k).+, $($field)*} + ) +); +(parent: $parent:expr, $($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::INFO, + {}, + $($arg)+ + ) +); + +// ... +({ $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { $($field)+ }, + $($arg)+ + ) +); +($($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { $($k).+ = $($field)*} + ) +); +(?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { ?$($k).+ = $($field)*} + ) +); +(%$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { %$($k).+ = $($field)*} + ) +); +($($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { $($k).+, $($field)*} + ) +); +(?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { ?$($k).+, $($field)*} + ) +); +(%$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { %$($k).+, $($field)*} + ) +); +(?$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { ?$($k).+ } + ) +); +(%$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { %$($k).+ } + ) +); +($($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + { $($k).+ } + ) +); +($($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::INFO, + $($arg)+ + ) +); +} + +#[macro_export] +macro_rules! warn { +// Name / target / parent. +(name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::WARN, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::WARN, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::WARN, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::WARN, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::WARN, {}, $($arg)+) +); + +// Name / target. +(name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::WARN, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::WARN, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::WARN, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::WARN, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::WARN, {}, $($arg)+) +); + +// Target / parent. +(target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::WARN, { $($field)* }, $($arg)*) +); +(target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::WARN, { $($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::WARN, { ?$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::WARN, { %$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::WARN, {}, $($arg)+) +); + +// Name / parent. +(name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::WARN, { $($field)* }, $($arg)*) +); +(name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::WARN, { $($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::WARN, { ?$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::WARN, { %$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::WARN, {}, $($arg)+) +); + +// Name. +(name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::WARN, { $($field)* }, $($arg)*) +); +(name: $name:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::WARN, { $($k).+ $($field)* }) +); +(name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::WARN, { ?$($k).+ $($field)* }) +); +(name: $name:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::WARN, { %$($k).+ $($field)* }) +); +(name: $name:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, $crate::Level::WARN, {}, $($arg)+) +); + +// Target. +(target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::WARN, { $($field)* }, $($arg)*) +); +(target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::WARN, { $($k).+ $($field)* }) +); +(target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::WARN, { ?$($k).+ $($field)* }) +); +(target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::WARN, { %$($k).+ $($field)* }) +); +(target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, $crate::Level::WARN, {}, $($arg)+) +); + +// Parent. +(parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + { $($field)+ }, + $($arg)+ + ) +); +(parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + { $($k).+ = $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + { ?$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + { %$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + { $($k).+, $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + { ?$($k).+, $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + { %$($k).+, $($field)*} + ) +); +(parent: $parent:expr, $($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::WARN, + {}, + $($arg)+ + ) +); + +// ... +({ $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { $($field)+ }, + $($arg)+ + ) +); +($($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { $($k).+ = $($field)*} + ) +); +(?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { ?$($k).+ = $($field)*} + ) +); +(%$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { %$($k).+ = $($field)*} + ) +); +($($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { $($k).+, $($field)*} + ) +); +(?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { ?$($k).+, $($field)*} + ) +); +(%$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { %$($k).+, $($field)*} + ) +); +(?$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { ?$($k).+ } + ) +); +(%$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { %$($k).+ } + ) +); +($($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + { $($k).+ } + ) +); +($($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::WARN, + $($arg)+ + ) +); +} + +#[macro_export] +macro_rules! error { +// Name / target / parent. +(name: $name:expr, target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::ERROR, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::ERROR, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::ERROR, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::ERROR, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, parent: $parent, $crate::Level::ERROR, {}, $($arg)+) +); + +// Name / target. +(name: $name:expr, target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::ERROR, { $($field)* }, $($arg)*) +); +(name: $name:expr, target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::ERROR, { $($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::ERROR, { ?$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::ERROR, { %$($k).+ $($field)* }) +); +(name: $name:expr, target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, target: $target, $crate::Level::ERROR, {}, $($arg)+) +); + +// Target / parent. +(target: $target:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::ERROR, { $($field)* }, $($arg)*) +); +(target: $target:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::ERROR, { $($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::ERROR, { ?$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::ERROR, { %$($k).+ $($field)* }) +); +(target: $target:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, parent: $parent, $crate::Level::ERROR, {}, $($arg)+) +); + +// Name / parent. +(name: $name:expr, parent: $parent:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::ERROR, { $($field)* }, $($arg)*) +); +(name: $name:expr, parent: $parent:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::ERROR, { $($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::ERROR, { ?$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::ERROR, { %$($k).+ $($field)* }) +); +(name: $name:expr, parent: $parent:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, parent: $parent, $crate::Level::ERROR, {}, $($arg)+) +); + +// Name. +(name: $name:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::ERROR, { $($field)* }, $($arg)*) +); +(name: $name:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::ERROR, { $($k).+ $($field)* }) +); +(name: $name:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::ERROR, { ?$($k).+ $($field)* }) +); +(name: $name:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(name: $name, $crate::Level::ERROR, { %$($k).+ $($field)* }) +); +(name: $name:expr, $($arg:tt)+ ) => ( + $crate::event!(name: $name, $crate::Level::ERROR, {}, $($arg)+) +); + +// Target. +(target: $target:expr, { $($field:tt)* }, $($arg:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::ERROR, { $($field)* }, $($arg)*) +); +(target: $target:expr, $($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::ERROR, { $($k).+ $($field)* }) +); +(target: $target:expr, ?$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::ERROR, { ?$($k).+ $($field)* }) +); +(target: $target:expr, %$($k:ident).+ $($field:tt)* ) => ( + $crate::event!(target: $target, $crate::Level::ERROR, { %$($k).+ $($field)* }) +); +(target: $target:expr, $($arg:tt)+ ) => ( + $crate::event!(target: $target, $crate::Level::ERROR, {}, $($arg)+) +); + +// Parent. +(parent: $parent:expr, { $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + { $($field)+ }, + $($arg)+ + ) +); +(parent: $parent:expr, $($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + { $($k).+ = $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + { ?$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + { %$($k).+ = $($field)*} + ) +); +(parent: $parent:expr, $($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + { $($k).+, $($field)*} + ) +); +(parent: $parent:expr, ?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + { ?$($k).+, $($field)*} + ) +); +(parent: $parent:expr, %$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + { %$($k).+, $($field)*} + ) +); +(parent: $parent:expr, $($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + parent: $parent, + $crate::Level::ERROR, + {}, + $($arg)+ + ) +); + +// ... +({ $($field:tt)+ }, $($arg:tt)+ ) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { $($field)+ }, + $($arg)+ + ) +); +($($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { $($k).+ = $($field)*} + ) +); +(?$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { ?$($k).+ = $($field)*} + ) +); +(%$($k:ident).+ = $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { %$($k).+ = $($field)*} + ) +); +($($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { $($k).+, $($field)*} + ) +); +(?$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { ?$($k).+, $($field)*} + ) +); +(%$($k:ident).+, $($field:tt)*) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { %$($k).+, $($field)*} + ) +); +(?$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { ?$($k).+ } + ) +); +(%$($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { %$($k).+ } + ) +); +($($k:ident).+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + { $($k).+ } + ) +); +($($arg:tt)+) => ( + $crate::event!( + target: module_path!(), + $crate::Level::ERROR, + $($arg)+ + ) +); +} + +#[doc(hidden)] +#[macro_export] +macro_rules! callsite { +(name: $name:expr, kind: $kind:expr, fields: $($fields:tt)*) => {{ + $crate::callsite! { + name: $name, + kind: $kind, + target: module_path!(), + level: $crate::Level::TRACE, + fields: $($fields)* + } +}}; +( + name: $name:expr, + kind: $kind:expr, + level: $lvl:expr, + fields: $($fields:tt)* +) => {{ + $crate::callsite! { + name: $name, + kind: $kind, + target: module_path!(), + level: $lvl, + fields: $($fields)* + } +}}; +( + name: $name:expr, + kind: $kind:expr, + target: $target:expr, + level: $lvl:expr, + fields: $($fields:tt)* +) => {{ + static META: $crate::Metadata<'static> = { + $crate::metadata! { + name: $name, + target: $target, + level: $lvl, + fields: $crate::fieldset!( $($fields)* ), + callsite: &__CALLSITE, + kind: $kind, + } + }; + static __CALLSITE: $crate::callsite::DefaultCallsite = $crate::callsite::DefaultCallsite::new(&META); + __CALLSITE.register(); + &__CALLSITE +}}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! callsite2 { +(name: $name:expr, kind: $kind:expr, fields: $($fields:tt)*) => {{ + $crate::callsite2! { + name: $name, + kind: $kind, + target: module_path!(), + level: $crate::Level::TRACE, + fields: $($fields)* + } +}}; +( + name: $name:expr, + kind: $kind:expr, + level: $lvl:expr, + fields: $($fields:tt)* +) => {{ + $crate::callsite2! { + name: $name, + kind: $kind, + target: module_path!(), + level: $lvl, + fields: $($fields)* + } +}}; +( + name: $name:expr, + kind: $kind:expr, + target: $target:expr, + level: $lvl:expr, + fields: $($fields:tt)* +) => {{ + static META: $crate::Metadata<'static> = { + $crate::metadata! { + name: $name, + target: $target, + level: $lvl, + fields: $crate::fieldset!( $($fields)* ), + callsite: &__CALLSITE, + kind: $kind, + } + }; + $crate::callsite::DefaultCallsite::new(&META) +}}; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! level_enabled { +($lvl:expr) => { + $lvl <= $crate::level_filters::STATIC_MAX_LEVEL + && $lvl <= $crate::level_filters::LevelFilter::current() +}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! valueset { + +// === base case === +(@ { $(,)* $($val:expr),* $(,)* }, $next:expr $(,)*) => { + &[ $($val),* ] +}; + +(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&debug(&$val) as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = %$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&display(&$val) as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = $val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&$val as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&$($k).+ as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, ?$($k:ident).+, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&debug(&$($k).+) as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, %$($k:ident).+, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&display(&$($k).+) as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = ?$val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&debug(&$val) as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = %$val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&display(&$val) as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = $val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&$val as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&$($k).+ as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, ?$($k:ident).+) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&debug(&$($k).+) as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, %$($k:ident).+) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&display(&$($k).+) as &dyn Value)) }, + $next, + ) +}; + +// Handle literal names +(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = ?$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&debug(&$val) as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = %$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&display(&$val) as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = $val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&$val as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = ?$val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&debug(&$val) as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = %$val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&display(&$val) as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = $val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, $crate::__macro_support::Option::Some(&$val as &dyn Value)) }, + $next, + ) +}; + +// Handle constant names +(@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = ?$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&debug(&$val) as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = %$val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&display(&$val) as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = $val:expr, $($rest:tt)*) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&$val as &dyn Value)) }, + $next, + $($rest)* + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = ?$val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&debug(&$val) as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = %$val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&display(&$val) as &dyn Value)) }, + $next, + ) +}; +(@ { $(,)* $($out:expr),* }, $next:expr, { $k:expr } = $val:expr) => { + $crate::valueset!( + @ { $($out),*, (&$next, Some(&$val as &dyn Value)) }, + $next, + ) +}; + +(@ { $(,)* $($out:expr),* }, $next:expr, $($rest:tt)+) => { + $crate::valueset!(@ { (&$next, $crate::__macro_support::Option::Some(&$crate::__macro_support::format_args!($($rest)+) as &dyn Value)), $($out),* }, $next, ) +}; + +($fields:expr, $($kvs:tt)+) => { + { + #[allow(unused_imports)] + use $crate::field::{debug, display, Value}; + let mut iter = $fields.iter(); + $fields.value_set($crate::valueset!( + @ { }, + $crate::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"), + $($kvs)+ + )) + } +}; +($fields:expr,) => { + { + $fields.value_set(&[]) + } +}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! fieldset { +(@ { $(,)* $($out:expr),* $(,)* } $(,)*) => { + &[ $($out),* ] +}; + +(@ { $(,)* $($out:expr),* } $($k:ident).+ = ?$val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $crate::__tracing_stringify!($($k).+) } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } $($k:ident).+ = %$val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $crate::__tracing_stringify!($($k).+) } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } $($k:ident).+ = $val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $crate::__tracing_stringify!($($k).+) } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } ?$($k:ident).+, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $crate::__tracing_stringify!($($k).+) } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } %$($k:ident).+, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $crate::__tracing_stringify!($($k).+) } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } $($k:ident).+, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $crate::__tracing_stringify!($($k).+) } $($rest)*) +}; + +// Handle literal names +(@ { $(,)* $($out:expr),* } $k:literal = ?$val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } $k:literal = %$val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } $k:literal = $val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) +}; + +// Handle constant names +(@ { $(,)* $($out:expr),* } { $k:expr } = ?$val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } { $k:expr } = %$val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) +}; +(@ { $(,)* $($out:expr),* } { $k:expr } = $val:expr, $($rest:tt)*) => { + $crate::fieldset!(@ { $($out),*, $k } $($rest)*) +}; + +(@ { $(,)* $($out:expr),* } $($rest:tt)+) => { + $crate::fieldset!(@ { "message", $($out),*, }) +}; + +($($args:tt)*) => { + $crate::fieldset!(@ { } $($args)*,) +}; + +} + +#[cfg(feature = "log")] +#[doc(hidden)] +#[macro_export] +macro_rules! level_to_log { +($level:expr) => { + match $level { + $crate::Level::ERROR => $crate::log::Level::Error, + $crate::Level::WARN => $crate::log::Level::Warn, + $crate::Level::INFO => $crate::log::Level::Info, + $crate::Level::DEBUG => $crate::log::Level::Debug, + _ => $crate::log::Level::Trace, + } +}; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __tracing_stringify { +($($t:tt)*) => { + stringify!($($t)*) +}; +} + +#[cfg(not(feature = "log"))] +#[doc(hidden)] +#[macro_export] +macro_rules! __tracing_log { +($level:expr, $callsite:expr, $value_set:expr) => {}; +} + +#[cfg(feature = "log")] +#[doc(hidden)] +#[macro_export] +macro_rules! __tracing_log { +($level:expr, $callsite:expr, $value_set:expr) => { + $crate::if_log_enabled! { $level, { + use $crate::log; + let level = $crate::level_to_log!($level); + if level <= log::max_level() { + let meta = $callsite.metadata(); + let log_meta = log::Metadata::builder() + .level(level) + .target(meta.target()) + .build(); + let logger = log::logger(); + if logger.enabled(&log_meta) { + $crate::__macro_support::__tracing_log(meta, logger, log_meta, $value_set) + } + } + }} +}; +} + +#[cfg(not(feature = "log"))] +#[doc(hidden)] +#[macro_export] +macro_rules! if_log_enabled { +($lvl:expr, $e:expr;) => { + $crate::if_log_enabled! { $lvl, $e } +}; +($lvl:expr, $if_log:block) => { + $crate::if_log_enabled! { $lvl, $if_log else {} } +}; +($lvl:expr, $if_log:block else $else_block:block) => { + $else_block +}; +} + +#[cfg(all(feature = "log", not(feature = "log-always")))] +#[doc(hidden)] +#[macro_export] +macro_rules! if_log_enabled { +($lvl:expr, $e:expr;) => { + $crate::if_log_enabled! { $lvl, $e } +}; +($lvl:expr, $if_log:block) => { + $crate::if_log_enabled! { $lvl, $if_log else {} } +}; +($lvl:expr, $if_log:block else $else_block:block) => { + if $crate::level_to_log!($lvl) <= $crate::log::STATIC_MAX_LEVEL { + if !$crate::dispatcher::has_been_set() { + $if_log + } else { + $else_block + } + } else { + $else_block + } +}; +} + +#[cfg(all(feature = "log", feature = "log-always"))] +#[doc(hidden)] +#[macro_export] +macro_rules! if_log_enabled { +($lvl:expr, $e:expr;) => { + $crate::if_log_enabled! { $lvl, $e } +}; +($lvl:expr, $if_log:block) => { + $crate::if_log_enabled! { $lvl, $if_log else {} } +}; +($lvl:expr, $if_log:block else $else_block:block) => { + if $crate::level_to_log!($lvl) <= $crate::log::STATIC_MAX_LEVEL { + #[allow(unused_braces)] + $if_log + } else { + $else_block + } +}; +} + +//- /lib.rs crate:ra_test_fixture deps:tracing +fn foo() { +tracing::error!(); +} + "#, + &["E0432", "inactive-code", "unresolved-macro-call", "syntax-error", "macro-error"], + ); +} diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs index 6a4e5ba290e..18f866eb9fc 100644 --- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs +++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs @@ -220,7 +220,11 @@ mod tests { location: AnnotationLocation::AboveName, }; - fn check_with_config(ra_fixture: &str, expect: Expect, config: &AnnotationConfig) { + fn check_with_config( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, + config: &AnnotationConfig, + ) { let (analysis, file_id) = fixture::file(ra_fixture); let annotations: Vec<Annotation> = analysis @@ -233,7 +237,7 @@ mod tests { expect.assert_debug_eq(&annotations); } - fn check(ra_fixture: &str, expect: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { check_with_config(ra_fixture, expect, &DEFAULT_CONFIG); } diff --git a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs index 8066894cd83..afd6f740c42 100644 --- a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs +++ b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs @@ -173,7 +173,7 @@ mod tests { fn check_hierarchy( exclude_tests: bool, - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, expected_nav: Expect, expected_incoming: Expect, expected_outgoing: Expect, diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs index 72fcac54177..bc9843f3f35 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs @@ -199,6 +199,7 @@ pub(crate) fn resolve_doc_path_for_def( ) -> Option<Definition> { match def { Definition::Module(it) => it.resolve_doc_path(db, link, ns), + Definition::Crate(it) => it.resolve_doc_path(db, link, ns), Definition::Function(it) => it.resolve_doc_path(db, link, ns), Definition::Adt(it) => it.resolve_doc_path(db, link, ns), Definition::Variant(it) => it.resolve_doc_path(db, link, ns), @@ -594,6 +595,7 @@ fn filename_and_frag_for_def( Adt::Enum(e) => format!("enum.{}.html", e.name(db).unescaped().display(db.upcast())), Adt::Union(u) => format!("union.{}.html", u.name(db).unescaped().display(db.upcast())), }, + Definition::Crate(_) => String::from("index.html"), Definition::Module(m) => match m.name(db) { // `#[doc(keyword = "...")]` is internal used only by rust compiler Some(name) => { diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs index fe91c81a615..d7291c4b9f3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs @@ -16,7 +16,7 @@ use crate::{ }; fn check_external_docs( - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, target_dir: Option<&str>, expect_web_url: Option<Expect>, expect_local_url: Option<Expect>, @@ -41,7 +41,7 @@ fn check_external_docs( } } -fn check_rewrite(ra_fixture: &str, expect: Expect) { +fn check_rewrite(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let sema = &Semantics::new(&*analysis.db); let (cursor_def, docs) = def_under_cursor(sema, &position); @@ -49,7 +49,7 @@ fn check_rewrite(ra_fixture: &str, expect: Expect) { expect.assert_eq(&res) } -fn check_doc_links(ra_fixture: &str) { +fn check_doc_links(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let key_fn = |&(FileRange { file_id, range }, _): &_| (file_id, range.start()); let (analysis, position, mut expected) = fixture::annotations(ra_fixture); diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs index e028c5ff0cb..0ad894427b2 100644 --- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs +++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs @@ -296,7 +296,7 @@ mod tests { use crate::fixture; #[track_caller] - fn check(ra_fixture: &str, expect: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, pos) = fixture::position(ra_fixture); let expansion = analysis.expand_macro(pos).unwrap().unwrap(); let actual = format!("{}\n{}", expansion.name, expansion.expansion); diff --git a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs index 5ef65c209ca..50977ee840c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs +++ b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs @@ -257,7 +257,7 @@ mod tests { use super::*; - fn check(ra_fixture: &str, expect: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let file = SourceFile::parse(ra_fixture, span::Edition::CURRENT).ok().unwrap(); let structure = file_structure(&file); expect.assert_debug_eq(&structure) diff --git a/src/tools/rust-analyzer/crates/ide/src/fixture.rs b/src/tools/rust-analyzer/crates/ide/src/fixture.rs index b16511072bd..a0612f48d37 100644 --- a/src/tools/rust-analyzer/crates/ide/src/fixture.rs +++ b/src/tools/rust-analyzer/crates/ide/src/fixture.rs @@ -5,7 +5,7 @@ use test_utils::{extract_annotations, RangeOrOffset}; use crate::{Analysis, AnalysisHost, FileId, FilePosition, FileRange}; /// Creates analysis for a single file. -pub(crate) fn file(ra_fixture: &str) -> (Analysis, FileId) { +pub(crate) fn file(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (Analysis, FileId) { let mut host = AnalysisHost::default(); let change_fixture = ChangeFixture::parse(ra_fixture); host.db.enable_proc_attr_macros(); @@ -14,7 +14,9 @@ pub(crate) fn file(ra_fixture: &str) -> (Analysis, FileId) { } /// Creates analysis from a multi-file fixture, returns positions marked with $0. -pub(crate) fn position(ra_fixture: &str) -> (Analysis, FilePosition) { +pub(crate) fn position( + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) -> (Analysis, FilePosition) { let mut host = AnalysisHost::default(); let change_fixture = ChangeFixture::parse(ra_fixture); host.db.enable_proc_attr_macros(); @@ -25,7 +27,7 @@ pub(crate) fn position(ra_fixture: &str) -> (Analysis, FilePosition) { } /// Creates analysis for a single file, returns range marked with a pair of $0. -pub(crate) fn range(ra_fixture: &str) -> (Analysis, FileRange) { +pub(crate) fn range(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (Analysis, FileRange) { let mut host = AnalysisHost::default(); let change_fixture = ChangeFixture::parse(ra_fixture); host.db.enable_proc_attr_macros(); @@ -36,7 +38,9 @@ pub(crate) fn range(ra_fixture: &str) -> (Analysis, FileRange) { } /// Creates analysis for a single file, returns range marked with a pair of $0 or a position marked with $0. -pub(crate) fn range_or_position(ra_fixture: &str) -> (Analysis, FileId, RangeOrOffset) { +pub(crate) fn range_or_position( + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) -> (Analysis, FileId, RangeOrOffset) { let mut host = AnalysisHost::default(); let change_fixture = ChangeFixture::parse(ra_fixture); host.db.enable_proc_attr_macros(); @@ -46,7 +50,9 @@ pub(crate) fn range_or_position(ra_fixture: &str) -> (Analysis, FileId, RangeOrO } /// Creates analysis from a multi-file fixture, returns positions marked with $0. -pub(crate) fn annotations(ra_fixture: &str) -> (Analysis, FilePosition, Vec<(FileRange, String)>) { +pub(crate) fn annotations( + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) -> (Analysis, FilePosition, Vec<(FileRange, String)>) { let mut host = AnalysisHost::default(); let change_fixture = ChangeFixture::parse(ra_fixture); host.db.enable_proc_attr_macros(); @@ -69,7 +75,9 @@ pub(crate) fn annotations(ra_fixture: &str) -> (Analysis, FilePosition, Vec<(Fil } /// Creates analysis from a multi-file fixture with annotations without $0 -pub(crate) fn annotations_without_marker(ra_fixture: &str) -> (Analysis, Vec<(FileRange, String)>) { +pub(crate) fn annotations_without_marker( + #[rust_analyzer::rust_fixture] ra_fixture: &str, +) -> (Analysis, Vec<(FileRange, String)>) { let mut host = AnalysisHost::default(); let change_fixture = ChangeFixture::parse(ra_fixture); host.db.enable_proc_attr_macros(); diff --git a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs index c1b7693a650..e5a94ff9fe9 100755 --- a/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs +++ b/src/tools/rust-analyzer/crates/ide/src/folding_ranges.rs @@ -286,7 +286,7 @@ mod tests { use super::*; - fn check(ra_fixture: &str) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (ranges, text) = extract_tags(ra_fixture, "fold"); let parse = SourceFile::parse(&text, span::Edition::CURRENT); diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs index 7b6a5ef13e5..3742edc8db8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs @@ -83,7 +83,7 @@ mod tests { use crate::fixture; - fn check(ra_fixture: &str) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, expected) = fixture::annotations(ra_fixture); let navs = analysis .goto_declaration(position) diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs index 6c66907ec3e..f804cc36772 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs @@ -81,6 +81,10 @@ pub(crate) fn goto_definition( return Some(RangeInfo::new(original_token.text_range(), navs)); } + if let Some(navs) = find_definition_for_known_blanket_dual_impls(sema, &original_token) { + return Some(RangeInfo::new(original_token.text_range(), navs)); + } + let navs = sema .descend_into_macros_no_opaque(original_token.clone()) .into_iter() @@ -125,6 +129,18 @@ pub(crate) fn goto_definition( Some(RangeInfo::new(original_token.text_range(), navs)) } +// If the token is into(), try_into(), parse(), search the definition of From, TryFrom, FromStr. +fn find_definition_for_known_blanket_dual_impls( + sema: &Semantics<'_, RootDatabase>, + original_token: &SyntaxToken, +) -> Option<Vec<NavigationTarget>> { + let method_call = ast::MethodCallExpr::cast(original_token.parent()?.parent()?)?; + let target_method = sema.resolve_known_blanket_dual_impls(&method_call)?; + + let def = Definition::from(target_method); + Some(def_to_nav(sema.db, def)) +} + fn try_lookup_include_path( sema: &Semantics<'_, RootDatabase>, token: ast::String, @@ -424,7 +440,7 @@ mod tests { use syntax::SmolStr; #[track_caller] - fn check(ra_fixture: &str) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, expected) = fixture::annotations(ra_fixture); let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info; @@ -443,14 +459,14 @@ mod tests { assert_eq!(expected, navs); } - fn check_unresolved(ra_fixture: &str) { + fn check_unresolved(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position) = fixture::position(ra_fixture); let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info; assert!(navs.is_empty(), "didn't expect this to resolve anywhere: {navs:?}") } - fn check_name(expected_name: &str, ra_fixture: &str) { + fn check_name(expected_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, _) = fixture::annotations(ra_fixture); let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info; assert!(navs.len() < 2, "expected single navigation target but encountered {}", navs.len()); @@ -3022,4 +3038,150 @@ fn foo() { "#, ); } + #[test] + fn into_call_to_from_definition() { + check( + r#" +//- minicore: from +struct A; + +struct B; + +impl From<A> for B { + fn from(value: A) -> Self { + //^^^^ + B + } +} + +fn f() { + let a = A; + let b: B = a.into$0(); +} + "#, + ); + } + + #[test] + fn into_call_to_from_definition_with_trait_bounds() { + check( + r#" +//- minicore: from, iterator +struct A; + +impl<T> From<T> for A +where + T: IntoIterator<Item = i64>, +{ + fn from(value: T) -> Self { + //^^^^ + A + } +} + +fn f() { + let a: A = [1, 2, 3].into$0(); +} + "#, + ); + } + + #[test] + fn goto_into_definition_if_exists() { + check( + r#" +//- minicore: from +struct A; + +struct B; + +impl Into<B> for A { + fn into(self) -> B { + //^^^^ + B + } +} + +fn f() { + let a = A; + let b: B = a.into$0(); +} + "#, + ); + } + + #[test] + fn try_into_call_to_try_from_definition() { + check( + r#" +//- minicore: from +struct A; + +struct B; + +impl TryFrom<A> for B { + type Error = String; + + fn try_from(value: A) -> Result<Self, Self::Error> { + //^^^^^^^^ + Ok(B) + } +} + +fn f() { + let a = A; + let b: Result<B, _> = a.try_into$0(); +} + "#, + ); + } + + #[test] + fn goto_try_into_definition_if_exists() { + check( + r#" +//- minicore: from +struct A; + +struct B; + +impl TryInto<B> for A { + type Error = String; + + fn try_into(self) -> Result<B, Self::Error> { + //^^^^^^^^ + Ok(B) + } +} + +fn f() { + let a = A; + let b: Result<B, _> = a.try_into$0(); +} + "#, + ); + } + + #[test] + fn parse_call_to_from_str_definition() { + check( + r#" +//- minicore: from, str +struct A; + +impl FromStr for A { + type Error = String; + + fn from_str(value: &str) -> Result<Self, Self::Error> { + //^^^^^^^^ + Ok(A) + } +} + +fn f() { + let a: Result<A, _> = "aaaaaa".parse$0(); +} + "#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs index 04da1f67e95..e926378367e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs @@ -129,7 +129,7 @@ mod tests { use crate::fixture; - fn check(ra_fixture: &str) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, expected) = fixture::annotations(ra_fixture); let navs = analysis.goto_implementation(position).unwrap().unwrap().info; diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs index c7ebd9a3531..2610d6c8863 100644 --- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs +++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs @@ -24,9 +24,10 @@ pub(crate) fn goto_type_definition( let file: ast::SourceFile = sema.parse_guess_edition(file_id); let token: SyntaxToken = pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind { - IDENT | INT_NUMBER | T![self] => 2, + IDENT | INT_NUMBER | T![self] => 3, kind if kind.is_trivia() => 0, - _ => 1, + T![;] => 1, + _ => 2, })?; let mut res = Vec::new(); @@ -118,7 +119,7 @@ mod tests { use crate::fixture; - fn check(ra_fixture: &str) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, expected) = fixture::annotations(ra_fixture); let navs = analysis.goto_type_definition(position).unwrap().unwrap().info; assert!(!navs.is_empty(), "navigation is empty"); diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs index 4002cbebad6..612bc36f628 100644 --- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs +++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs @@ -684,12 +684,15 @@ mod tests { }; #[track_caller] - fn check(ra_fixture: &str) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config(ra_fixture, ENABLED_CONFIG); } #[track_caller] - fn check_with_config(ra_fixture: &str, config: HighlightRelatedConfig) { + fn check_with_config( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + config: HighlightRelatedConfig, + ) { let (analysis, pos, annotations) = fixture::annotations(ra_fixture); let hls = analysis.highlight_related(config, pos).unwrap().unwrap_or_default(); diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index 1431bd8ca29..18a3fed07ec 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs @@ -6,7 +6,9 @@ mod tests; use std::{iter, ops::Not}; use either::Either; -use hir::{db::DefDatabase, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics}; +use hir::{ + db::DefDatabase, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics, +}; use ide_db::{ defs::{Definition, IdentClass, NameRefClass, OperatorClass}, famous_defs::FamousDefs, @@ -548,24 +550,29 @@ fn goto_type_action_for_def( }); } - if let Definition::GenericParam(hir::GenericParam::TypeParam(it)) = def { - let krate = it.module(db).krate(); - let sized_trait = - db.lang_item(krate.into(), LangItem::Sized).and_then(|lang_item| lang_item.as_trait()); - - it.trait_bounds(db) - .into_iter() - .filter(|&it| Some(it.into()) != sized_trait) - .for_each(|it| push_new_def(it.into())); - } else { - let ty = match def { - Definition::Local(it) => it.ty(db), - Definition::GenericParam(hir::GenericParam::ConstParam(it)) => it.ty(db), - Definition::Field(field) => field.ty(db), - Definition::Function(function) => function.ret_type(db), - _ => return HoverAction::goto_type_from_targets(db, targets, edition), - }; + if let Ok(generic_def) = GenericDef::try_from(def) { + generic_def.type_or_const_params(db).into_iter().for_each(|it| { + walk_and_push_ty(db, &it.ty(db), &mut push_new_def); + }); + } + let ty = match def { + Definition::Local(it) => Some(it.ty(db)), + Definition::Field(field) => Some(field.ty(db)), + Definition::TupleField(field) => Some(field.ty(db)), + Definition::Const(it) => Some(it.ty(db)), + Definition::Static(it) => Some(it.ty(db)), + Definition::Function(func) => { + for param in func.assoc_fn_params(db) { + walk_and_push_ty(db, param.ty(), &mut push_new_def); + } + Some(func.ret_type(db)) + } + Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)), + Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)), + _ => None, + }; + if let Some(ty) = ty { walk_and_push_ty(db, &ty, &mut push_new_def); } @@ -592,6 +599,14 @@ fn walk_and_push_ty( traits.for_each(|it| push_new_def(it.into())); } else if let Some(trait_) = t.as_associated_type_parent_trait(db) { push_new_def(trait_.into()); + } else if let Some(tp) = t.as_type_param(db) { + let sized_trait = db + .lang_item(t.krate(db).into(), LangItem::Sized) + .and_then(|lang_item| lang_item.as_trait()); + tp.trait_bounds(db) + .into_iter() + .filter(|&it| Some(it.into()) != sized_trait) + .for_each(|it| push_new_def(it.into())); } }); } diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index 8fbd445d962..46242b75dd0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs @@ -3,7 +3,7 @@ use std::{env, mem, ops::Not}; use either::Either; use hir::{ - db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, AssocItemContainer, CaptureKind, + db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError, MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef, }; @@ -376,7 +376,7 @@ pub(super) fn process_markup( Markup::from(markup) } -fn definition_owner_name(db: &RootDatabase, def: &Definition, edition: Edition) -> Option<String> { +fn definition_owner_name(db: &RootDatabase, def: Definition, edition: Edition) -> Option<String> { match def { Definition::Field(f) => { let parent = f.parent_def(db); @@ -390,9 +390,52 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition, edition: Edition) _ => Some(parent_name), }; } - Definition::Local(l) => l.parent(db).name(db), Definition::Variant(e) => Some(e.parent_enum(db).name(db)), - + Definition::GenericParam(generic_param) => match generic_param.parent() { + hir::GenericDef::Adt(it) => Some(it.name(db)), + hir::GenericDef::Trait(it) => Some(it.name(db)), + hir::GenericDef::TraitAlias(it) => Some(it.name(db)), + hir::GenericDef::TypeAlias(it) => Some(it.name(db)), + + hir::GenericDef::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)), + hir::GenericDef::Function(it) => { + let container = it.as_assoc_item(db).and_then(|assoc| match assoc.container(db) { + hir::AssocItemContainer::Trait(t) => Some(t.name(db)), + hir::AssocItemContainer::Impl(i) => { + i.self_ty(db).as_adt().map(|adt| adt.name(db)) + } + }); + match container { + Some(name) => { + return Some(format!( + "{}::{}", + name.display(db, edition), + it.name(db).display(db, edition) + )) + } + None => Some(it.name(db)), + } + } + hir::GenericDef::Const(it) => { + let container = it.as_assoc_item(db).and_then(|assoc| match assoc.container(db) { + hir::AssocItemContainer::Trait(t) => Some(t.name(db)), + hir::AssocItemContainer::Impl(i) => { + i.self_ty(db).as_adt().map(|adt| adt.name(db)) + } + }); + match container { + Some(name) => { + return Some(format!( + "{}::{}", + name.display(db, edition), + it.name(db)?.display(db, edition) + )) + } + None => it.name(db), + } + } + }, + Definition::DeriveHelper(derive_helper) => Some(derive_helper.derive().name(db)), d => { if let Some(assoc_item) = d.as_assoc_item(db) { match assoc_item.container(db) { @@ -436,7 +479,7 @@ pub(super) fn definition( config: &HoverConfig, edition: Edition, ) -> Markup { - let mod_path = definition_mod_path(db, &def, edition); + let mod_path = definition_path(db, &def, edition); let label = match def { Definition::Trait(trait_) => { trait_.display_limited(db, config.max_trait_assoc_items_count, edition).to_string() @@ -915,19 +958,22 @@ fn closure_ty( Some(res) } -fn definition_mod_path(db: &RootDatabase, def: &Definition, edition: Edition) -> Option<String> { - if matches!(def, Definition::GenericParam(_) | Definition::Local(_) | Definition::Label(_)) { +fn definition_path(db: &RootDatabase, &def: &Definition, edition: Edition) -> Option<String> { + if matches!( + def, + Definition::TupleField(_) + | Definition::Label(_) + | Definition::Local(_) + | Definition::BuiltinAttr(_) + | Definition::BuiltinLifetime(_) + | Definition::BuiltinType(_) + | Definition::InlineAsmRegOrRegClass(_) + | Definition::InlineAsmOperand(_) + ) { return None; } - let container: Option<Definition> = - def.as_assoc_item(db).and_then(|assoc| match assoc.container(db) { - AssocItemContainer::Trait(trait_) => Some(trait_.into()), - AssocItemContainer::Impl(impl_) => impl_.self_ty(db).as_adt().map(|adt| adt.into()), - }); - container - .unwrap_or(*def) - .module(db) - .map(|module| path(db, module, definition_owner_name(db, def, edition), edition)) + let rendered_parent = definition_owner_name(db, def, edition); + def.module(db).map(|module| path(db, module, rendered_parent, edition)) } fn markup( diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs index 2e7637e4677..014b751f95b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs @@ -23,7 +23,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig { max_subst_ty_len: super::SubstTyLen::Unlimited, }; -fn check_hover_no_result(ra_fixture: &str) { +fn check_hover_no_result(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( @@ -35,7 +35,7 @@ fn check_hover_no_result(ra_fixture: &str) { } #[track_caller] -fn check(ra_fixture: &str, expect: Expect) { +fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( @@ -55,7 +55,7 @@ fn check(ra_fixture: &str, expect: Expect) { #[track_caller] fn check_hover_fields_limit( fields_count: impl Into<Option<usize>>, - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect, ) { let (analysis, position) = fixture::position(ra_fixture); @@ -81,7 +81,7 @@ fn check_hover_fields_limit( #[track_caller] fn check_hover_enum_variants_limit( variants_count: impl Into<Option<usize>>, - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect, ) { let (analysis, position) = fixture::position(ra_fixture); @@ -105,7 +105,11 @@ fn check_hover_enum_variants_limit( } #[track_caller] -fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) { +fn check_assoc_count( + count: usize, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, +) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( @@ -126,7 +130,7 @@ fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } -fn check_hover_no_links(ra_fixture: &str, expect: Expect) { +fn check_hover_no_links(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( @@ -143,7 +147,7 @@ fn check_hover_no_links(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } -fn check_hover_no_memory_layout(ra_fixture: &str, expect: Expect) { +fn check_hover_no_memory_layout(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( @@ -160,7 +164,7 @@ fn check_hover_no_memory_layout(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } -fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) { +fn check_hover_no_markdown(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let hover = analysis .hover( @@ -181,7 +185,7 @@ fn check_hover_no_markdown(ra_fixture: &str, expect: Expect) { expect.assert_eq(&actual) } -fn check_actions(ra_fixture: &str, expect: Expect) { +fn check_actions(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, file_id, position) = fixture::range_or_position(ra_fixture); let mut hover = analysis .hover( @@ -206,13 +210,13 @@ fn check_actions(ra_fixture: &str, expect: Expect) { expect.assert_debug_eq(&hover.info.actions) } -fn check_hover_range(ra_fixture: &str, expect: Expect) { +fn check_hover_range(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, range) = fixture::range(ra_fixture); let hover = analysis.hover(&HOVER_BASE_CONFIG, range).unwrap().unwrap(); expect.assert_eq(hover.info.markup.as_str()) } -fn check_hover_range_actions(ra_fixture: &str, expect: Expect) { +fn check_hover_range_actions(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, range) = fixture::range(ra_fixture); let mut hover = analysis .hover(&HoverConfig { links_in_hover: true, ..HOVER_BASE_CONFIG }, range) @@ -234,7 +238,7 @@ fn check_hover_range_actions(ra_fixture: &str, expect: Expect) { expect.assert_debug_eq(&hover.info.actions); } -fn check_hover_range_no_results(ra_fixture: &str) { +fn check_hover_range_no_results(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, range) = fixture::range(ra_fixture); let hover = analysis.hover(&HOVER_BASE_CONFIG, range).unwrap(); assert!(hover.is_none()); @@ -2365,6 +2369,97 @@ fn test() { } #[test] +fn test_hover_show_type_def_for_func_param() { + check_actions( + r#" +struct Bar; +fn f(b: Bar) { + +} + +fn test() { + let b = Bar; + f$0(b); +} +"#, + expect![[r#" + [ + Reference( + FilePositionWrapper { + file_id: FileId( + 0, + ), + offset: 15, + }, + ), + GoToType( + [ + HoverGotoTypeData { + mod_path: "ra_test_fixture::Bar", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..11, + focus_range: 7..10, + name: "Bar", + kind: Struct, + description: "struct Bar", + }, + }, + ], + ), + ] + "#]], + ); +} + +#[test] +fn test_hover_show_type_def_for_trait_bound() { + check_actions( + r#" +trait Bar {} +fn f<T: Bar>(b: T) { + +} + +fn test() { + f$0(); +} +"#, + expect![[r#" + [ + Reference( + FilePositionWrapper { + file_id: FileId( + 0, + ), + offset: 16, + }, + ), + GoToType( + [ + HoverGotoTypeData { + mod_path: "ra_test_fixture::Bar", + nav: NavigationTarget { + file_id: FileId( + 0, + ), + full_range: 0..12, + focus_range: 6..9, + name: "Bar", + kind: Trait, + description: "trait Bar", + }, + }, + ], + ), + ] + "#]], + ); +} + +#[test] fn test_hover_non_ascii_space_doc() { check( " @@ -4700,6 +4795,10 @@ fn hover_lifetime() { *'lifetime* ```rust + ra_test_fixture::foo + ``` + + ```rust 'lifetime ``` "#]], @@ -4730,6 +4829,10 @@ impl<T: TraitA + TraitB> Foo<T$0> where T: Sized {} *T* ```rust + ra_test_fixture::Foo + ``` + + ```rust T: TraitA + TraitB ``` "#]], @@ -4744,6 +4847,10 @@ impl<T> Foo<T$0> {} *T* ```rust + ra_test_fixture::Foo + ``` + + ```rust T ``` "#]], @@ -4758,6 +4865,10 @@ impl<T: 'static> Foo<T$0> {} *T* ```rust + ra_test_fixture::Foo + ``` + + ```rust T: 'static ``` "#]], @@ -4778,6 +4889,10 @@ impl<T$0: Trait> Foo<T> {} *T* ```rust + ra_test_fixture::Foo + ``` + + ```rust T: Trait ``` "#]], @@ -4793,6 +4908,10 @@ impl<T$0: Trait + ?Sized> Foo<T> {} *T* ```rust + ra_test_fixture::Foo + ``` + + ```rust T: Trait + ?Sized ``` "#]], @@ -4813,6 +4932,10 @@ fn foo<T$0>() {} *T* ```rust + ra_test_fixture::foo + ``` + + ```rust T ``` @@ -4834,6 +4957,10 @@ fn foo<T$0: Sized>() {} *T* ```rust + ra_test_fixture::foo + ``` + + ```rust T ``` @@ -4855,6 +4982,10 @@ fn foo<T$0: ?Sized>() {} *T* ```rust + ra_test_fixture::foo + ``` + + ```rust T: ?Sized ``` @@ -4877,6 +5008,10 @@ fn foo<T$0: Trait>() {} *T* ```rust + ra_test_fixture::foo + ``` + + ```rust T: Trait ``` @@ -4899,6 +5034,10 @@ fn foo<T$0: Trait + Sized>() {} *T* ```rust + ra_test_fixture::foo + ``` + + ```rust T: Trait ``` @@ -4921,6 +5060,10 @@ fn foo<T$0: Trait + ?Sized>() {} *T* ```rust + ra_test_fixture::foo + ``` + + ```rust T: Trait + ?Sized ``` @@ -4942,6 +5085,10 @@ fn foo<T$0: ?Sized + Sized + Sized>() {} *T* ```rust + ra_test_fixture::foo + ``` + + ```rust T ``` @@ -4964,6 +5111,10 @@ fn foo<T$0: Sized + ?Sized + Sized + Trait>() {} *T* ```rust + ra_test_fixture::foo + ``` + + ```rust T: Trait ``` @@ -5011,6 +5162,10 @@ impl<const LEN: usize> Foo<LEN$0> {} *LEN* ```rust + ra_test_fixture::Foo + ``` + + ```rust const LEN: usize ``` "#]], @@ -6112,7 +6267,7 @@ use foo::bar::{self$0}; ``` ```rust - mod bar + pub mod bar ``` --- @@ -7857,7 +8012,7 @@ fn test() { *foo* ```rust - ra_test_fixture::S + ra_test_fixture::m::S ``` ```rust @@ -7886,7 +8041,7 @@ fn test() { *foo* ```rust - ra_test_fixture::S + ra_test_fixture::m::S ``` ```rust @@ -7916,7 +8071,7 @@ mod m { *foo* ```rust - ra_test_fixture::S + ra_test_fixture::m::inner::S ``` ```rust @@ -7946,7 +8101,7 @@ fn test() { *A* ```rust - ra_test_fixture::S + ra_test_fixture::m::S ``` ```rust @@ -7975,7 +8130,7 @@ fn test() { *A* ```rust - ra_test_fixture::S + ra_test_fixture::m::S ``` ```rust @@ -8005,7 +8160,7 @@ mod m { *A* ```rust - ra_test_fixture::S + ra_test_fixture::m::inner::S ``` ```rust diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs index faa65019eea..6d83a747d76 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs @@ -1,6 +1,6 @@ use std::{ fmt::{self, Write}, - mem::take, + mem::{self, take}, }; use either::Either; @@ -24,6 +24,7 @@ use crate::{navigation_target::TryToNav, FileId}; mod adjustment; mod bind_pat; mod binding_mode; +mod bounds; mod chaining; mod closing_brace; mod closure_captures; @@ -111,6 +112,9 @@ pub(crate) fn inlay_hints( } hints(event); } + if let Some(range_limit) = range_limit { + acc.retain(|hint| range_limit.contains_range(hint.range)); + } acc } @@ -264,6 +268,7 @@ fn hints( ast::Type::PathType(path) => lifetime::fn_path_hints(hints, ctx, famous_defs, config, file_id, path), _ => Some(()), }, + ast::GenericParamList(it) => bounds::hints(hints, famous_defs, config, file_id, it), _ => Some(()), } }; @@ -273,6 +278,7 @@ fn hints( pub struct InlayHintsConfig { pub render_colons: bool, pub type_hints: bool, + pub sized_bound: bool, pub discriminant_hints: DiscriminantHints, pub parameter_hints: bool, pub generic_parameter_hints: GenericParameterHints, @@ -294,6 +300,36 @@ pub struct InlayHintsConfig { pub closing_brace_hints_min_lines: Option<usize>, pub fields_to_resolve: InlayFieldsToResolve, } +impl InlayHintsConfig { + fn lazy_text_edit(&self, finish: impl FnOnce() -> TextEdit) -> Lazy<TextEdit> { + if self.fields_to_resolve.resolve_text_edits { + Lazy::Lazy + } else { + let edit = finish(); + never!(edit.is_empty(), "inlay hint produced an empty text edit"); + Lazy::Computed(edit) + } + } + + fn lazy_tooltip(&self, finish: impl FnOnce() -> InlayTooltip) -> Lazy<InlayTooltip> { + if self.fields_to_resolve.resolve_hint_tooltip + && self.fields_to_resolve.resolve_label_tooltip + { + Lazy::Lazy + } else { + let tooltip = finish(); + never!( + match &tooltip { + InlayTooltip::String(s) => s, + InlayTooltip::Markdown(s) => s, + } + .is_empty(), + "inlay hint produced an empty tooltip" + ); + Lazy::Computed(tooltip) + } + } +} #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct InlayFieldsToResolve { @@ -405,12 +441,32 @@ pub struct InlayHint { /// The actual label to show in the inlay hint. pub label: InlayHintLabel, /// Text edit to apply when "accepting" this inlay hint. - pub text_edit: Option<TextEdit>, + pub text_edit: Option<Lazy<TextEdit>>, /// Range to recompute inlay hints when trying to resolve for this hint. If this is none, the /// hint does not support resolving. pub resolve_parent: Option<TextRange>, } +/// A type signaling that a value is either computed, or is available for computation. +#[derive(Clone, Debug)] +pub enum Lazy<T> { + Computed(T), + Lazy, +} + +impl<T> Lazy<T> { + pub fn computed(self) -> Option<T> { + match self { + Lazy::Computed(it) => Some(it), + _ => None, + } + } + + pub fn is_lazy(&self) -> bool { + matches!(self, Self::Lazy) + } +} + impl std::hash::Hash for InlayHint { fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.range.hash(state); @@ -419,7 +475,7 @@ impl std::hash::Hash for InlayHint { self.pad_right.hash(state); self.kind.hash(state); self.label.hash(state); - self.text_edit.is_some().hash(state); + mem::discriminant(&self.text_edit).hash(state); } } @@ -436,10 +492,6 @@ impl InlayHint { resolve_parent: None, } } - - pub fn needs_resolve(&self) -> Option<TextRange> { - self.resolve_parent.filter(|_| self.text_edit.is_some() || self.label.needs_resolve()) - } } #[derive(Debug, Hash)] @@ -456,7 +508,7 @@ pub struct InlayHintLabel { impl InlayHintLabel { pub fn simple( s: impl Into<String>, - tooltip: Option<InlayTooltip>, + tooltip: Option<Lazy<InlayTooltip>>, linked_location: Option<FileRange>, ) -> InlayHintLabel { InlayHintLabel { @@ -500,10 +552,6 @@ impl InlayHintLabel { } self.parts.push(part); } - - pub fn needs_resolve(&self) -> bool { - self.parts.iter().any(|part| part.linked_location.is_some() || part.tooltip.is_some()) - } } impl From<String> for InlayHintLabel { @@ -538,7 +586,6 @@ impl fmt::Debug for InlayHintLabel { } } -#[derive(Hash)] pub struct InlayHintLabelPart { pub text: String, /// Source location represented by this label part. The client will use this to fetch the part's @@ -549,13 +596,21 @@ pub struct InlayHintLabelPart { pub linked_location: Option<FileRange>, /// The tooltip to show when hovering over the inlay hint, this may invoke other actions like /// hover requests to show. - pub tooltip: Option<InlayTooltip>, + pub tooltip: Option<Lazy<InlayTooltip>>, +} + +impl std::hash::Hash for InlayHintLabelPart { + fn hash<H: std::hash::Hasher>(&self, state: &mut H) { + self.text.hash(state); + self.linked_location.hash(state); + self.tooltip.is_some().hash(state); + } } impl fmt::Debug for InlayHintLabelPart { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self { text, linked_location: None, tooltip: None } => text.fmt(f), + Self { text, linked_location: None, tooltip: None | Some(Lazy::Lazy) } => text.fmt(f), Self { text, linked_location, tooltip } => f .debug_struct("InlayHintLabelPart") .field("text", text) @@ -563,7 +618,8 @@ impl fmt::Debug for InlayHintLabelPart { .field( "tooltip", &tooltip.as_ref().map_or("", |it| match it { - InlayTooltip::String(it) | InlayTooltip::Markdown(it) => it, + Lazy::Computed(InlayTooltip::String(it) | InlayTooltip::Markdown(it)) => it, + Lazy::Lazy => "", }), ) .finish(), @@ -722,19 +778,22 @@ fn hint_iterator( fn ty_to_text_edit( sema: &Semantics<'_, RootDatabase>, + config: &InlayHintsConfig, node_for_hint: &SyntaxNode, ty: &hir::Type, offset_to_insert: TextSize, - prefix: String, -) -> Option<TextEdit> { - let scope = sema.scope(node_for_hint)?; + prefix: impl Into<String>, +) -> Option<Lazy<TextEdit>> { // FIXME: Limit the length and bail out on excess somehow? - let rendered = ty.display_source_code(scope.db, scope.module().into(), false).ok()?; - - let mut builder = TextEdit::builder(); - builder.insert(offset_to_insert, prefix); - builder.insert(offset_to_insert, rendered); - Some(builder.finish()) + let rendered = sema + .scope(node_for_hint) + .and_then(|scope| ty.display_source_code(scope.db, scope.module().into(), false).ok())?; + Some(config.lazy_text_edit(|| { + let mut builder = TextEdit::builder(); + builder.insert(offset_to_insert, prefix.into()); + builder.insert(offset_to_insert, rendered); + builder.finish() + })) } fn closure_has_block_body(closure: &ast::ClosureExpr) -> bool { @@ -760,6 +819,7 @@ mod tests { render_colons: false, type_hints: false, parameter_hints: false, + sized_bound: false, generic_parameter_hints: GenericParameterHints { type_hints: false, lifetime_hints: false, @@ -794,12 +854,15 @@ mod tests { }; #[track_caller] - pub(super) fn check(ra_fixture: &str) { + pub(super) fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config(TEST_CONFIG, ra_fixture); } #[track_caller] - pub(super) fn check_with_config(config: InlayHintsConfig, ra_fixture: &str) { + pub(super) fn check_with_config( + config: InlayHintsConfig, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + ) { let (analysis, file_id) = fixture::file(ra_fixture); let mut expected = extract_annotations(&analysis.file_text(file_id).unwrap()); let inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); @@ -814,16 +877,33 @@ mod tests { assert_eq!(expected, actual, "\nExpected:\n{expected:#?}\n\nActual:\n{actual:#?}"); } + #[track_caller] + pub(super) fn check_expect( + config: InlayHintsConfig, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, + ) { + let (analysis, file_id) = fixture::file(ra_fixture); + let inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); + let filtered = + inlay_hints.into_iter().map(|hint| (hint.range, hint.label)).collect::<Vec<_>>(); + expect.assert_debug_eq(&filtered) + } + /// Computes inlay hints for the fixture, applies all the provided text edits and then runs /// expect test. #[track_caller] - pub(super) fn check_edit(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { + pub(super) fn check_edit( + config: InlayHintsConfig, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, + ) { let (analysis, file_id) = fixture::file(ra_fixture); let inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); let edits = inlay_hints .into_iter() - .filter_map(|hint| hint.text_edit) + .filter_map(|hint| hint.text_edit?.computed()) .reduce(|mut acc, next| { acc.union(next).expect("merging text edits failed"); acc @@ -836,11 +916,15 @@ mod tests { } #[track_caller] - pub(super) fn check_no_edit(config: InlayHintsConfig, ra_fixture: &str) { + pub(super) fn check_no_edit( + config: InlayHintsConfig, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + ) { let (analysis, file_id) = fixture::file(ra_fixture); let inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); - let edits: Vec<_> = inlay_hints.into_iter().filter_map(|hint| hint.text_edit).collect(); + let edits: Vec<_> = + inlay_hints.into_iter().filter_map(|hint| hint.text_edit?.computed()).collect(); assert!(edits.is_empty(), "unexpected edits: {edits:?}"); } @@ -870,4 +954,17 @@ fn foo() { "#, ); } + + #[test] + fn regression_18898() { + check( + r#" +//- proc_macros: issue_18898 +#[proc_macros::issue_18898] +fn foo() { + let +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs index 4e48baa6f14..2acd4021cc1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs @@ -162,11 +162,13 @@ pub(super) fn hints( let label = InlayHintLabelPart { text: if postfix { format!(".{}", text.trim_end()) } else { text.to_owned() }, linked_location: None, - tooltip: Some(InlayTooltip::Markdown(format!( - "`{}` → `{}` ({coercion} coercion)", - source.display(sema.db, file_id.edition()), - target.display(sema.db, file_id.edition()), - ))), + tooltip: Some(config.lazy_tooltip(|| { + InlayTooltip::Markdown(format!( + "`{}` → `{}` ({coercion} coercion)", + source.display(sema.db, file_id.edition()), + target.display(sema.db, file_id.edition()), + )) + })), }; if postfix { &mut post } else { &mut pre }.label.append_part(label); } @@ -183,7 +185,7 @@ pub(super) fn hints( return None; } if allow_edit { - let edit = { + let edit = Some(config.lazy_text_edit(|| { let mut b = TextEditBuilder::default(); if let Some(pre) = &pre { b.insert( @@ -198,14 +200,14 @@ pub(super) fn hints( ); } b.finish() - }; + })); match (&mut pre, &mut post) { (Some(pre), Some(post)) => { - pre.text_edit = Some(edit.clone()); - post.text_edit = Some(edit); + pre.text_edit = edit.clone(); + post.text_edit = edit; } - (Some(pre), None) => pre.text_edit = Some(edit), - (None, Some(post)) => post.text_edit = Some(edit), + (Some(pre), None) => pre.text_edit = edit, + (None, Some(post)) => post.text_edit = edit, (None, None) => (), } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs index 7a808fb4a92..ab5464156f0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs @@ -78,13 +78,14 @@ pub(super) fn hints( let text_edit = if let Some(colon_token) = &type_ascriptable { ty_to_text_edit( sema, + config, desc_pat.syntax(), &ty, colon_token .as_ref() .map_or_else(|| pat.syntax().text_range(), |t| t.text_range()) .end(), - if colon_token.is_some() { String::new() } else { String::from(": ") }, + if colon_token.is_some() { "" } else { ": " }, ) } else { None @@ -185,7 +186,7 @@ mod tests { }; #[track_caller] - fn check_types(ra_fixture: &str) { + fn check_types(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config(InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG }, ra_fixture); } @@ -391,36 +392,37 @@ fn main() { #[test] fn check_hint_range_limit() { let fixture = r#" - //- minicore: fn, sized - fn foo() -> impl Fn() { loop {} } - fn foo1() -> impl Fn(f64) { loop {} } - fn foo2() -> impl Fn(f64, f64) { loop {} } - fn foo3() -> impl Fn(f64, f64) -> u32 { loop {} } - fn foo4() -> &'static dyn Fn(f64, f64) -> u32 { loop {} } - fn foo5() -> &'static dyn Fn(&'static dyn Fn(f64, f64) -> u32, f64) -> u32 { loop {} } - fn foo6() -> impl Fn(f64, f64) -> u32 + Sized { loop {} } - fn foo7() -> *const (impl Fn(f64, f64) -> u32 + Sized) { loop {} } - - fn main() { - let foo = foo(); - let foo = foo1(); - let foo = foo2(); - // ^^^ impl Fn(f64, f64) - let foo = foo3(); - // ^^^ impl Fn(f64, f64) -> u32 - let foo = foo4(); - let foo = foo5(); - let foo = foo6(); - let foo = foo7(); - } - "#; +//- minicore: fn, sized +fn foo() -> impl Fn() { loop {} } +fn foo1() -> impl Fn(f64) { loop {} } +fn foo2() -> impl Fn(f64, f64) { loop {} } +fn foo3() -> impl Fn(f64, f64) -> u32 { loop {} } +fn foo4() -> &'static dyn Fn(f64, f64) -> u32 { loop {} } +fn foo5() -> &'static dyn Fn(&'static dyn Fn(f64, f64) -> u32, f64) -> u32 { loop {} } +fn foo6() -> impl Fn(f64, f64) -> u32 + Sized { loop {} } +fn foo7() -> *const (impl Fn(f64, f64) -> u32 + Sized) { loop {} } + +fn main() { + let foo = foo(); + let foo = foo1(); + let foo = foo2(); + // ^^^ impl Fn(f64, f64) + let foo = foo3(); + // ^^^ impl Fn(f64, f64) -> u32 + let foo = foo4(); + // ^^^ &dyn Fn(f64, f64) -> u32 + let foo = foo5(); + let foo = foo6(); + let foo = foo7(); +} +"#; let (analysis, file_id) = fixture::file(fixture); let expected = extract_annotations(&analysis.file_text(file_id).unwrap()); let inlay_hints = analysis .inlay_hints( &InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG }, file_id, - Some(TextRange::new(TextSize::from(500), TextSize::from(600))), + Some(TextRange::new(TextSize::from(491), TextSize::from(640))), ) .unwrap(); let actual = @@ -1163,4 +1165,45 @@ fn main() { }"#, ); } + + #[test] + fn collapses_nested_impl_projections() { + check_types( + r#" +//- minicore: sized +trait T { + type Assoc; + fn f(self) -> Self::Assoc; +} + +trait T2 {} +trait T3<T> {} + +fn f(it: impl T<Assoc: T2>) { + let l = it.f(); + // ^ impl T2 +} + +fn f2<G: T<Assoc: T2 + 'static>>(it: G) { + let l = it.f(); + //^ impl T2 + 'static +} + +fn f3<G: T>(it: G) where <G as T>::Assoc: T2 { + let l = it.f(); + //^ impl T2 +} + +fn f4<G: T<Assoc: T2 + T3<()>>>(it: G) { + let l = it.f(); + //^ impl T2 + T3<()> +} + +fn f5<G: T<Assoc = ()>>(it: G) { + let l = it.f(); + //^ () +} +"#, + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs index 5afb98cb1c7..5bbb4fe4e66 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs @@ -99,17 +99,24 @@ pub(super) fn hints( } if let hints @ [_, ..] = &mut acc[acc_base..] { - let mut edit = TextEditBuilder::default(); - for h in &mut *hints { - edit.insert( - match h.position { - InlayHintPosition::Before => h.range.start(), - InlayHintPosition::After => h.range.end(), - }, - h.label.parts.iter().map(|p| &*p.text).collect(), - ); - } - let edit = edit.finish(); + let edit = config.lazy_text_edit(|| { + let mut edit = TextEditBuilder::default(); + for h in &mut *hints { + edit.insert( + match h.position { + InlayHintPosition::Before => h.range.start(), + InlayHintPosition::After => h.range.end(), + }, + h.label + .parts + .iter() + .map(|p| &*p.text) + .chain(h.pad_right.then_some(" ")) + .collect(), + ); + } + edit.finish() + }); hints.iter_mut().for_each(|h| h.text_edit = Some(edit.clone())); } @@ -118,8 +125,10 @@ pub(super) fn hints( #[cfg(test)] mod tests { + use expect_test::expect; + use crate::{ - inlay_hints::tests::{check_with_config, DISABLED_CONFIG}, + inlay_hints::tests::{check_edit, check_with_config, DISABLED_CONFIG}, InlayHintsConfig, }; @@ -194,4 +203,27 @@ fn foo(s @ Struct { field, .. }: &Struct) {} "#, ); } + + #[test] + fn edits() { + check_edit( + InlayHintsConfig { binding_mode_hints: true, ..DISABLED_CONFIG }, + r#" +fn main() { + match &(0,) { + (x,) | (x,) => (), + ((x,) | (x,)) => (), + } +} +"#, + expect![[r#" + fn main() { + match &(0,) { + &(&((ref x,) | (ref x,))) => (), + &((ref x,) | (ref x,)) => (), + } + } + "#]], + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs new file mode 100644 index 00000000000..429ddd31cbd --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bounds.rs @@ -0,0 +1,152 @@ +//! Implementation of trait bound hints. +//! +//! Currently this renders the implied `Sized` bound. +use ide_db::{famous_defs::FamousDefs, FileRange}; + +use span::EditionedFileId; +use syntax::ast::{self, AstNode, HasTypeBounds}; + +use crate::{ + InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintPosition, InlayHintsConfig, InlayKind, + TryToNav, +}; + +pub(super) fn hints( + acc: &mut Vec<InlayHint>, + famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>, + config: &InlayHintsConfig, + _file_id: EditionedFileId, + params: ast::GenericParamList, +) -> Option<()> { + if !config.sized_bound { + return None; + } + + let linked_location = + famous_defs.core_marker_Sized().and_then(|it| it.try_to_nav(sema.db)).map(|it| { + let n = it.call_site(); + FileRange { file_id: n.file_id, range: n.focus_or_full_range() } + }); + + for param in params.type_or_const_params() { + match param { + ast::TypeOrConstParam::Type(type_param) => { + let c = type_param.colon_token().map(|it| it.text_range()); + let has_bounds = + type_param.type_bound_list().is_some_and(|it| it.bounds().next().is_some()); + acc.push(InlayHint { + range: c.unwrap_or_else(|| type_param.syntax().text_range()), + kind: InlayKind::Type, + label: { + let mut hint = InlayHintLabel::default(); + if c.is_none() { + hint.parts.push(InlayHintLabelPart { + text: ": ".to_owned(), + linked_location: None, + tooltip: None, + }); + } + hint.parts.push(InlayHintLabelPart { + text: "Sized".to_owned(), + linked_location, + tooltip: None, + }); + if has_bounds { + hint.parts.push(InlayHintLabelPart { + text: " +".to_owned(), + linked_location: None, + tooltip: None, + }); + } + hint + }, + text_edit: None, + position: InlayHintPosition::After, + pad_left: c.is_some(), + pad_right: has_bounds, + resolve_parent: Some(params.syntax().text_range()), + }); + } + ast::TypeOrConstParam::Const(_) => (), + } + } + + Some(()) +} + +#[cfg(test)] +mod tests { + use expect_test::expect; + + use crate::inlay_hints::InlayHintsConfig; + + use crate::inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG}; + + #[track_caller] + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { + check_with_config(InlayHintsConfig { sized_bound: true, ..DISABLED_CONFIG }, ra_fixture); + } + + #[test] + fn smoke() { + check( + r#" +fn foo<T>() {} + // ^ : Sized +"#, + ); + } + + #[test] + fn with_colon() { + check( + r#" +fn foo<T:>() {} + // ^ Sized +"#, + ); + } + + #[test] + fn with_colon_and_bounds() { + check( + r#" +fn foo<T: 'static>() {} + // ^ Sized + +"#, + ); + } + + #[test] + fn location_works() { + check_expect( + InlayHintsConfig { sized_bound: true, ..DISABLED_CONFIG }, + r#" +//- minicore: sized +fn foo<T>() {} +"#, + expect![[r#" + [ + ( + 7..8, + [ + ": ", + InlayHintLabelPart { + text: "Sized", + linked_location: Some( + FileRangeWrapper { + file_id: FileId( + 1, + ), + range: 135..140, + }, + ), + tooltip: "", + }, + ], + ), + ] + "#]], + ); + } +} diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs index 028ed1650f4..7fa7ab1a94d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs @@ -81,28 +81,19 @@ mod tests { use crate::{ fixture, - inlay_hints::tests::{check_with_config, DISABLED_CONFIG, TEST_CONFIG}, + inlay_hints::tests::{check_expect, check_with_config, DISABLED_CONFIG, TEST_CONFIG}, InlayHintsConfig, }; #[track_caller] - fn check_chains(ra_fixture: &str) { + fn check_chains(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config(InlayHintsConfig { chaining_hints: true, ..DISABLED_CONFIG }, ra_fixture); } #[track_caller] - pub(super) fn check_expect(config: InlayHintsConfig, ra_fixture: &str, expect: Expect) { - let (analysis, file_id) = fixture::file(ra_fixture); - let inlay_hints = analysis.inlay_hints(&config, file_id, None).unwrap(); - let filtered = - inlay_hints.into_iter().map(|hint| (hint.range, hint.label)).collect::<Vec<_>>(); - expect.assert_debug_eq(&filtered) - } - - #[track_caller] pub(super) fn check_expect_clear_loc( config: InlayHintsConfig, - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect, ) { let (analysis, file_id) = fixture::file(ra_fixture); diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs index 6827540fa82..7858b1d90a3 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs @@ -52,13 +52,14 @@ pub(super) fn hints( let text_edit = if has_block_body { ty_to_text_edit( sema, + config, closure.syntax(), &ty, arrow .as_ref() .map_or_else(|| param_list.syntax().text_range(), |t| t.text_range()) .end(), - if arrow.is_none() { String::from(" -> ") } else { String::new() }, + if arrow.is_none() { " -> " } else { "" }, ) } else { None diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs index 8f2949cb387..f1e1955d14c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs @@ -36,13 +36,14 @@ pub(super) fn enum_hints( return None; } for variant in enum_.variant_list()?.variants() { - variant_hints(acc, sema, &enum_, &variant); + variant_hints(acc, config, sema, &enum_, &variant); } Some(()) } fn variant_hints( acc: &mut Vec<InlayHint>, + config: &InlayHintsConfig, sema: &Semantics<'_, RootDatabase>, enum_: &ast::Enum, variant: &ast::Variant, @@ -75,9 +76,11 @@ fn variant_hints( } Err(_) => format!("{eq_} ?"), }, - Some(InlayTooltip::String(match &d { - Ok(_) => "enum variant discriminant".into(), - Err(e) => format!("{e:?}"), + Some(config.lazy_tooltip(|| { + InlayTooltip::String(match &d { + Ok(_) => "enum variant discriminant".into(), + Err(e) => format!("{e:?}"), + }) })), None, ); @@ -88,7 +91,9 @@ fn variant_hints( }, kind: InlayKind::Discriminant, label, - text_edit: d.ok().map(|val| TextEdit::insert(range.start(), format!("{eq_} {val}"))), + text_edit: d.ok().map(|val| { + config.lazy_text_edit(|| TextEdit::insert(range.end(), format!("{eq_} {val}"))) + }), position: InlayHintPosition::After, pad_left: false, pad_right: false, @@ -99,13 +104,15 @@ fn variant_hints( } #[cfg(test)] mod tests { + use expect_test::expect; + use crate::inlay_hints::{ - tests::{check_with_config, DISABLED_CONFIG}, + tests::{check_edit, check_with_config, DISABLED_CONFIG}, DiscriminantHints, InlayHintsConfig, }; #[track_caller] - fn check_discriminants(ra_fixture: &str) { + fn check_discriminants(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config( InlayHintsConfig { discriminant_hints: DiscriminantHints::Always, ..DISABLED_CONFIG }, ra_fixture, @@ -113,7 +120,7 @@ mod tests { } #[track_caller] - fn check_discriminants_fieldless(ra_fixture: &str) { + fn check_discriminants_fieldless(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config( InlayHintsConfig { discriminant_hints: DiscriminantHints::Fieldless, @@ -207,4 +214,33 @@ enum Enum { "#, ); } + + #[test] + fn edit() { + check_edit( + InlayHintsConfig { discriminant_hints: DiscriminantHints::Always, ..DISABLED_CONFIG }, + r#" +#[repr(u8)] +enum Enum { + Variant(), + Variant1, + Variant2 {}, + Variant3, + Variant5, + Variant6, +} +"#, + expect![[r#" + #[repr(u8)] + enum Enum { + Variant() = 0, + Variant1 = 1, + Variant2 {} = 2, + Variant3 = 3, + Variant5 = 4, + Variant6 = 5, + } + "#]], + ); + } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs index 4cc4925cda6..2bc91b68ed8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/extern_block.rs @@ -8,7 +8,7 @@ use crate::{InlayHint, InlayHintsConfig}; pub(super) fn extern_block_hints( acc: &mut Vec<InlayHint>, FamousDefs(_sema, _): &FamousDefs<'_, '_>, - _config: &InlayHintsConfig, + config: &InlayHintsConfig, _file_id: EditionedFileId, extern_block: ast::ExternBlock, ) -> Option<()> { @@ -23,7 +23,9 @@ pub(super) fn extern_block_hints( pad_right: true, kind: crate::InlayKind::ExternUnsafety, label: crate::InlayHintLabel::from("unsafe"), - text_edit: Some(TextEdit::insert(abi.syntax().text_range().start(), "unsafe ".to_owned())), + text_edit: Some(config.lazy_text_edit(|| { + TextEdit::insert(abi.syntax().text_range().start(), "unsafe ".to_owned()) + })), resolve_parent: Some(extern_block.syntax().text_range()), }); Some(()) @@ -32,7 +34,7 @@ pub(super) fn extern_block_hints( pub(super) fn fn_hints( acc: &mut Vec<InlayHint>, FamousDefs(_sema, _): &FamousDefs<'_, '_>, - _config: &InlayHintsConfig, + config: &InlayHintsConfig, _file_id: EditionedFileId, fn_: &ast::Fn, extern_block: &ast::ExternBlock, @@ -42,14 +44,14 @@ pub(super) fn fn_hints( return None; } let fn_ = fn_.fn_token()?; - acc.push(item_hint(extern_block, fn_)); + acc.push(item_hint(config, extern_block, fn_)); Some(()) } pub(super) fn static_hints( acc: &mut Vec<InlayHint>, FamousDefs(_sema, _): &FamousDefs<'_, '_>, - _config: &InlayHintsConfig, + config: &InlayHintsConfig, _file_id: EditionedFileId, static_: &ast::Static, extern_block: &ast::ExternBlock, @@ -59,11 +61,15 @@ pub(super) fn static_hints( return None; } let static_ = static_.static_token()?; - acc.push(item_hint(extern_block, static_)); + acc.push(item_hint(config, extern_block, static_)); Some(()) } -fn item_hint(extern_block: &ast::ExternBlock, token: SyntaxToken) -> InlayHint { +fn item_hint( + config: &InlayHintsConfig, + extern_block: &ast::ExternBlock, + token: SyntaxToken, +) -> InlayHint { InlayHint { range: token.text_range(), position: crate::InlayHintPosition::Before, @@ -71,7 +77,7 @@ fn item_hint(extern_block: &ast::ExternBlock, token: SyntaxToken) -> InlayHint { pad_right: true, kind: crate::InlayKind::ExternUnsafety, label: crate::InlayHintLabel::from("unsafe"), - text_edit: { + text_edit: Some(config.lazy_text_edit(|| { let mut builder = TextEdit::builder(); builder.insert(token.text_range().start(), "unsafe ".to_owned()); if extern_block.unsafe_token().is_none() { @@ -79,8 +85,8 @@ fn item_hint(extern_block: &ast::ExternBlock, token: SyntaxToken) -> InlayHint { builder.insert(abi.syntax().text_range().start(), "unsafe ".to_owned()); } } - Some(builder.finish()) - }, + builder.finish() + })), resolve_parent: Some(extern_block.syntax().text_range()), } } diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs index ed7ebc3b1e7..037b328d971 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/generic_param.rs @@ -142,7 +142,7 @@ mod tests { }; #[track_caller] - fn generic_param_name_hints_always(ra_fixture: &str) { + fn generic_param_name_hints_always(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config( InlayHintsConfig { generic_parameter_hints: GenericParameterHints { @@ -157,7 +157,7 @@ mod tests { } #[track_caller] - fn generic_param_name_hints_const_only(ra_fixture: &str) { + fn generic_param_name_hints_const_only(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config( InlayHintsConfig { generic_parameter_hints: GenericParameterHints { diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs index dd4b3efeecf..1358d3722f8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs @@ -108,7 +108,7 @@ pub(super) fn hints( } let mut label = InlayHintLabel::simple( name, - Some(crate::InlayTooltip::String("moz".into())), + Some(config.lazy_tooltip(|| crate::InlayTooltip::String("moz".into()))), binding_source, ); label.prepend_str("drop("); diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs index 1560df37d0d..ae5b519b43d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs @@ -39,7 +39,9 @@ pub(super) fn hints( range: t.text_range(), kind: InlayKind::Lifetime, label: "'static".into(), - text_edit: Some(TextEdit::insert(t.text_range().start(), "'static ".into())), + text_edit: Some(config.lazy_text_edit(|| { + TextEdit::insert(t.text_range().start(), "'static ".into()) + })), position: InlayHintPosition::After, pad_left: false, pad_right: true, diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs index a03ff6a52b4..a7b066700c5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs +++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs @@ -269,7 +269,7 @@ mod tests { }; #[track_caller] - fn check_params(ra_fixture: &str) { + fn check_params(#[rust_analyzer::rust_fixture] ra_fixture: &str) { check_with_config( InlayHintsConfig { parameter_hints: true, ..DISABLED_CONFIG }, ra_fixture, diff --git a/src/tools/rust-analyzer/crates/ide/src/join_lines.rs b/src/tools/rust-analyzer/crates/ide/src/join_lines.rs index 5192f91a4a6..e4670177ecf 100644 --- a/src/tools/rust-analyzer/crates/ide/src/join_lines.rs +++ b/src/tools/rust-analyzer/crates/ide/src/join_lines.rs @@ -307,7 +307,10 @@ mod tests { use super::*; - fn check_join_lines(ra_fixture_before: &str, ra_fixture_after: &str) { + fn check_join_lines( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, + ) { let config = JoinLinesConfig { join_else_if: true, remove_trailing_comma: true, @@ -333,7 +336,10 @@ mod tests { assert_eq_text!(ra_fixture_after, &actual); } - fn check_join_lines_sel(ra_fixture_before: &str, ra_fixture_after: &str) { + fn check_join_lines_sel( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, + ) { let config = JoinLinesConfig { join_else_if: true, remove_trailing_comma: true, diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs index 6e7c718953c..346e2862b0f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/lib.rs +++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs @@ -48,7 +48,6 @@ mod ssr; mod static_index; mod status; mod syntax_highlighting; -mod syntax_tree; mod test_explorer; mod typing; mod view_crate_graph; @@ -56,6 +55,7 @@ mod view_hir; mod view_item_tree; mod view_memory_layout; mod view_mir; +mod view_syntax_tree; use std::{iter, panic::UnwindSafe}; @@ -120,7 +120,7 @@ pub use ide_assists::{ }; pub use ide_completion::{ CallableSnippets, CompletionConfig, CompletionFieldsToResolve, CompletionItem, - CompletionItemKind, CompletionRelevance, Snippet, SnippetScope, + CompletionItemKind, CompletionItemRefMode, CompletionRelevance, Snippet, SnippetScope, }; pub use ide_db::text_edit::{Indel, TextEdit}; pub use ide_db::{ @@ -329,14 +329,8 @@ impl Analysis { }) } - /// Returns a syntax tree represented as `String`, for debug purposes. - // FIXME: use a better name here. - pub fn syntax_tree( - &self, - file_id: FileId, - text_range: Option<TextRange>, - ) -> Cancellable<String> { - self.with_db(|db| syntax_tree::syntax_tree(db, file_id, text_range)) + pub fn view_syntax_tree(&self, file_id: FileId) -> Cancellable<String> { + self.with_db(|db| view_syntax_tree::view_syntax_tree(db, file_id)) } pub fn view_hir(&self, position: FilePosition) -> Cancellable<String> { @@ -410,17 +404,11 @@ impl Analysis { &self, position: FilePosition, char_typed: char, - chars_to_exclude: Option<String>, ) -> Cancellable<Option<SourceChange>> { // Fast path to not even parse the file. if !typing::TRIGGER_CHARS.contains(char_typed) { return Ok(None); } - if let Some(chars_to_exclude) = chars_to_exclude { - if chars_to_exclude.contains(char_typed) { - return Ok(None); - } - } self.with_db(|db| typing::on_char_typed(db, position, char_typed)) } @@ -588,17 +576,17 @@ impl Analysis { self.with_db(|db| parent_module::parent_module(db, position)) } - /// Returns crates this file belongs too. + /// Returns crates that this file belongs to. pub fn crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> { self.with_db(|db| parent_module::crates_for(db, file_id)) } - /// Returns crates this file belongs too. + /// Returns crates that this file belongs to. pub fn transitive_rev_deps(&self, crate_id: CrateId) -> Cancellable<Vec<CrateId>> { self.with_db(|db| db.crate_graph().transitive_rev_deps(crate_id).collect()) } - /// Returns crates this file *might* belong too. + /// Returns crates that this file *might* belong to. pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> { self.with_db(|db| db.relevant_crates(file_id).iter().copied().collect()) } diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs index 052466725fa..d97c12ebafb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs +++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs @@ -191,7 +191,7 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati MacroKind::ProcMacro => Macro, }, Definition::Field(..) | Definition::TupleField(..) => Field, - Definition::Module(..) => Module, + Definition::Module(..) | Definition::Crate(..) => Module, Definition::Function(it) => { if it.as_assoc_item(db).is_some() { if it.has_self_param(db) { @@ -405,7 +405,7 @@ mod tests { #[allow(dead_code)] #[track_caller] - fn no_moniker(ra_fixture: &str) { + fn no_moniker(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position) = fixture::position(ra_fixture); if let Some(x) = analysis.moniker(position).unwrap() { assert_eq!(x.info.len(), 0, "Moniker found but no moniker expected: {x:?}"); @@ -413,7 +413,12 @@ mod tests { } #[track_caller] - fn check_local_moniker(ra_fixture: &str, identifier: &str, package: &str, kind: MonikerKind) { + fn check_local_moniker( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + identifier: &str, + package: &str, + kind: MonikerKind, + ) { let (analysis, position) = fixture::position(ra_fixture); let x = analysis.moniker(position).unwrap().expect("no moniker found").info; assert_eq!(x.len(), 1); @@ -433,7 +438,12 @@ mod tests { } #[track_caller] - fn check_moniker(ra_fixture: &str, identifier: &str, package: &str, kind: MonikerKind) { + fn check_moniker( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + identifier: &str, + package: &str, + kind: MonikerKind, + ) { let (analysis, position) = fixture::position(ra_fixture); let x = analysis.moniker(position).unwrap().expect("no moniker found").info; assert_eq!(x.len(), 1); diff --git a/src/tools/rust-analyzer/crates/ide/src/move_item.rs b/src/tools/rust-analyzer/crates/ide/src/move_item.rs index a232df2b82b..b0df9257ba1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/move_item.rs +++ b/src/tools/rust-analyzer/crates/ide/src/move_item.rs @@ -180,7 +180,11 @@ mod tests { use crate::Direction; - fn check(ra_fixture: &str, expect: Expect, direction: Direction) { + fn check( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, + direction: Direction, + ) { let (analysis, range) = fixture::range(ra_fixture); let edit = analysis.move_item(range, direction).unwrap().unwrap_or_default(); let mut file = analysis.file_text(range.file_id).unwrap().to_string(); diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs index 9259243db85..d9f80cb53dd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs +++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs @@ -44,13 +44,16 @@ pub struct NavigationTarget { /// /// This range must be contained within [`Self::full_range`]. pub focus_range: Option<TextRange>, + // FIXME: Symbol pub name: SmolStr, pub kind: Option<SymbolKind>, + // FIXME: Symbol pub container_name: Option<SmolStr>, pub description: Option<String>, pub docs: Option<Documentation>, /// In addition to a `name` field, a `NavigationTarget` may also be aliased /// In such cases we want a `NavigationTarget` to be accessible by its alias + // FIXME: Symbol pub alias: Option<SmolStr>, } @@ -191,11 +194,11 @@ impl TryToNav for FileSymbol { NavigationTarget { file_id, name: self.is_alias.then(|| self.def.name(db)).flatten().map_or_else( - || self.name.clone(), + || self.name.as_str().into(), |it| it.display_no_db(edition).to_smolstr(), ), - alias: self.is_alias.then(|| self.name.clone()), - kind: Some(hir::ModuleDefId::from(self.def).into()), + alias: self.is_alias.then(|| self.name.as_str().into()), + kind: Some(self.def.into()), full_range, focus_range, container_name: self.container_name.clone(), @@ -225,6 +228,7 @@ impl TryToNav for Definition { Definition::Local(it) => Some(it.to_nav(db)), Definition::Label(it) => it.try_to_nav(db), Definition::Module(it) => Some(it.to_nav(db)), + Definition::Crate(it) => Some(it.to_nav(db)), Definition::Macro(it) => it.try_to_nav(db), Definition::Field(it) => it.try_to_nav(db), Definition::SelfType(it) => it.try_to_nav(db), @@ -398,6 +402,12 @@ impl ToNav for hir::Module { } } +impl ToNav for hir::Crate { + fn to_nav(&self, db: &RootDatabase) -> UpmappingResult<NavigationTarget> { + self.root_module().to_nav(db) + } +} + impl TryToNav for hir::Impl { fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> { let InFile { file_id, value } = self.source(db)?; diff --git a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs index b51a5cc4f4c..7a0c28d925a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs +++ b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs @@ -70,7 +70,7 @@ mod tests { use crate::fixture; - fn check(ra_fixture: &str) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str) { let (analysis, position, expected) = fixture::annotations(ra_fixture); let navs = analysis.parent_module(position).unwrap(); let navs = navs diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs index 46714df8d69..b1079312d3b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/references.rs +++ b/src/tools/rust-analyzer/crates/ide/src/references.rs @@ -1255,11 +1255,15 @@ impl Foo { ); } - fn check(ra_fixture: &str, expect: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { check_with_scope(ra_fixture, None, expect) } - fn check_with_scope(ra_fixture: &str, search_scope: Option<SearchScope>, expect: Expect) { + fn check_with_scope( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + search_scope: Option<SearchScope>, + expect: Expect, + ) { let (analysis, pos) = fixture::position(ra_fixture); let refs = analysis.find_all_refs(pos, search_scope).unwrap().unwrap(); diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs index 11bbd99110b..ba739df3092 100644 --- a/src/tools/rust-analyzer/crates/ide/src/rename.rs +++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs @@ -456,7 +456,11 @@ mod tests { use super::{RangeInfo, RenameError}; #[track_caller] - fn check(new_name: &str, ra_fixture_before: &str, ra_fixture_after: &str) { + fn check( + new_name: &str, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, + ) { let ra_fixture_after = &trim_indent(ra_fixture_after); let (analysis, position) = fixture::position(ra_fixture_before); if !ra_fixture_after.starts_with("error: ") { @@ -494,14 +498,22 @@ mod tests { }; } - fn check_expect(new_name: &str, ra_fixture: &str, expect: Expect) { + fn check_expect( + new_name: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, + ) { let (analysis, position) = fixture::position(ra_fixture); let source_change = analysis.rename(position, new_name).unwrap().expect("Expect returned a RenameError"); expect.assert_eq(&filter_expect(source_change)) } - fn check_expect_will_rename_file(new_name: &str, ra_fixture: &str, expect: Expect) { + fn check_expect_will_rename_file( + new_name: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, + ) { let (analysis, position) = fixture::position(ra_fixture); let source_change = analysis .will_rename_file(position.file_id, new_name) @@ -510,7 +522,7 @@ mod tests { expect.assert_eq(&filter_expect(source_change)) } - fn check_prepare(ra_fixture: &str, expect: Expect) { + fn check_prepare(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let result = analysis .prepare_rename(position) diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs index 3e39c750b13..32edacee51c 100644 --- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs +++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs @@ -748,7 +748,7 @@ mod tests { use crate::fixture; - fn check(ra_fixture: &str, expect: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let result = analysis .runnables(position.file_id) @@ -769,7 +769,7 @@ mod tests { expect.assert_debug_eq(&result); } - fn check_tests(ra_fixture: &str, expect: Expect) { + fn check_tests(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let (analysis, position) = fixture::position(ra_fixture); let tests = analysis.related_tests(position, None).unwrap(); let navigation_targets = tests.into_iter().map(|runnable| runnable.nav).collect::<Vec<_>>(); diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs index 84ccadc8c4e..f8c60418eb0 100644 --- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs +++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs @@ -692,7 +692,9 @@ mod tests { use crate::RootDatabase; /// Creates analysis from a multi-file fixture, returns positions marked with $0. - pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { + pub(crate) fn position( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + ) -> (RootDatabase, FilePosition) { let change_fixture = ChangeFixture::parse(ra_fixture); let mut database = RootDatabase::default(); database.apply_change(change_fixture.change); @@ -703,7 +705,7 @@ mod tests { } #[track_caller] - fn check(ra_fixture: &str, expect: Expect) { + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let fixture = format!( r#" //- minicore: sized, fn diff --git a/src/tools/rust-analyzer/crates/ide/src/ssr.rs b/src/tools/rust-analyzer/crates/ide/src/ssr.rs index 6def28e0b74..77a011cac19 100644 --- a/src/tools/rust-analyzer/crates/ide/src/ssr.rs +++ b/src/tools/rust-analyzer/crates/ide/src/ssr.rs @@ -67,7 +67,10 @@ mod tests { use super::ssr_assists; - fn get_assists(ra_fixture: &str, resolve: AssistResolveStrategy) -> Vec<Assist> { + fn get_assists( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + resolve: AssistResolveStrategy, + ) -> Vec<Assist> { let (mut db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture); let mut local_roots = FxHashSet::default(); local_roots.insert(test_fixture::WORKSPACE); diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs index 700e166b238..8050a38b3ca 100644 --- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs +++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs @@ -138,6 +138,7 @@ impl StaticIndex<'_> { render_colons: true, discriminant_hints: crate::DiscriminantHints::Fieldless, type_hints: true, + sized_bound: false, parameter_hints: true, generic_parameter_hints: crate::GenericParameterHints { type_hints: false, @@ -290,7 +291,10 @@ mod tests { use super::VendoredLibrariesConfig; - fn check_all_ranges(ra_fixture: &str, vendored_libs_config: VendoredLibrariesConfig<'_>) { + fn check_all_ranges( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + vendored_libs_config: VendoredLibrariesConfig<'_>, + ) { let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture); let s = StaticIndex::compute(&analysis, vendored_libs_config); let mut range_set: FxHashSet<_> = ranges.iter().map(|it| it.0).collect(); @@ -309,7 +313,10 @@ mod tests { } #[track_caller] - fn check_definitions(ra_fixture: &str, vendored_libs_config: VendoredLibrariesConfig<'_>) { + fn check_definitions( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + vendored_libs_config: VendoredLibrariesConfig<'_>, + ) { let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture); let s = StaticIndex::compute(&analysis, vendored_libs_config); let mut range_set: FxHashSet<_> = ranges.iter().map(|it| it.0).collect(); diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs index 4f3d5d9d00c..22a2fe4e9eb 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs @@ -386,6 +386,9 @@ pub(super) fn highlight_def( Definition::Field(_) | Definition::TupleField(_) => { Highlight::new(HlTag::Symbol(SymbolKind::Field)) } + Definition::Crate(_) => { + Highlight::new(HlTag::Symbol(SymbolKind::Module)) | HlMod::CrateRoot + } Definition::Module(module) => { let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Module)); if module.is_crate_root() { diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs index 0a157c157c3..1be90ad6a1e 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs @@ -28,7 +28,14 @@ pub(super) fn ra_fixture( expanded: &ast::String, ) -> Option<()> { let active_parameter = ActiveParameter::at_token(sema, expanded.syntax().clone())?; - if !active_parameter.ident().is_some_and(|name| name.text().starts_with("ra_fixture")) { + let has_rust_fixture_attr = active_parameter.attrs().is_some_and(|attrs| { + attrs.filter_map(|attr| attr.as_simple_path()).any(|path| { + path.segments() + .zip(["rust_analyzer", "rust_fixture"]) + .all(|(seg, name)| seg.name_ref().map_or(false, |nr| nr.text() == name)) + }) + }); + if !has_rust_fixture_attr { return None; } let value = literal.value().ok()?; @@ -287,7 +294,9 @@ fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::Stri fn module_def_to_hl_tag(def: Definition) -> HlTag { let symbol = match def { - Definition::Module(_) | Definition::ExternCrateDecl(_) => SymbolKind::Module, + Definition::Module(_) | Definition::Crate(_) | Definition::ExternCrateDecl(_) => { + SymbolKind::Module + } Definition::Function(_) => SymbolKind::Function, Definition::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct, Definition::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum, diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html index cad5a8b593f..485d44f97e1 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html @@ -46,7 +46,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> <pre><code><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">allow</span><span class="parenthesis attribute">(</span><span class="none attribute">dead_code</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span> -<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute library">rustfmt</span><span class="operator attribute">::</span><span class="tool_module attribute library">skip</span><span class="attribute_bracket attribute">]</span> +<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute">rustfmt</span><span class="operator attribute">::</span><span class="tool_module attribute">skip</span><span class="attribute_bracket attribute">]</span> <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">identity</span><span class="attribute_bracket attribute">]</span> <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Default</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span> <span class="comment documentation">/// This is a doc comment</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html index edd9639768a..c6eab90e42b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html @@ -45,7 +45,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> -<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">foo</span> <span class="brace">{</span> +<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">foo</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span>foo<span class="colon">:</span>ident<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="keyword">mod</span> y <span class="brace">{</span> <span class="keyword">pub</span> <span class="keyword">struct</span> <span class="punctuation">$</span>foo<span class="semicolon">;</span> @@ -53,9 +53,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="brace">}</span><span class="semicolon">;</span> <span class="brace">}</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> - <span class="macro">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Foo</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Foo</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="keyword">mod</span> <span class="module declaration">module</span> <span class="brace">{</span> - <span class="macro">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="module">y</span><span class="operator">::</span><span class="struct public">Bar</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span> <span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle"><</span><span class="keyword">const</span> <span class="const_param const declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">></span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html index 05289cfe3fe..96cdb532dd5 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html @@ -45,7 +45,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> -<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span> +<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">id</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span> <span class="brace">}</span><span class="semicolon">;</span> @@ -57,7 +57,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword const">const</span> <span class="brace">{</span> <span class="keyword">const</span> <span class="punctuation">|</span><span class="punctuation">|</span> <span class="brace">{</span><span class="brace">}</span> <span class="brace">}</span> - <span class="macro">id</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span> + <span class="macro public">id</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span> <span class="constant const macro">CONST_ITEM</span><span class="semicolon macro">;</span> <span class="const_param const macro">CONST_PARAM</span><span class="semicolon macro">;</span> <span class="keyword const macro">const</span> <span class="brace macro">{</span> @@ -78,7 +78,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function associated const declaration static trait">assoc_const_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">unsafe_deref</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">unsafe_deref</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span> <span class="brace">}</span><span class="semicolon">;</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html index aa9d23250c1..5ff96ae2a74 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html @@ -147,10 +147,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="brace">}</span> <span class="comment documentation">/// ```</span> -<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="operator injected">></span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr </span><span class="brace injected">}</span><span class="brace injected">}</span> -<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected">noop</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="numeric_literal injected macro">1</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span> +<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected public">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="operator injected">></span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr </span><span class="brace injected">}</span><span class="brace injected">}</span> +<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected public">noop</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="numeric_literal injected macro">1</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span> <span class="comment documentation">/// ```</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">noop</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="punctuation">$</span>expr <span class="brace">}</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html index 7820e4e5a5f..fe5f5ab6a9a 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html @@ -45,7 +45,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> -<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root public">self</span> <span class="keyword">as</span> <span class="module crate_root declaration">this</span><span class="semicolon">;</span> +<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root">self</span> <span class="keyword">as</span> <span class="module crate_root declaration">this</span><span class="semicolon">;</span> <span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span> <span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root declaration">abc</span><span class="semicolon">;</span> <span class="keyword">extern</span> <span class="keyword">crate</span> <span class="unresolved_reference">unresolved</span> <span class="keyword">as</span> <span class="module crate_root declaration">definitely_unresolved</span><span class="semicolon">;</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html index 6c3fbcfcf41..5fbed35192b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html @@ -45,7 +45,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> -<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> +<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute">rust_analyzer</span><span class="operator attribute">::</span><span class="tool_module attribute">rust_fixture</span><span class="attribute_bracket attribute">]</span> <span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span><span class="none injected"> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html index 361dcd1bc37..06817af1b1f 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html @@ -46,8 +46,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> - <span class="macro">template</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">template</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">template</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">template</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="brace">}</span> <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">issue_18089</span><span class="attribute_bracket attribute">]</span> -<span class="keyword">fn</span> <span class="macro declaration">template</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span></code></pre> \ No newline at end of file +<span class="keyword">fn</span> <span class="macro declaration public">template</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span></code></pre> \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html index c2bf94fd9b6..2d3407dbcda 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html @@ -53,22 +53,22 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword">use</span> <span class="keyword crate_root public">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span><span class="brace">}</span> <span class="brace">}</span> <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span> <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// edition dependent</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">try</span> <span class="none macro">async</span> <span class="none macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">try</span> <span class="none macro">async</span> <span class="none macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// edition and context dependent</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// builtin custom syntax</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// contextual</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// reserved</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre> \ No newline at end of file +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre> \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html index a30d16d5327..f8eb5d068a8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html @@ -53,22 +53,22 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword">use</span> <span class="keyword crate_root public">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span><span class="brace">}</span> <span class="brace">}</span> <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span> <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// edition dependent</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// edition and context dependent</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// builtin custom syntax</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// contextual</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// reserved</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre> \ No newline at end of file +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre> \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html index a30d16d5327..f8eb5d068a8 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html @@ -53,22 +53,22 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword">use</span> <span class="keyword crate_root public">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span><span class="brace">}</span> <span class="brace">}</span> <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span> <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// edition dependent</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// edition and context dependent</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// builtin custom syntax</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// contextual</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// reserved</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre> \ No newline at end of file +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre> \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html index b82a3f9f819..fca84017069 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html @@ -53,22 +53,22 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword">use</span> <span class="keyword crate_root public">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span><span class="brace">}</span> <span class="brace">}</span> <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span> <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// edition dependent</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="keyword macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="keyword macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// edition and context dependent</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// builtin custom syntax</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// contextual</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// reserved</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> -<span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre> \ No newline at end of file +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> +<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre> \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html index 06673d1a73c..f640a5e6ca7 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html @@ -53,34 +53,34 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="comma macro proc_macro">,</span><span class="builtin_type macro proc_macro">i32</span> <span class="colon macro proc_macro">:</span><span class="field declaration macro proc_macro public">y</span> <span class="keyword macro proc_macro">pub</span> <span class="brace macro proc_macro">}</span> <span class="struct declaration macro proc_macro">Foo</span> <span class="keyword macro proc_macro">struct</span> <span class="brace macro proc_macro">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">def_fn</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">def_fn</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="brace">}</span> <span class="brace">}</span> -<span class="macro">def_fn</span><span class="macro_bang">!</span> <span class="brace macro">{</span> +<span class="macro public">def_fn</span><span class="macro_bang">!</span> <span class="brace macro">{</span> <span class="keyword macro">fn</span> <span class="function declaration macro">bar</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="operator macro">-</span><span class="operator macro">></span> <span class="builtin_type macro">u32</span> <span class="brace macro">{</span> <span class="numeric_literal macro">100</span> <span class="brace macro">}</span> <span class="brace macro">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">dont_color_me_braces</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">dont_color_me_braces</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span><span class="numeric_literal">0</span><span class="brace">}</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">noop</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="punctuation">$</span>expr <span class="brace">}</span> <span class="brace">}</span> <span class="comment documentation">/// textually shadow previous definition</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">noop</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="punctuation">$</span>expr <span class="brace">}</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">keyword_frag</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span> <span class="brace">}</span> @@ -94,7 +94,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="brace">}</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">id</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span> <span class="brace">}</span><span class="semicolon">;</span> @@ -106,10 +106,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> <span class="keyword">struct</span> <span class="struct declaration">TestLocal</span><span class="semicolon">;</span> <span class="comment">// regression test, TestLocal here used to not resolve</span> - <span class="keyword">let</span> <span class="punctuation">_</span><span class="colon">:</span> <span class="struct">S</span><span class="angle"><</span><span class="macro">id</span><span class="macro_bang">!</span><span class="bracket macro">[</span><span class="struct macro">TestLocal</span><span class="bracket macro">]</span><span class="angle">></span><span class="semicolon">;</span> + <span class="keyword">let</span> <span class="punctuation">_</span><span class="colon">:</span> <span class="struct">S</span><span class="angle"><</span><span class="macro public">id</span><span class="macro_bang">!</span><span class="bracket macro">[</span><span class="struct macro">TestLocal</span><span class="bracket macro">]</span><span class="angle">></span><span class="semicolon">;</span> <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">92</span><span class="comma macro">,</span><span class="parenthesis macro">)</span><span class="operator macro">.</span><span class="field library macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">dont_color_me_braces</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">noop</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro macro">noop</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">dont_color_me_braces</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">noop</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro macro public">noop</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="brace">}</span> </code></pre> \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 1385ae0510a..0a7e273950d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -45,14 +45,14 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> -<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">println</span> <span class="brace">{</span> +<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">println</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="parenthesis">(</span><span class="brace">{</span> <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">}</span><span class="parenthesis">)</span> <span class="brace">}</span> <span class="keyword">mod</span> <span class="module declaration">panic</span> <span class="brace">{</span> - <span class="keyword">pub</span> <span class="keyword">macro</span> <span class="macro declaration">panic_2015</span> <span class="brace">{</span> + <span class="keyword">pub</span> <span class="keyword">macro</span> <span class="macro declaration public">panic_2015</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">></span> <span class="parenthesis">(</span> panic<span class="parenthesis">(</span><span class="string_literal">"explicit panic"</span><span class="parenthesis">)</span> <span class="parenthesis">)</span><span class="comma">,</span> @@ -73,12 +73,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="brace">}</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">toho</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">toho</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented"</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented: {}"</span><span class="comma">,</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">reuse_twice</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">reuse_twice</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="colon">:</span>literal<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span><span class="brace">{</span>stringify<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="parenthesis">)</span><span class="semicolon">;</span> format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>literal<span class="parenthesis">)</span><span class="brace">}</span><span class="brace">}</span><span class="semicolon">;</span> <span class="brace">}</span> @@ -95,74 +95,74 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="byte_literal">b'</span><span class="escape_sequence">\xFF</span><span class="byte_literal">'</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "Hello"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "Hello, world!"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "The number is 1"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "(3, 4)"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "4"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "1 2"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">42</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "0042" with leading zerosV</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "2 1 1 2"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "test"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "2 1"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="variable declaration macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="variable declaration macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "a 3 b"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "{2}"</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier"><</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier"><</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">></span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">-</span><span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="variable declaration macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">></span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "Hello"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "Hello, world!"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "The number is 1"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "(3, 4)"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "4"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "1 2"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">42</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "0042" with leading zerosV</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "2 1 1 2"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "test"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "2 1"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="variable declaration macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="variable declaration macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "a 3 b"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// => "{2}"</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier"><</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier"><</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">></span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">-</span><span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="variable declaration macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">></span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{}"</span> <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{{}}"</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="comment">// escape sequences</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="invalid_escape_sequence">\xFF</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// invalid non-UTF8 escape sequences</span> <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">b"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\xFF</span><span class="invalid_escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, invalid unicodes</span> <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">c"</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\xFF</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, valid unicodes</span> <span class="keyword">let</span> <span class="variable declaration reference">backslash</span> <span class="operator">=</span> <span class="string_literal">r"\\"</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span> <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span> @@ -175,6 +175,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword const">const</span> <span class="constant const declaration">CONSTANT</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span> <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">m</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro public">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> <span class="brace">}</span></code></pre> \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index 4e69c82f3da..d9beac30898 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html @@ -45,12 +45,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; } .unresolved_reference { color: #FC5555; text-decoration: wavy underline; } </style> -<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span> +<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">id</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span> <span class="brace">}</span><span class="semicolon">;</span> <span class="brace">}</span> -<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">unsafe_deref</span> <span class="brace">{</span> +<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">unsafe_deref</span> <span class="brace">{</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">></span> <span class="brace">{</span> <span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span> <span class="brace">}</span><span class="semicolon">;</span> @@ -92,13 +92,13 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="semicolon">;</span> <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field">b</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span> - <span class="macro">id</span><span class="macro_bang">!</span> <span class="brace macro">{</span> - <span class="keyword macro unsafe">unsafe</span> <span class="brace macro">{</span> <span class="macro macro unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span> + <span class="macro public">id</span><span class="macro_bang">!</span> <span class="brace macro">{</span> + <span class="keyword macro unsafe">unsafe</span> <span class="brace macro">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span> <span class="brace macro">}</span><span class="semicolon">;</span> <span class="keyword unsafe">unsafe</span> <span class="brace">{</span> - <span class="macro unsafe">unsafe_deref</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> - <span class="macro unsafe">id</span><span class="macro_bang">!</span> <span class="brace macro">{</span> <span class="macro macro unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span><span class="semicolon">;</span> + <span class="macro public unsafe">unsafe_deref</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span> + <span class="macro public unsafe">id</span><span class="macro_bang">!</span> <span class="brace macro">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span><span class="semicolon">;</span> <span class="comment">// unsafe fn and method calls</span> <span class="function unsafe">unsafe_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs index a20147add36..af52b33de64 100644 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs +++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs @@ -990,7 +990,7 @@ impl t for foo { fn test_injection() { check_highlighting( r##" -fn fixture(ra_fixture: &str) {} +fn fixture(#[rust_analyzer::rust_fixture] ra_fixture: &str) {} fn main() { fixture(r#" @@ -1188,7 +1188,11 @@ fn foo(x: &fn(&dyn Trait)) {} /// Highlights the code given by the `ra_fixture` argument, renders the /// result as HTML, and compares it with the HTML file given as `snapshot`. /// Note that the `snapshot` file is overwritten by the rendered HTML. -fn check_highlighting(ra_fixture: &str, expect: ExpectFile, rainbow: bool) { +fn check_highlighting( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: ExpectFile, + rainbow: bool, +) { let (analysis, file_id) = fixture::file(ra_fixture.trim()); let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap(); expect.assert_eq(actual_html) diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_tree.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_tree.rs deleted file mode 100644 index e241cb82bd5..00000000000 --- a/src/tools/rust-analyzer/crates/ide/src/syntax_tree.rs +++ /dev/null @@ -1,338 +0,0 @@ -use hir::Semantics; -use ide_db::{FileId, RootDatabase}; -use syntax::{ - AstNode, NodeOrToken, SourceFile, SyntaxKind::STRING, SyntaxToken, TextRange, TextSize, -}; - -// Feature: Show Syntax Tree -// -// Shows the parse tree of the current file. It exists mostly for debugging -// rust-analyzer itself. -// -// |=== -// | Editor | Action Name -// -// | VS Code | **rust-analyzer: Show Syntax Tree** -// |=== -// image::https://user-images.githubusercontent.com/48062697/113065586-068bdb80-91b1-11eb-9507-fee67f9f45a0.gif[] -pub(crate) fn syntax_tree( - db: &RootDatabase, - file_id: FileId, - text_range: Option<TextRange>, -) -> String { - let sema = Semantics::new(db); - let parse = sema.parse_guess_edition(file_id); - if let Some(text_range) = text_range { - let node = match parse.syntax().covering_element(text_range) { - NodeOrToken::Node(node) => node, - NodeOrToken::Token(token) => { - if let Some(tree) = syntax_tree_for_string(&token, text_range) { - return tree; - } - token.parent().unwrap() - } - }; - - format!("{node:#?}") - } else { - format!("{:#?}", parse.syntax()) - } -} - -/// Attempts parsing the selected contents of a string literal -/// as rust syntax and returns its syntax tree -fn syntax_tree_for_string(token: &SyntaxToken, text_range: TextRange) -> Option<String> { - // When the range is inside a string - // we'll attempt parsing it as rust syntax - // to provide the syntax tree of the contents of the string - match token.kind() { - STRING => syntax_tree_for_token(token, text_range), - _ => None, - } -} - -fn syntax_tree_for_token(node: &SyntaxToken, text_range: TextRange) -> Option<String> { - // Range of the full node - let node_range = node.text_range(); - let text = node.text().to_owned(); - - // We start at some point inside the node - // Either we have selected the whole string - // or our selection is inside it - let start = text_range.start() - node_range.start(); - - // how many characters we have selected - let len = text_range.len(); - - let node_len = node_range.len(); - - // We want to cap our length - let len = len.min(node_len); - - // Ensure our slice is inside the actual string - let end = - if start + len < TextSize::of(&text) { start + len } else { TextSize::of(&text) - start }; - - let text = &text[TextRange::new(start, end)]; - - // Remove possible extra string quotes from the start - // and the end of the string - let text = text - .trim_start_matches('r') - .trim_start_matches('#') - .trim_start_matches('"') - .trim_end_matches('#') - .trim_end_matches('"') - .trim() - // Remove custom markers - .replace("$0", ""); - - let parsed = SourceFile::parse(&text, span::Edition::CURRENT_FIXME); - - // If the "file" parsed without errors, - // return its syntax - if parsed.errors().is_empty() { - return Some(format!("{:#?}", parsed.tree().syntax())); - } - - None -} - -#[cfg(test)] -mod tests { - use expect_test::expect; - - use crate::fixture; - - fn check(ra_fixture: &str, expect: expect_test::Expect) { - let (analysis, file_id) = fixture::file(ra_fixture); - let syn = analysis.syntax_tree(file_id, None).unwrap(); - expect.assert_eq(&syn) - } - fn check_range(ra_fixture: &str, expect: expect_test::Expect) { - let (analysis, frange) = fixture::range(ra_fixture); - let syn = analysis.syntax_tree(frange.file_id, Some(frange.range)).unwrap(); - expect.assert_eq(&syn) - } - - #[test] - fn test_syntax_tree_without_range() { - // Basic syntax - check( - r#"fn foo() {}"#, - expect![[r#" - SOURCE_FILE@0..11 - FN@0..11 - FN_KW@0..2 "fn" - WHITESPACE@2..3 " " - NAME@3..6 - IDENT@3..6 "foo" - PARAM_LIST@6..8 - L_PAREN@6..7 "(" - R_PAREN@7..8 ")" - WHITESPACE@8..9 " " - BLOCK_EXPR@9..11 - STMT_LIST@9..11 - L_CURLY@9..10 "{" - R_CURLY@10..11 "}" - "#]], - ); - - check( - r#" -fn test() { - assert!(" - fn foo() { - } - ", ""); -}"#, - expect![[r#" - SOURCE_FILE@0..60 - FN@0..60 - FN_KW@0..2 "fn" - WHITESPACE@2..3 " " - NAME@3..7 - IDENT@3..7 "test" - PARAM_LIST@7..9 - L_PAREN@7..8 "(" - R_PAREN@8..9 ")" - WHITESPACE@9..10 " " - BLOCK_EXPR@10..60 - STMT_LIST@10..60 - L_CURLY@10..11 "{" - WHITESPACE@11..16 "\n " - EXPR_STMT@16..58 - MACRO_EXPR@16..57 - MACRO_CALL@16..57 - PATH@16..22 - PATH_SEGMENT@16..22 - NAME_REF@16..22 - IDENT@16..22 "assert" - BANG@22..23 "!" - TOKEN_TREE@23..57 - L_PAREN@23..24 "(" - STRING@24..52 "\"\n fn foo() {\n ..." - COMMA@52..53 "," - WHITESPACE@53..54 " " - STRING@54..56 "\"\"" - R_PAREN@56..57 ")" - SEMICOLON@57..58 ";" - WHITESPACE@58..59 "\n" - R_CURLY@59..60 "}" - "#]], - ) - } - - #[test] - fn test_syntax_tree_with_range() { - check_range( - r#"$0fn foo() {}$0"#, - expect![[r#" - FN@0..11 - FN_KW@0..2 "fn" - WHITESPACE@2..3 " " - NAME@3..6 - IDENT@3..6 "foo" - PARAM_LIST@6..8 - L_PAREN@6..7 "(" - R_PAREN@7..8 ")" - WHITESPACE@8..9 " " - BLOCK_EXPR@9..11 - STMT_LIST@9..11 - L_CURLY@9..10 "{" - R_CURLY@10..11 "}" - "#]], - ); - - check_range( - r#" -fn test() { - $0assert!(" - fn foo() { - } - ", "");$0 -}"#, - expect![[r#" - EXPR_STMT@16..58 - MACRO_EXPR@16..57 - MACRO_CALL@16..57 - PATH@16..22 - PATH_SEGMENT@16..22 - NAME_REF@16..22 - IDENT@16..22 "assert" - BANG@22..23 "!" - TOKEN_TREE@23..57 - L_PAREN@23..24 "(" - STRING@24..52 "\"\n fn foo() {\n ..." - COMMA@52..53 "," - WHITESPACE@53..54 " " - STRING@54..56 "\"\"" - R_PAREN@56..57 ")" - SEMICOLON@57..58 ";" - "#]], - ); - } - - #[test] - fn test_syntax_tree_inside_string() { - check_range( - r#"fn test() { - assert!(" -$0fn foo() { -}$0 -fn bar() { -} - ", ""); -}"#, - expect![[r#" - SOURCE_FILE@0..12 - FN@0..12 - FN_KW@0..2 "fn" - WHITESPACE@2..3 " " - NAME@3..6 - IDENT@3..6 "foo" - PARAM_LIST@6..8 - L_PAREN@6..7 "(" - R_PAREN@7..8 ")" - WHITESPACE@8..9 " " - BLOCK_EXPR@9..12 - STMT_LIST@9..12 - L_CURLY@9..10 "{" - WHITESPACE@10..11 "\n" - R_CURLY@11..12 "}" - "#]], - ); - - // With a raw string - check_range( - r###"fn test() { - assert!(r#" -$0fn foo() { -}$0 -fn bar() { -} - "#, ""); -}"###, - expect![[r#" - SOURCE_FILE@0..12 - FN@0..12 - FN_KW@0..2 "fn" - WHITESPACE@2..3 " " - NAME@3..6 - IDENT@3..6 "foo" - PARAM_LIST@6..8 - L_PAREN@6..7 "(" - R_PAREN@7..8 ")" - WHITESPACE@8..9 " " - BLOCK_EXPR@9..12 - STMT_LIST@9..12 - L_CURLY@9..10 "{" - WHITESPACE@10..11 "\n" - R_CURLY@11..12 "}" - "#]], - ); - - // With a raw string - check_range( - r###"fn test() { - assert!(r$0#" -fn foo() { -} -fn bar() { -}"$0#, ""); -}"###, - expect![[r#" - SOURCE_FILE@0..25 - FN@0..12 - FN_KW@0..2 "fn" - WHITESPACE@2..3 " " - NAME@3..6 - IDENT@3..6 "foo" - PARAM_LIST@6..8 - L_PAREN@6..7 "(" - R_PAREN@7..8 ")" - WHITESPACE@8..9 " " - BLOCK_EXPR@9..12 - STMT_LIST@9..12 - L_CURLY@9..10 "{" - WHITESPACE@10..11 "\n" - R_CURLY@11..12 "}" - WHITESPACE@12..13 "\n" - FN@13..25 - FN_KW@13..15 "fn" - WHITESPACE@15..16 " " - NAME@16..19 - IDENT@16..19 "bar" - PARAM_LIST@19..21 - L_PAREN@19..20 "(" - R_PAREN@20..21 ")" - WHITESPACE@21..22 " " - BLOCK_EXPR@22..25 - STMT_LIST@22..25 - L_CURLY@22..23 "{" - WHITESPACE@23..24 "\n" - R_CURLY@24..25 "}" - "#]], - ); - } -} diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs index 8998934e0e8..47d75f1c957 100644 --- a/src/tools/rust-analyzer/crates/ide/src/typing.rs +++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs @@ -436,14 +436,18 @@ mod tests { }) } - fn type_char(char_typed: char, ra_fixture_before: &str, ra_fixture_after: &str) { + fn type_char( + char_typed: char, + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, + ) { let actual = do_type_char(char_typed, ra_fixture_before) .unwrap_or_else(|| panic!("typing `{char_typed}` did nothing")); assert_eq_text!(ra_fixture_after, &actual); } - fn type_char_noop(char_typed: char, ra_fixture_before: &str) { + fn type_char_noop(char_typed: char, #[rust_analyzer::rust_fixture] ra_fixture_before: &str) { let file_change = do_type_char(char_typed, ra_fixture_before); assert_eq!(file_change, None) } @@ -889,7 +893,7 @@ fn main() { type_char_noop( '{', r##" -fn check_with(ra_fixture: &str, expect: Expect) { +fn check_with(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let base = r#" enum E { T(), R$0, C } use self::E::X; @@ -1191,7 +1195,7 @@ fn f(n: a<>b::<d>::c) {} type_char_noop( '(', r##" -fn check_with(ra_fixture: &str, expect: Expect) { +fn check_with(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { let base = r#" enum E { T(), R$0, C } use self::E::X; diff --git a/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs b/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs index 773e352220e..e249c38c73d 100644 --- a/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs +++ b/src/tools/rust-analyzer/crates/ide/src/typing/on_enter.rs @@ -208,7 +208,10 @@ mod tests { Some(actual) } - fn do_check(ra_fixture_before: &str, ra_fixture_after: &str) { + fn do_check( + #[rust_analyzer::rust_fixture] ra_fixture_before: &str, + #[rust_analyzer::rust_fixture] ra_fixture_after: &str, + ) { let ra_fixture_after = &trim_indent(ra_fixture_after); let actual = apply_on_enter(ra_fixture_before).unwrap(); assert_eq_text!(ra_fixture_after, &actual); diff --git a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs index 830c39e21ea..ff74e05e943 100644 --- a/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs +++ b/src/tools/rust-analyzer/crates/ide/src/view_memory_layout.rs @@ -220,7 +220,9 @@ mod tests { use crate::fixture; use expect_test::expect; - fn make_memory_layout(ra_fixture: &str) -> Option<RecursiveMemoryLayout> { + fn make_memory_layout( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + ) -> Option<RecursiveMemoryLayout> { let (analysis, position, _) = fixture::annotations(ra_fixture); view_memory_layout(&analysis.db, position) diff --git a/src/tools/rust-analyzer/crates/ide/src/view_syntax_tree.rs b/src/tools/rust-analyzer/crates/ide/src/view_syntax_tree.rs new file mode 100644 index 00000000000..218ee15a7dd --- /dev/null +++ b/src/tools/rust-analyzer/crates/ide/src/view_syntax_tree.rs @@ -0,0 +1,226 @@ +use hir::Semantics; +use ide_db::{FileId, RootDatabase}; +use span::TextRange; +use stdx::format_to; +use syntax::{ + ast::{self, IsString}, + AstNode, AstToken, NodeOrToken, SourceFile, SyntaxNode, SyntaxToken, WalkEvent, +}; + +// Feature: Show Syntax Tree +// +// Shows a tree view with the syntax tree of the current file +// +// |=== +// | Editor | Panel Name +// +// | VS Code | **Rust Syntax Tree** +// |=== +pub(crate) fn view_syntax_tree(db: &RootDatabase, file_id: FileId) -> String { + let sema = Semantics::new(db); + let parse = sema.parse_guess_edition(file_id); + syntax_node_to_json(parse.syntax(), None) +} + +fn syntax_node_to_json(node: &SyntaxNode, ctx: Option<InStringCtx>) -> String { + let mut result = String::new(); + for event in node.preorder_with_tokens() { + match event { + WalkEvent::Enter(it) => { + let kind = it.kind(); + let (text_range, inner_range_str) = match &ctx { + Some(ctx) => { + let inner_start: u32 = it.text_range().start().into(); + let inner_end: u32 = it.text_range().end().into(); + + let mut true_start = inner_start + ctx.offset; + let mut true_end = inner_end + ctx.offset; + for pos in &ctx.marker_positions { + if *pos >= inner_end { + break; + } + + // We conditionally add to true_start in case + // the marker is between the start and end. + true_start += 2 * (*pos < inner_start) as u32; + true_end += 2; + } + + let true_range = TextRange::new(true_start.into(), true_end.into()); + + ( + true_range, + format!( + r#","istart":{:?},"iend":{:?}"#, + it.text_range().start(), + it.text_range().end() + ), + ) + } + None => (it.text_range(), "".to_owned()), + }; + let start = text_range.start(); + let end = text_range.end(); + + match it { + NodeOrToken::Node(_) => { + format_to!( + result, + r#"{{"type":"Node","kind":"{kind:?}","start":{start:?},"end":{end:?}{inner_range_str},"children":["# + ); + } + NodeOrToken::Token(token) => { + let comma = if token.next_sibling_or_token().is_some() { "," } else { "" }; + match parse_rust_string(token) { + Some(parsed) => { + format_to!( + result, + r#"{{"type":"Node","kind":"{kind:?}","start":{start:?},"end":{end:?}{inner_range_str},"children":[{parsed}]}}{comma}"# + ); + } + None => format_to!( + result, + r#"{{"type":"Token","kind":"{kind:?}","start":{start:?},"end":{end:?}{inner_range_str}}}{comma}"# + ), + } + } + } + } + WalkEvent::Leave(it) => match it { + NodeOrToken::Node(node) => { + let comma = if node.next_sibling_or_token().is_some() { "," } else { "" }; + format_to!(result, "]}}{comma}") + } + NodeOrToken::Token(_) => (), + }, + } + } + + result +} + +fn parse_rust_string(token: SyntaxToken) -> Option<String> { + let string_node = ast::String::cast(token)?; + let text = string_node.value().ok()?; + + let mut trim_result = String::new(); + let mut marker_positions = Vec::new(); + let mut skipped = 0; + let mut last_end = 0; + for (start, part) in text.match_indices("$0") { + marker_positions.push((start - skipped) as u32); + trim_result.push_str(&text[last_end..start]); + skipped += part.len(); + last_end = start + part.len(); + } + trim_result.push_str(&text[last_end..text.len()]); + + let parsed = SourceFile::parse(&trim_result, span::Edition::CURRENT); + + if !parsed.errors().is_empty() { + return None; + } + + let node: &SyntaxNode = &parsed.syntax_node(); + + if node.children().count() == 0 { + // C'mon, you should have at least one node other than SOURCE_FILE + return None; + } + + Some(syntax_node_to_json( + node, + Some(InStringCtx { + offset: string_node.text_range_between_quotes()?.start().into(), + marker_positions, + }), + )) +} + +struct InStringCtx { + offset: u32, + marker_positions: Vec<u32>, +} + +#[cfg(test)] +mod tests { + use expect_test::expect; + + use crate::fixture; + + fn check(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: expect_test::Expect) { + let (analysis, file_id) = fixture::file(ra_fixture); + let syn = analysis.view_syntax_tree(file_id).unwrap(); + expect.assert_eq(&syn) + } + + #[test] + fn view_syntax_tree() { + // Basic syntax + check( + r#"fn foo() {}"#, + expect![[ + r#"{"type":"Node","kind":"SOURCE_FILE","start":0,"end":11,"children":[{"type":"Node","kind":"FN","start":0,"end":11,"children":[{"type":"Token","kind":"FN_KW","start":0,"end":2},{"type":"Token","kind":"WHITESPACE","start":2,"end":3},{"type":"Node","kind":"NAME","start":3,"end":6,"children":[{"type":"Token","kind":"IDENT","start":3,"end":6}]},{"type":"Node","kind":"PARAM_LIST","start":6,"end":8,"children":[{"type":"Token","kind":"L_PAREN","start":6,"end":7},{"type":"Token","kind":"R_PAREN","start":7,"end":8}]},{"type":"Token","kind":"WHITESPACE","start":8,"end":9},{"type":"Node","kind":"BLOCK_EXPR","start":9,"end":11,"children":[{"type":"Node","kind":"STMT_LIST","start":9,"end":11,"children":[{"type":"Token","kind":"L_CURLY","start":9,"end":10},{"type":"Token","kind":"R_CURLY","start":10,"end":11}]}]}]}]}"# + ]], + ); + + check( + r#" +fn test() { + assert!(" + fn foo() { + } + ", ""); +}"#, + expect![[ + r#"{"type":"Node","kind":"SOURCE_FILE","start":0,"end":60,"children":[{"type":"Node","kind":"FN","start":0,"end":60,"children":[{"type":"Token","kind":"FN_KW","start":0,"end":2},{"type":"Token","kind":"WHITESPACE","start":2,"end":3},{"type":"Node","kind":"NAME","start":3,"end":7,"children":[{"type":"Token","kind":"IDENT","start":3,"end":7}]},{"type":"Node","kind":"PARAM_LIST","start":7,"end":9,"children":[{"type":"Token","kind":"L_PAREN","start":7,"end":8},{"type":"Token","kind":"R_PAREN","start":8,"end":9}]},{"type":"Token","kind":"WHITESPACE","start":9,"end":10},{"type":"Node","kind":"BLOCK_EXPR","start":10,"end":60,"children":[{"type":"Node","kind":"STMT_LIST","start":10,"end":60,"children":[{"type":"Token","kind":"L_CURLY","start":10,"end":11},{"type":"Token","kind":"WHITESPACE","start":11,"end":16},{"type":"Node","kind":"EXPR_STMT","start":16,"end":58,"children":[{"type":"Node","kind":"MACRO_EXPR","start":16,"end":57,"children":[{"type":"Node","kind":"MACRO_CALL","start":16,"end":57,"children":[{"type":"Node","kind":"PATH","start":16,"end":22,"children":[{"type":"Node","kind":"PATH_SEGMENT","start":16,"end":22,"children":[{"type":"Node","kind":"NAME_REF","start":16,"end":22,"children":[{"type":"Token","kind":"IDENT","start":16,"end":22}]}]}]},{"type":"Token","kind":"BANG","start":22,"end":23},{"type":"Node","kind":"TOKEN_TREE","start":23,"end":57,"children":[{"type":"Token","kind":"L_PAREN","start":23,"end":24},{"type":"Node","kind":"STRING","start":24,"end":52,"children":[{"type":"Node","kind":"SOURCE_FILE","start":25,"end":51,"istart":0,"iend":26,"children":[{"type":"Token","kind":"WHITESPACE","start":25,"end":30,"istart":0,"iend":5},{"type":"Node","kind":"FN","start":30,"end":46,"istart":5,"iend":21,"children":[{"type":"Token","kind":"FN_KW","start":30,"end":32,"istart":5,"iend":7},{"type":"Token","kind":"WHITESPACE","start":32,"end":33,"istart":7,"iend":8},{"type":"Node","kind":"NAME","start":33,"end":36,"istart":8,"iend":11,"children":[{"type":"Token","kind":"IDENT","start":33,"end":36,"istart":8,"iend":11}]},{"type":"Node","kind":"PARAM_LIST","start":36,"end":38,"istart":11,"iend":13,"children":[{"type":"Token","kind":"L_PAREN","start":36,"end":37,"istart":11,"iend":12},{"type":"Token","kind":"R_PAREN","start":37,"end":38,"istart":12,"iend":13}]},{"type":"Token","kind":"WHITESPACE","start":38,"end":39,"istart":13,"iend":14},{"type":"Node","kind":"BLOCK_EXPR","start":39,"end":46,"istart":14,"iend":21,"children":[{"type":"Node","kind":"STMT_LIST","start":39,"end":46,"istart":14,"iend":21,"children":[{"type":"Token","kind":"L_CURLY","start":39,"end":40,"istart":14,"iend":15},{"type":"Token","kind":"WHITESPACE","start":40,"end":45,"istart":15,"iend":20},{"type":"Token","kind":"R_CURLY","start":45,"end":46,"istart":20,"iend":21}]}]}]},{"type":"Token","kind":"WHITESPACE","start":46,"end":51,"istart":21,"iend":26}]}]},{"type":"Token","kind":"COMMA","start":52,"end":53},{"type":"Token","kind":"WHITESPACE","start":53,"end":54},{"type":"Token","kind":"STRING","start":54,"end":56},{"type":"Token","kind":"R_PAREN","start":56,"end":57}]}]}]},{"type":"Token","kind":"SEMICOLON","start":57,"end":58}]},{"type":"Token","kind":"WHITESPACE","start":58,"end":59},{"type":"Token","kind":"R_CURLY","start":59,"end":60}]}]}]}]}"# + ]], + ) + } + + #[test] + fn view_syntax_tree_inside_string() { + check( + r#"fn test() { + assert!(" +$0fn foo() { +}$0 +fn bar() { +} + ", ""); +}"#, + expect![[ + r#"{"type":"Node","kind":"SOURCE_FILE","start":0,"end":65,"children":[{"type":"Node","kind":"FN","start":0,"end":65,"children":[{"type":"Token","kind":"FN_KW","start":0,"end":2},{"type":"Token","kind":"WHITESPACE","start":2,"end":3},{"type":"Node","kind":"NAME","start":3,"end":7,"children":[{"type":"Token","kind":"IDENT","start":3,"end":7}]},{"type":"Node","kind":"PARAM_LIST","start":7,"end":9,"children":[{"type":"Token","kind":"L_PAREN","start":7,"end":8},{"type":"Token","kind":"R_PAREN","start":8,"end":9}]},{"type":"Token","kind":"WHITESPACE","start":9,"end":10},{"type":"Node","kind":"BLOCK_EXPR","start":10,"end":65,"children":[{"type":"Node","kind":"STMT_LIST","start":10,"end":65,"children":[{"type":"Token","kind":"L_CURLY","start":10,"end":11},{"type":"Token","kind":"WHITESPACE","start":11,"end":16},{"type":"Node","kind":"EXPR_STMT","start":16,"end":63,"children":[{"type":"Node","kind":"MACRO_EXPR","start":16,"end":62,"children":[{"type":"Node","kind":"MACRO_CALL","start":16,"end":62,"children":[{"type":"Node","kind":"PATH","start":16,"end":22,"children":[{"type":"Node","kind":"PATH_SEGMENT","start":16,"end":22,"children":[{"type":"Node","kind":"NAME_REF","start":16,"end":22,"children":[{"type":"Token","kind":"IDENT","start":16,"end":22}]}]}]},{"type":"Token","kind":"BANG","start":22,"end":23},{"type":"Node","kind":"TOKEN_TREE","start":23,"end":62,"children":[{"type":"Token","kind":"L_PAREN","start":23,"end":24},{"type":"Node","kind":"STRING","start":24,"end":57,"children":[{"type":"Node","kind":"SOURCE_FILE","start":25,"end":56,"istart":0,"iend":31,"children":[{"type":"Token","kind":"WHITESPACE","start":25,"end":26,"istart":0,"iend":1},{"type":"Node","kind":"FN","start":26,"end":38,"istart":1,"iend":13,"children":[{"type":"Token","kind":"FN_KW","start":26,"end":28,"istart":1,"iend":3},{"type":"Token","kind":"WHITESPACE","start":28,"end":29,"istart":3,"iend":4},{"type":"Node","kind":"NAME","start":29,"end":32,"istart":4,"iend":7,"children":[{"type":"Token","kind":"IDENT","start":29,"end":32,"istart":4,"iend":7}]},{"type":"Node","kind":"PARAM_LIST","start":32,"end":34,"istart":7,"iend":9,"children":[{"type":"Token","kind":"L_PAREN","start":32,"end":33,"istart":7,"iend":8},{"type":"Token","kind":"R_PAREN","start":33,"end":34,"istart":8,"iend":9}]},{"type":"Token","kind":"WHITESPACE","start":34,"end":35,"istart":9,"iend":10},{"type":"Node","kind":"BLOCK_EXPR","start":35,"end":38,"istart":10,"iend":13,"children":[{"type":"Node","kind":"STMT_LIST","start":35,"end":38,"istart":10,"iend":13,"children":[{"type":"Token","kind":"L_CURLY","start":35,"end":36,"istart":10,"iend":11},{"type":"Token","kind":"WHITESPACE","start":36,"end":37,"istart":11,"iend":12},{"type":"Token","kind":"R_CURLY","start":37,"end":38,"istart":12,"iend":13}]}]}]},{"type":"Token","kind":"WHITESPACE","start":38,"end":39,"istart":13,"iend":14},{"type":"Node","kind":"FN","start":39,"end":51,"istart":14,"iend":26,"children":[{"type":"Token","kind":"FN_KW","start":39,"end":41,"istart":14,"iend":16},{"type":"Token","kind":"WHITESPACE","start":41,"end":42,"istart":16,"iend":17},{"type":"Node","kind":"NAME","start":42,"end":45,"istart":17,"iend":20,"children":[{"type":"Token","kind":"IDENT","start":42,"end":45,"istart":17,"iend":20}]},{"type":"Node","kind":"PARAM_LIST","start":45,"end":47,"istart":20,"iend":22,"children":[{"type":"Token","kind":"L_PAREN","start":45,"end":46,"istart":20,"iend":21},{"type":"Token","kind":"R_PAREN","start":46,"end":47,"istart":21,"iend":22}]},{"type":"Token","kind":"WHITESPACE","start":47,"end":48,"istart":22,"iend":23},{"type":"Node","kind":"BLOCK_EXPR","start":48,"end":51,"istart":23,"iend":26,"children":[{"type":"Node","kind":"STMT_LIST","start":48,"end":51,"istart":23,"iend":26,"children":[{"type":"Token","kind":"L_CURLY","start":48,"end":49,"istart":23,"iend":24},{"type":"Token","kind":"WHITESPACE","start":49,"end":50,"istart":24,"iend":25},{"type":"Token","kind":"R_CURLY","start":50,"end":51,"istart":25,"iend":26}]}]}]},{"type":"Token","kind":"WHITESPACE","start":51,"end":56,"istart":26,"iend":31}]}]},{"type":"Token","kind":"COMMA","start":57,"end":58},{"type":"Token","kind":"WHITESPACE","start":58,"end":59},{"type":"Token","kind":"STRING","start":59,"end":61},{"type":"Token","kind":"R_PAREN","start":61,"end":62}]}]}]},{"type":"Token","kind":"SEMICOLON","start":62,"end":63}]},{"type":"Token","kind":"WHITESPACE","start":63,"end":64},{"type":"Token","kind":"R_CURLY","start":64,"end":65}]}]}]}]}"# + ]], + ); + + // With a raw string + check( + r###"fn test() { + assert!(r#" +$0fn foo() { +}$0 +fn bar() { +} + "#, ""); +}"###, + expect![[ + r#"{"type":"Node","kind":"SOURCE_FILE","start":0,"end":68,"children":[{"type":"Node","kind":"FN","start":0,"end":68,"children":[{"type":"Token","kind":"FN_KW","start":0,"end":2},{"type":"Token","kind":"WHITESPACE","start":2,"end":3},{"type":"Node","kind":"NAME","start":3,"end":7,"children":[{"type":"Token","kind":"IDENT","start":3,"end":7}]},{"type":"Node","kind":"PARAM_LIST","start":7,"end":9,"children":[{"type":"Token","kind":"L_PAREN","start":7,"end":8},{"type":"Token","kind":"R_PAREN","start":8,"end":9}]},{"type":"Token","kind":"WHITESPACE","start":9,"end":10},{"type":"Node","kind":"BLOCK_EXPR","start":10,"end":68,"children":[{"type":"Node","kind":"STMT_LIST","start":10,"end":68,"children":[{"type":"Token","kind":"L_CURLY","start":10,"end":11},{"type":"Token","kind":"WHITESPACE","start":11,"end":16},{"type":"Node","kind":"EXPR_STMT","start":16,"end":66,"children":[{"type":"Node","kind":"MACRO_EXPR","start":16,"end":65,"children":[{"type":"Node","kind":"MACRO_CALL","start":16,"end":65,"children":[{"type":"Node","kind":"PATH","start":16,"end":22,"children":[{"type":"Node","kind":"PATH_SEGMENT","start":16,"end":22,"children":[{"type":"Node","kind":"NAME_REF","start":16,"end":22,"children":[{"type":"Token","kind":"IDENT","start":16,"end":22}]}]}]},{"type":"Token","kind":"BANG","start":22,"end":23},{"type":"Node","kind":"TOKEN_TREE","start":23,"end":65,"children":[{"type":"Token","kind":"L_PAREN","start":23,"end":24},{"type":"Node","kind":"STRING","start":24,"end":60,"children":[{"type":"Node","kind":"SOURCE_FILE","start":27,"end":58,"istart":0,"iend":31,"children":[{"type":"Token","kind":"WHITESPACE","start":27,"end":28,"istart":0,"iend":1},{"type":"Node","kind":"FN","start":28,"end":40,"istart":1,"iend":13,"children":[{"type":"Token","kind":"FN_KW","start":28,"end":30,"istart":1,"iend":3},{"type":"Token","kind":"WHITESPACE","start":30,"end":31,"istart":3,"iend":4},{"type":"Node","kind":"NAME","start":31,"end":34,"istart":4,"iend":7,"children":[{"type":"Token","kind":"IDENT","start":31,"end":34,"istart":4,"iend":7}]},{"type":"Node","kind":"PARAM_LIST","start":34,"end":36,"istart":7,"iend":9,"children":[{"type":"Token","kind":"L_PAREN","start":34,"end":35,"istart":7,"iend":8},{"type":"Token","kind":"R_PAREN","start":35,"end":36,"istart":8,"iend":9}]},{"type":"Token","kind":"WHITESPACE","start":36,"end":37,"istart":9,"iend":10},{"type":"Node","kind":"BLOCK_EXPR","start":37,"end":40,"istart":10,"iend":13,"children":[{"type":"Node","kind":"STMT_LIST","start":37,"end":40,"istart":10,"iend":13,"children":[{"type":"Token","kind":"L_CURLY","start":37,"end":38,"istart":10,"iend":11},{"type":"Token","kind":"WHITESPACE","start":38,"end":39,"istart":11,"iend":12},{"type":"Token","kind":"R_CURLY","start":39,"end":40,"istart":12,"iend":13}]}]}]},{"type":"Token","kind":"WHITESPACE","start":40,"end":41,"istart":13,"iend":14},{"type":"Node","kind":"FN","start":41,"end":53,"istart":14,"iend":26,"children":[{"type":"Token","kind":"FN_KW","start":41,"end":43,"istart":14,"iend":16},{"type":"Token","kind":"WHITESPACE","start":43,"end":44,"istart":16,"iend":17},{"type":"Node","kind":"NAME","start":44,"end":47,"istart":17,"iend":20,"children":[{"type":"Token","kind":"IDENT","start":44,"end":47,"istart":17,"iend":20}]},{"type":"Node","kind":"PARAM_LIST","start":47,"end":49,"istart":20,"iend":22,"children":[{"type":"Token","kind":"L_PAREN","start":47,"end":48,"istart":20,"iend":21},{"type":"Token","kind":"R_PAREN","start":48,"end":49,"istart":21,"iend":22}]},{"type":"Token","kind":"WHITESPACE","start":49,"end":50,"istart":22,"iend":23},{"type":"Node","kind":"BLOCK_EXPR","start":50,"end":53,"istart":23,"iend":26,"children":[{"type":"Node","kind":"STMT_LIST","start":50,"end":53,"istart":23,"iend":26,"children":[{"type":"Token","kind":"L_CURLY","start":50,"end":51,"istart":23,"iend":24},{"type":"Token","kind":"WHITESPACE","start":51,"end":52,"istart":24,"iend":25},{"type":"Token","kind":"R_CURLY","start":52,"end":53,"istart":25,"iend":26}]}]}]},{"type":"Token","kind":"WHITESPACE","start":53,"end":58,"istart":26,"iend":31}]}]},{"type":"Token","kind":"COMMA","start":60,"end":61},{"type":"Token","kind":"WHITESPACE","start":61,"end":62},{"type":"Token","kind":"STRING","start":62,"end":64},{"type":"Token","kind":"R_PAREN","start":64,"end":65}]}]}]},{"type":"Token","kind":"SEMICOLON","start":65,"end":66}]},{"type":"Token","kind":"WHITESPACE","start":66,"end":67},{"type":"Token","kind":"R_CURLY","start":67,"end":68}]}]}]}]}"# + ]], + ); + + // With a raw string + check( + r###"fn test() { + assert!(r$0#" +fn foo() { +} +fn bar() { +}"$0#, ""); +}"###, + expect![[ + r#"{"type":"Node","kind":"SOURCE_FILE","start":0,"end":63,"children":[{"type":"Node","kind":"FN","start":0,"end":63,"children":[{"type":"Token","kind":"FN_KW","start":0,"end":2},{"type":"Token","kind":"WHITESPACE","start":2,"end":3},{"type":"Node","kind":"NAME","start":3,"end":7,"children":[{"type":"Token","kind":"IDENT","start":3,"end":7}]},{"type":"Node","kind":"PARAM_LIST","start":7,"end":9,"children":[{"type":"Token","kind":"L_PAREN","start":7,"end":8},{"type":"Token","kind":"R_PAREN","start":8,"end":9}]},{"type":"Token","kind":"WHITESPACE","start":9,"end":10},{"type":"Node","kind":"BLOCK_EXPR","start":10,"end":63,"children":[{"type":"Node","kind":"STMT_LIST","start":10,"end":63,"children":[{"type":"Token","kind":"L_CURLY","start":10,"end":11},{"type":"Token","kind":"WHITESPACE","start":11,"end":16},{"type":"Node","kind":"EXPR_STMT","start":16,"end":61,"children":[{"type":"Node","kind":"MACRO_EXPR","start":16,"end":60,"children":[{"type":"Node","kind":"MACRO_CALL","start":16,"end":60,"children":[{"type":"Node","kind":"PATH","start":16,"end":22,"children":[{"type":"Node","kind":"PATH_SEGMENT","start":16,"end":22,"children":[{"type":"Node","kind":"NAME_REF","start":16,"end":22,"children":[{"type":"Token","kind":"IDENT","start":16,"end":22}]}]}]},{"type":"Token","kind":"BANG","start":22,"end":23},{"type":"Node","kind":"TOKEN_TREE","start":23,"end":60,"children":[{"type":"Token","kind":"L_PAREN","start":23,"end":24},{"type":"Node","kind":"STRING","start":24,"end":55,"children":[{"type":"Node","kind":"SOURCE_FILE","start":27,"end":53,"istart":0,"iend":26,"children":[{"type":"Token","kind":"WHITESPACE","start":27,"end":28,"istart":0,"iend":1},{"type":"Node","kind":"FN","start":28,"end":40,"istart":1,"iend":13,"children":[{"type":"Token","kind":"FN_KW","start":28,"end":30,"istart":1,"iend":3},{"type":"Token","kind":"WHITESPACE","start":30,"end":31,"istart":3,"iend":4},{"type":"Node","kind":"NAME","start":31,"end":34,"istart":4,"iend":7,"children":[{"type":"Token","kind":"IDENT","start":31,"end":34,"istart":4,"iend":7}]},{"type":"Node","kind":"PARAM_LIST","start":34,"end":36,"istart":7,"iend":9,"children":[{"type":"Token","kind":"L_PAREN","start":34,"end":35,"istart":7,"iend":8},{"type":"Token","kind":"R_PAREN","start":35,"end":36,"istart":8,"iend":9}]},{"type":"Token","kind":"WHITESPACE","start":36,"end":37,"istart":9,"iend":10},{"type":"Node","kind":"BLOCK_EXPR","start":37,"end":40,"istart":10,"iend":13,"children":[{"type":"Node","kind":"STMT_LIST","start":37,"end":40,"istart":10,"iend":13,"children":[{"type":"Token","kind":"L_CURLY","start":37,"end":38,"istart":10,"iend":11},{"type":"Token","kind":"WHITESPACE","start":38,"end":39,"istart":11,"iend":12},{"type":"Token","kind":"R_CURLY","start":39,"end":40,"istart":12,"iend":13}]}]}]},{"type":"Token","kind":"WHITESPACE","start":40,"end":41,"istart":13,"iend":14},{"type":"Node","kind":"FN","start":41,"end":53,"istart":14,"iend":26,"children":[{"type":"Token","kind":"FN_KW","start":41,"end":43,"istart":14,"iend":16},{"type":"Token","kind":"WHITESPACE","start":43,"end":44,"istart":16,"iend":17},{"type":"Node","kind":"NAME","start":44,"end":47,"istart":17,"iend":20,"children":[{"type":"Token","kind":"IDENT","start":44,"end":47,"istart":17,"iend":20}]},{"type":"Node","kind":"PARAM_LIST","start":47,"end":49,"istart":20,"iend":22,"children":[{"type":"Token","kind":"L_PAREN","start":47,"end":48,"istart":20,"iend":21},{"type":"Token","kind":"R_PAREN","start":48,"end":49,"istart":21,"iend":22}]},{"type":"Token","kind":"WHITESPACE","start":49,"end":50,"istart":22,"iend":23},{"type":"Node","kind":"BLOCK_EXPR","start":50,"end":53,"istart":23,"iend":26,"children":[{"type":"Node","kind":"STMT_LIST","start":50,"end":53,"istart":23,"iend":26,"children":[{"type":"Token","kind":"L_CURLY","start":50,"end":51,"istart":23,"iend":24},{"type":"Token","kind":"WHITESPACE","start":51,"end":52,"istart":24,"iend":25},{"type":"Token","kind":"R_CURLY","start":52,"end":53,"istart":25,"iend":26}]}]}]}]}]},{"type":"Token","kind":"COMMA","start":55,"end":56},{"type":"Token","kind":"WHITESPACE","start":56,"end":57},{"type":"Token","kind":"STRING","start":57,"end":59},{"type":"Token","kind":"R_PAREN","start":59,"end":60}]}]}]},{"type":"Token","kind":"SEMICOLON","start":60,"end":61}]},{"type":"Token","kind":"WHITESPACE","start":61,"end":62},{"type":"Token","kind":"R_CURLY","start":62,"end":63}]}]}]}]}"# + ]], + ); + } +} diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs index 66b8900109c..b3b46421b50 100644 --- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs +++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs @@ -174,6 +174,7 @@ define_symbols! { const_param_ty, Context, Continue, + convert, copy, Copy, core_panic, @@ -239,6 +240,8 @@ define_symbols! { format_unsafe_arg, format, freeze, + From, + FromStr, from_output, from_residual, from_usize, @@ -429,6 +432,7 @@ define_symbols! { shr, simd, sized, + skip, slice_len_fn, Some, start, @@ -456,6 +460,7 @@ define_symbols! { transmute_trait, transparent, Try, + TryFrom, tuple_trait, u128, u16, diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs index 73899408652..00446b27cf2 100644 --- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs +++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs @@ -242,9 +242,6 @@ impl ProjectFolders { } } - if dirs.include.is_empty() { - continue; - } vfs::loader::Entry::Directories(dirs) }; @@ -267,7 +264,7 @@ impl ProjectFolders { }; let file_set_roots = vec![VfsPath::from(ratoml_path.to_owned())]; - let entry = vfs::loader::Entry::Files(vec![ratoml_path]); + let entry = vfs::loader::Entry::Files(vec![ratoml_path.to_owned()]); res.watch.push(res.load.len()); res.load.push(entry); diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs index 9255c5a6899..7710ea79389 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs @@ -38,7 +38,10 @@ impl<'t> Bindings<'t> { nesting_state.hit = true; b = match b { Binding::Fragment(_) => break, - Binding::Missing(_) => break, + Binding::Missing(_) => { + nesting_state.at_end = true; + break; + } Binding::Nested(bs) => bs.get(nesting_state.idx).ok_or_else(|| { nesting_state.at_end = true; binding_err!("could not find nested binding `{name}`") @@ -445,6 +448,7 @@ fn expand_repeat( let mut counter = 0; let mut err = None; + let initial_restore_point = builder.restore_point(); let mut restore_point = builder.restore_point(); loop { let ExpandResult { value: (), err: e } = @@ -462,6 +466,10 @@ fn expand_repeat( counter += 1; if counter == limit { + // FIXME: This is a bug here, we get here when we shouldn't, see https://github.com/rust-lang/rust-analyzer/issues/18910. + // If we don't restore we emit a lot of nodes which causes a stack overflow down the road. For now just ignore them, + // there is always an error here anyway. + builder.restore(initial_restore_point); err = Some(ExpandError::new(ctx.call_site, ExpandErrorKind::LimitExceeded)); break; } diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs index 6abf56d4b37..bebd29ef747 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs @@ -369,7 +369,8 @@ pub fn expect_fragment<'t>( ) -> ExpandResult<tt::TokenTreesView<'t, Span>> { use ::parser; let buffer = tt_iter.remaining(); - let parser_input = to_parser_input(edition, buffer); + // FIXME: Pass the correct edition per token. Due to the split between mbe and hir-expand it's complicated. + let parser_input = to_parser_input(buffer, &mut |_ctx| edition); let tree_traversal = entry_point.parse(&parser_input, edition); let mut cursor = buffer.cursor(); let mut error = false; diff --git a/src/tools/rust-analyzer/crates/mbe/src/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/tests.rs index e63ad113ffd..fb68d35a4c8 100644 --- a/src/tools/rust-analyzer/crates/mbe/src/tests.rs +++ b/src/tools/rust-analyzer/crates/mbe/src/tests.rs @@ -26,7 +26,7 @@ fn check_( file_id: EditionedFileId::new(FileId::from_raw(0), def_edition), ast_id: ErasedFileAstId::from_raw(0), }, - SyntaxContextId::ROOT, + SyntaxContextId::root(Edition::CURRENT), decl, ) .unwrap(); @@ -39,16 +39,20 @@ fn check_( file_id: EditionedFileId::new(FileId::from_raw(1), call_edition), ast_id: ErasedFileAstId::from_raw(0), }; - let arg_tt = - syntax_bridge::parse_to_token_tree(call_edition, call_anchor, SyntaxContextId::ROOT, arg) - .unwrap(); + let arg_tt = syntax_bridge::parse_to_token_tree( + call_edition, + call_anchor, + SyntaxContextId::root(Edition::CURRENT), + arg, + ) + .unwrap(); let res = mac.expand( &arg_tt, |_| (), Span { range: TextRange::up_to(TextSize::of(arg)), anchor: call_anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, def_edition, ); @@ -59,7 +63,12 @@ fn check_( if render_debug { format_to!(expect_res, "{:#?}\n\n", res.value.0); } - let (node, _) = syntax_bridge::token_tree_to_syntax_node(&res.value.0, parse, def_edition); + let (node, _) = syntax_bridge::token_tree_to_syntax_node( + &res.value.0, + parse, + &mut |_| def_edition, + def_edition, + ); format_to!( expect_res, "{}", @@ -106,25 +115,25 @@ fn token_mapping_smoke_test() { struct MyTraitMap2 "#, expect![[r#" - SUBTREE $$ 1:0@0..20#0 1:0@0..20#0 - IDENT struct 0:0@34..40#0 - IDENT MyTraitMap2 1:0@8..19#0 - SUBTREE {} 0:0@48..49#0 0:0@100..101#0 - IDENT map 0:0@58..61#0 - PUNCH : [alone] 0:0@61..62#0 - PUNCH : [joint] 0:0@63..64#0 - PUNCH : [alone] 0:0@64..65#0 - IDENT std 0:0@65..68#0 - PUNCH : [joint] 0:0@68..69#0 - PUNCH : [alone] 0:0@69..70#0 - IDENT collections 0:0@70..81#0 - PUNCH : [joint] 0:0@81..82#0 - PUNCH : [alone] 0:0@82..83#0 - IDENT HashSet 0:0@83..90#0 - PUNCH < [alone] 0:0@90..91#0 - SUBTREE () 0:0@91..92#0 0:0@92..93#0 - PUNCH > [joint] 0:0@93..94#0 - PUNCH , [alone] 0:0@94..95#0 + SUBTREE $$ 1:0@0..20#2 1:0@0..20#2 + IDENT struct 0:0@34..40#2 + IDENT MyTraitMap2 1:0@8..19#2 + SUBTREE {} 0:0@48..49#2 0:0@100..101#2 + IDENT map 0:0@58..61#2 + PUNCH : [alone] 0:0@61..62#2 + PUNCH : [joint] 0:0@63..64#2 + PUNCH : [alone] 0:0@64..65#2 + IDENT std 0:0@65..68#2 + PUNCH : [joint] 0:0@68..69#2 + PUNCH : [alone] 0:0@69..70#2 + IDENT collections 0:0@70..81#2 + PUNCH : [joint] 0:0@81..82#2 + PUNCH : [alone] 0:0@82..83#2 + IDENT HashSet 0:0@83..90#2 + PUNCH < [alone] 0:0@90..91#2 + SUBTREE () 0:0@91..92#2 0:0@92..93#2 + PUNCH > [joint] 0:0@93..94#2 + PUNCH , [alone] 0:0@94..95#2 struct MyTraitMap2 { map: ::std::collections::HashSet<()>, @@ -153,28 +162,28 @@ fn main() { } "#, expect![[r#" - SUBTREE $$ 1:0@0..63#0 1:0@0..63#0 - IDENT fn 1:0@1..3#0 - IDENT main 1:0@4..8#0 - SUBTREE () 1:0@8..9#0 1:0@9..10#0 - SUBTREE {} 1:0@11..12#0 1:0@61..62#0 - LITERAL Integer 1 1:0@17..18#0 - PUNCH ; [alone] 1:0@18..19#0 - LITERAL Float 1.0 1:0@24..27#0 - PUNCH ; [alone] 1:0@27..28#0 - SUBTREE () 1:0@33..34#0 1:0@39..40#0 - SUBTREE () 1:0@34..35#0 1:0@37..38#0 - LITERAL Integer 1 1:0@35..36#0 - PUNCH , [alone] 1:0@36..37#0 - PUNCH , [alone] 1:0@38..39#0 - PUNCH . [alone] 1:0@40..41#0 - LITERAL Float 0.0 1:0@41..44#0 - PUNCH ; [alone] 1:0@44..45#0 - IDENT let 1:0@50..53#0 - IDENT x 1:0@54..55#0 - PUNCH = [alone] 1:0@56..57#0 - LITERAL Integer 1 1:0@58..59#0 - PUNCH ; [alone] 1:0@59..60#0 + SUBTREE $$ 1:0@0..63#2 1:0@0..63#2 + IDENT fn 1:0@1..3#2 + IDENT main 1:0@4..8#2 + SUBTREE () 1:0@8..9#2 1:0@9..10#2 + SUBTREE {} 1:0@11..12#2 1:0@61..62#2 + LITERAL Integer 1 1:0@17..18#2 + PUNCH ; [alone] 1:0@18..19#2 + LITERAL Float 1.0 1:0@24..27#2 + PUNCH ; [alone] 1:0@27..28#2 + SUBTREE () 1:0@33..34#2 1:0@39..40#2 + SUBTREE () 1:0@34..35#2 1:0@37..38#2 + LITERAL Integer 1 1:0@35..36#2 + PUNCH , [alone] 1:0@36..37#2 + PUNCH , [alone] 1:0@38..39#2 + PUNCH . [alone] 1:0@40..41#2 + LITERAL Float 0.0 1:0@41..44#2 + PUNCH ; [alone] 1:0@44..45#2 + IDENT let 1:0@50..53#2 + IDENT x 1:0@54..55#2 + PUNCH = [alone] 1:0@56..57#2 + LITERAL Integer 1 1:0@58..59#2 + PUNCH ; [alone] 1:0@59..60#2 fn main(){ 1; @@ -200,14 +209,14 @@ fn expr_2021() { const { 1 }, "#, expect![[r#" - SUBTREE $$ 1:0@0..25#0 1:0@0..25#0 - IDENT _ 1:0@5..6#0 - PUNCH ; [joint] 0:0@36..37#0 - SUBTREE () 0:0@34..35#0 0:0@34..35#0 - IDENT const 1:0@12..17#0 - SUBTREE {} 1:0@18..19#0 1:0@22..23#0 - LITERAL Integer 1 1:0@20..21#0 - PUNCH ; [alone] 0:0@39..40#0 + SUBTREE $$ 1:0@0..25#2 1:0@0..25#2 + IDENT _ 1:0@5..6#2 + PUNCH ; [joint] 0:0@36..37#2 + SUBTREE () 0:0@34..35#2 0:0@34..35#2 + IDENT const 1:0@12..17#2 + SUBTREE {} 1:0@18..19#2 1:0@22..23#2 + LITERAL Integer 1 1:0@20..21#2 + PUNCH ; [alone] 0:0@39..40#2 _; (const { @@ -228,13 +237,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..6#0, + 1:0@5..6#2, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..8#0 1:0@0..8#0 - PUNCH ; [alone] 0:0@39..40#0 + SUBTREE $$ 1:0@0..8#2 1:0@0..8#2 + PUNCH ; [alone] 0:0@39..40#2 ;"#]], ); @@ -252,13 +261,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..10#0, + 1:0@5..10#2, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..18#0 1:0@0..18#0 - PUNCH ; [alone] 0:0@39..40#0 + SUBTREE $$ 1:0@0..18#2 1:0@0..18#2 + PUNCH ; [alone] 0:0@39..40#2 ;"#]], ); @@ -278,26 +287,26 @@ fn expr_2021() { break 'foo bar, "#, expect![[r#" - SUBTREE $$ 1:0@0..76#0 1:0@0..76#0 - LITERAL Integer 4 1:0@5..6#0 - PUNCH ; [joint] 0:0@41..42#0 - LITERAL Str literal 1:0@12..21#0 - PUNCH ; [joint] 0:0@41..42#0 - SUBTREE () 0:0@39..40#0 0:0@39..40#0 - IDENT funcall 1:0@27..34#0 - SUBTREE () 1:0@34..35#0 1:0@35..36#0 - PUNCH ; [joint] 0:0@41..42#0 - SUBTREE () 0:0@39..40#0 0:0@39..40#0 - IDENT future 1:0@42..48#0 - PUNCH . [alone] 1:0@48..49#0 - IDENT await 1:0@49..54#0 - PUNCH ; [joint] 0:0@41..42#0 - SUBTREE () 0:0@39..40#0 0:0@39..40#0 - IDENT break 1:0@60..65#0 - PUNCH ' [joint] 1:0@66..67#0 - IDENT foo 1:0@67..70#0 - IDENT bar 1:0@71..74#0 - PUNCH ; [alone] 0:0@44..45#0 + SUBTREE $$ 1:0@0..76#2 1:0@0..76#2 + LITERAL Integer 4 1:0@5..6#2 + PUNCH ; [joint] 0:0@41..42#2 + LITERAL Str literal 1:0@12..21#2 + PUNCH ; [joint] 0:0@41..42#2 + SUBTREE () 0:0@39..40#2 0:0@39..40#2 + IDENT funcall 1:0@27..34#2 + SUBTREE () 1:0@34..35#2 1:0@35..36#2 + PUNCH ; [joint] 0:0@41..42#2 + SUBTREE () 0:0@39..40#2 0:0@39..40#2 + IDENT future 1:0@42..48#2 + PUNCH . [alone] 1:0@48..49#2 + IDENT await 1:0@49..54#2 + PUNCH ; [joint] 0:0@41..42#2 + SUBTREE () 0:0@39..40#2 0:0@39..40#2 + IDENT break 1:0@60..65#2 + PUNCH ' [joint] 1:0@66..67#2 + IDENT foo 1:0@67..70#2 + IDENT bar 1:0@71..74#2 + PUNCH ; [alone] 0:0@44..45#2 4; "literal"; @@ -319,13 +328,13 @@ fn expr_2021() { expect![[r#" ExpandError { inner: ( - 1:0@5..6#0, + 1:0@5..6#2, NoMatchingRule, ), } - SUBTREE $$ 1:0@0..8#0 1:0@0..8#0 - PUNCH ; [alone] 0:0@44..45#0 + SUBTREE $$ 1:0@0..8#2 1:0@0..8#2 + PUNCH ; [alone] 0:0@44..45#2 ;"#]], ); diff --git a/src/tools/rust-analyzer/crates/parser/src/event.rs b/src/tools/rust-analyzer/crates/parser/src/event.rs index e38571dd3ec..b197b086f37 100644 --- a/src/tools/rust-analyzer/crates/parser/src/event.rs +++ b/src/tools/rust-analyzer/crates/parser/src/event.rs @@ -12,7 +12,7 @@ use crate::{ /// `Parser` produces a flat list of `Event`s. /// They are converted to a tree-structure in /// a separate pass, via `TreeBuilder`. -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub(crate) enum Event { /// This event signifies the start of the node. /// It should be either abandoned (in which case the diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs index 3b3f11be130..389c01933c9 100644 --- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs +++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs @@ -134,10 +134,12 @@ pub(super) fn let_stmt(p: &mut Parser<'_>, with_semi: Semicolon) { // test_err let_else_right_curly_brace // fn func() { let Some(_) = {Some(1)} else { panic!("h") };} if let Some(expr) = expr_after_eq { - if BlockLike::is_blocklike(expr.kind()) { - p.error( - "right curly brace `}` before `else` in a `let...else` statement not allowed", - ) + if let Some(token) = expr.last_token(p) { + if token == T!['}'] { + p.error( + "right curly brace `}` before `else` in a `let...else` statement not allowed" + ) + } } } @@ -339,13 +341,20 @@ fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLik // // raw reference operator // let _ = &raw mut foo; // let _ = &raw const foo; + // let _ = &raw foo; // } T![&] => { m = p.start(); p.bump(T![&]); - if p.at_contextual_kw(T![raw]) && [T![mut], T![const]].contains(&p.nth(1)) { - p.bump_remap(T![raw]); - p.bump_any(); + if p.at_contextual_kw(T![raw]) { + if [T![mut], T![const]].contains(&p.nth(1)) { + p.bump_remap(T![raw]); + p.bump_any(); + } else if p.nth_at(1, SyntaxKind::IDENT) { + // we treat raw as keyword in this case + // &raw foo; + p.bump_remap(T![raw]); + } } else { p.eat(T![mut]); } diff --git a/src/tools/rust-analyzer/crates/parser/src/parser.rs b/src/tools/rust-analyzer/crates/parser/src/parser.rs index 75a75f601cf..2f6ba525747 100644 --- a/src/tools/rust-analyzer/crates/parser/src/parser.rs +++ b/src/tools/rust-analyzer/crates/parser/src/parser.rs @@ -318,7 +318,8 @@ impl Marker { _ => unreachable!(), } p.push_event(Event::Finish); - CompletedMarker::new(self.pos, kind) + let end_pos = p.events.len() as u32; + CompletedMarker::new(self.pos, end_pos, kind) } /// Abandons the syntax tree node. All its children @@ -336,13 +337,14 @@ impl Marker { } pub(crate) struct CompletedMarker { - pos: u32, + start_pos: u32, + end_pos: u32, kind: SyntaxKind, } impl CompletedMarker { - fn new(pos: u32, kind: SyntaxKind) -> Self { - CompletedMarker { pos, kind } + fn new(start_pos: u32, end_pos: u32, kind: SyntaxKind) -> Self { + CompletedMarker { start_pos, end_pos, kind } } /// This method allows to create a new node which starts @@ -360,10 +362,10 @@ impl CompletedMarker { /// distance to `NEWSTART` into forward_parent(=2 in this case); pub(crate) fn precede(self, p: &mut Parser<'_>) -> Marker { let new_pos = p.start(); - let idx = self.pos as usize; + let idx = self.start_pos as usize; match &mut p.events[idx] { Event::Start { forward_parent, .. } => { - *forward_parent = Some(new_pos.pos - self.pos); + *forward_parent = Some(new_pos.pos - self.start_pos); } _ => unreachable!(), } @@ -376,7 +378,7 @@ impl CompletedMarker { let idx = m.pos as usize; match &mut p.events[idx] { Event::Start { forward_parent, .. } => { - *forward_parent = Some(self.pos - m.pos); + *forward_parent = Some(self.start_pos - m.pos); } _ => unreachable!(), } @@ -386,4 +388,13 @@ impl CompletedMarker { pub(crate) fn kind(&self) -> SyntaxKind { self.kind } + + pub(crate) fn last_token(&self, p: &Parser<'_>) -> Option<SyntaxKind> { + let end_pos = self.end_pos as usize; + debug_assert_eq!(p.events[end_pos - 1], Event::Finish); + p.events[..end_pos].iter().rev().find_map(|event| match event { + Event::Token { kind, .. } => Some(*kind), + _ => None, + }) + } } diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rast new file mode 100644 index 00000000000..578dc2b0f96 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rast @@ -0,0 +1,79 @@ +SOURCE_FILE + STRUCT + STRUCT_KW "struct" + WHITESPACE " " + NAME + IDENT "X" + WHITESPACE " " + RECORD_FIELD_LIST + L_CURLY "{" + RECORD_FIELD + NAME + IDENT "a" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "i32" + R_CURLY "}" + WHITESPACE "\n" + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "f" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LET_STMT + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + RECORD_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "X" + WHITESPACE " " + RECORD_EXPR_FIELD_LIST + L_CURLY "{" + WHITESPACE "\n " + RECORD_EXPR_FIELD + NAME_REF + IDENT "a" + COLON ":" + WHITESPACE " " + LITERAL + INT_NUMBER "1" + WHITESPACE "\n " + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE "\n " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" +error 63: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rs new file mode 100644 index 00000000000..c0c0edc9830 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0056_let_else_right_curly_brace_struct.rs @@ -0,0 +1,8 @@ +struct X {a: i32} +fn f() { + let foo = X { + a: 1 + } else { + return; + }; +} \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rast new file mode 100644 index 00000000000..8e994f22d41 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rast @@ -0,0 +1,42 @@ +SOURCE_FILE + ERROR + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + BIN_EXPR + LITERAL + INT_NUMBER "1" + WHITESPACE " " + PLUS "+" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LITERAL + INT_NUMBER "1" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" +error 0: expected an item +error 23: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rs new file mode 100644 index 00000000000..c29ddcce1ff --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_arithmetic.rs @@ -0,0 +1,5 @@ +let foo = 1 + { + 1 +} else { + return; +}; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rast new file mode 100644 index 00000000000..055b583acec --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rast @@ -0,0 +1,90 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "r" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LET_STMT + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "ok" + WHITESPACE " " + EQ "=" + WHITESPACE " " + MACRO_EXPR + MACRO_CALL + PATH + PATH_SEGMENT + NAME_REF + IDENT "format_args" + BANG "!" + TOKEN_TREE + L_PAREN "(" + STRING "\"\"" + R_PAREN ")" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE " " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE " " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n\n " + LET_STMT + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "bad" + WHITESPACE " " + EQ "=" + WHITESPACE " " + MACRO_EXPR + MACRO_CALL + PATH + PATH_SEGMENT + NAME_REF + IDENT "format_args" + BANG "!" + WHITESPACE " " + TOKEN_TREE + L_CURLY "{" + STRING "\"\"" + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE " " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE " " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE "\n" +error 89: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rs new file mode 100644 index 00000000000..5916fa07dc2 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0057_let_else_right_curly_brace_format_args.rs @@ -0,0 +1,5 @@ +fn r() { + let ok = format_args!("") else { return; }; + + let bad = format_args! {""} else { return; }; +} diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rast new file mode 100644 index 00000000000..8c7fd8c295d --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rast @@ -0,0 +1,40 @@ +SOURCE_FILE + ERROR + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + RANGE_EXPR + LITERAL + INT_NUMBER "1" + DOT2 ".." + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LITERAL + INT_NUMBER "1" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" +error 0: expected an item +error 22: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rs new file mode 100644 index 00000000000..5417131d28e --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0058_let_else_right_curly_brace_range.rs @@ -0,0 +1,5 @@ +let foo = 1..{ + 1 +} else { + return; +}; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rast new file mode 100644 index 00000000000..57925a0d192 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rast @@ -0,0 +1,55 @@ +SOURCE_FILE + ERROR + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + CLOSURE_EXPR + PARAM_LIST + PIPE "|" + PARAM + IDENT_PAT + NAME + IDENT "x" + COLON ":" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "i32" + PIPE "|" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "x" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" +error 0: expected an item +error 28: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rs new file mode 100644 index 00000000000..89c7579b071 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0059_let_else_right_curly_brace_closure.rs @@ -0,0 +1,5 @@ +let foo = |x: i32| { + x +} else { + return; +}; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rast new file mode 100644 index 00000000000..4fb70bd50e3 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rast @@ -0,0 +1,38 @@ +SOURCE_FILE + ERROR + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + PREFIX_EXPR + MINUS "-" + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LITERAL + INT_NUMBER "1" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" +error 0: expected an item +error 20: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rs new file mode 100644 index 00000000000..1ba7f7d761b --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0060_let_else_right_curly_brace_unary.rs @@ -0,0 +1,5 @@ +let foo = -{ + 1 +} else { + return; +}; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rast new file mode 100644 index 00000000000..e8eeeee695e --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rast @@ -0,0 +1,90 @@ +SOURCE_FILE + FN + FN_KW "fn" + WHITESPACE " " + NAME + IDENT "o" + PARAM_LIST + L_PAREN "(" + R_PAREN ")" + WHITESPACE " " + RET_TYPE + THIN_ARROW "->" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Result" + GENERIC_ARG_LIST + L_ANGLE "<" + TYPE_ARG + TUPLE_TYPE + L_PAREN "(" + R_PAREN ")" + COMMA "," + WHITESPACE " " + TYPE_ARG + TUPLE_TYPE + L_PAREN "(" + R_PAREN ")" + R_ANGLE ">" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LET_STMT + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + YEET_EXPR + DO_KW "do" + WHITESPACE " " + YEET_KW "yeet" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + TUPLE_EXPR + L_PAREN "(" + R_PAREN ")" + WHITESPACE "\n " + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + WHITESPACE " " + CALL_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "Ok" + ARG_LIST + L_PAREN "(" + TUPLE_EXPR + L_PAREN "(" + R_PAREN ")" + R_PAREN ")" + SEMICOLON ";" + WHITESPACE "\n " + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" +error 67: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rs new file mode 100644 index 00000000000..188fb07d91b --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0061_let_else_right_curly_brace_do_yeet.rs @@ -0,0 +1,7 @@ +fn o() -> Result<(), ()> { + let foo = do yeet { + () + } else { + return Ok(()); + }; +} \ No newline at end of file diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rast new file mode 100644 index 00000000000..cc5e1278c3d --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rast @@ -0,0 +1,40 @@ +SOURCE_FILE + ERROR + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + BECOME_EXPR + BECOME_KW "become" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + TUPLE_EXPR + L_PAREN "(" + R_PAREN ")" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" +error 0: expected an item +error 27: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rs new file mode 100644 index 00000000000..622548b8f33 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0062_let_else_right_curly_brace_become.rs @@ -0,0 +1,5 @@ +let foo = become { + () +} else { + return; +}; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rast new file mode 100644 index 00000000000..ea2f4f28e2d --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rast @@ -0,0 +1,38 @@ +SOURCE_FILE + ERROR + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + REF_EXPR + AMP "&" + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LITERAL + INT_NUMBER "1" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" +error 0: expected an item +error 20: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rs new file mode 100644 index 00000000000..9a00dca3689 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0063_let_else_right_curly_brace_reference.rs @@ -0,0 +1,5 @@ +let foo = &{ + 1 +} else { + return; +}; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rast new file mode 100644 index 00000000000..47396140c5c --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rast @@ -0,0 +1,45 @@ +SOURCE_FILE + ERROR + LET_KW "let" + WHITESPACE " " + IDENT_PAT + NAME + IDENT "foo" + WHITESPACE " " + EQ "=" + WHITESPACE " " + BIN_EXPR + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "bar" + WHITESPACE " " + EQ "=" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + LITERAL + INT_NUMBER "1" + WHITESPACE "\n" + R_CURLY "}" + WHITESPACE " " + LET_ELSE + ELSE_KW "else" + WHITESPACE " " + BLOCK_EXPR + STMT_LIST + L_CURLY "{" + WHITESPACE "\n " + EXPR_STMT + RETURN_EXPR + RETURN_KW "return" + SEMICOLON ";" + WHITESPACE "\n" + R_CURLY "}" + SEMICOLON ";" + WHITESPACE "\n" +error 0: expected an item +error 25: right curly brace `}` before `else` in a `let...else` statement not allowed diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rs new file mode 100644 index 00000000000..08e677416f1 --- /dev/null +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0064_let_else_right_curly_brace_assignment.rs @@ -0,0 +1,5 @@ +let foo = bar = { + 1 +} else { + return; +}; diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast index 108b0802c33..8dc916e5cc5 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rast @@ -134,6 +134,25 @@ SOURCE_FILE NAME_REF IDENT "foo" SEMICOLON ";" + WHITESPACE "\n " + LET_STMT + LET_KW "let" + WHITESPACE " " + WILDCARD_PAT + UNDERSCORE "_" + WHITESPACE " " + EQ "=" + WHITESPACE " " + REF_EXPR + AMP "&" + RAW_KW "raw" + WHITESPACE " " + PATH_EXPR + PATH + PATH_SEGMENT + NAME_REF + IDENT "foo" + SEMICOLON ";" WHITESPACE "\n" R_CURLY "}" WHITESPACE "\n" diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs index c5262f4469b..31a2485b439 100644 --- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs +++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/ref_expr.rs @@ -7,4 +7,5 @@ fn foo() { // raw reference operator let _ = &raw mut foo; let _ = &raw const foo; + let _ = &raw foo; } diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs index 6ea8db9a905..4b831e4aceb 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs @@ -159,7 +159,7 @@ type ProtocolWrite<W: Write> = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str) #[cfg(test)] mod tests { use intern::{sym, Symbol}; - use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize}; + use span::{Edition, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize}; use tt::{ Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree, TopSubtreeBuilder, @@ -180,12 +180,12 @@ mod tests { open: Span { range: TextRange::empty(TextSize::new(0)), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, close: Span { range: TextRange::empty(TextSize::new(19)), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, kind: DelimiterKind::Invisible, }); @@ -196,7 +196,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(0), TextSize::of("struct")), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, is_raw: tt::IdentIsRaw::No, } @@ -208,7 +208,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, is_raw: tt::IdentIsRaw::Yes, } @@ -219,7 +219,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, kind: tt::LitKind::Str, suffix: None, @@ -229,7 +229,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(13), TextSize::of('@')), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, spacing: Spacing::Joint, })); @@ -238,7 +238,7 @@ mod tests { Span { range: TextRange::at(TextSize::new(14), TextSize::of('{')), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, ); builder.push(Leaf::Literal(Literal { @@ -246,7 +246,7 @@ mod tests { span: Span { range: TextRange::at(TextSize::new(15), TextSize::of("0u32")), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }, kind: tt::LitKind::Integer, suffix: Some(sym::u32.clone()), @@ -254,7 +254,7 @@ mod tests { builder.close(Span { range: TextRange::at(TextSize::new(19), TextSize::of('}')), anchor, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }); builder.build() diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml index 00695c54737..191535ac55e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml @@ -14,6 +14,7 @@ doctest = false [dependencies] object.workspace = true +libc.workspace = true libloading.workspace = true memmap2.workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs index fe15d42b4e4..cbf7a277bfa 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs @@ -28,11 +28,16 @@ fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> { #[cfg(unix)] fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> { + // not defined by POSIX, different values on mips vs other targets + #[cfg(target_env = "gnu")] + use libc::RTLD_DEEPBIND; use libloading::os::unix::Library as UnixLibrary; - use std::os::raw::c_int; + // defined by POSIX + use libloading::os::unix::RTLD_NOW; - const RTLD_NOW: c_int = 0x00002; - const RTLD_DEEPBIND: c_int = 0x00008; + // MUSL and bionic don't have it.. + #[cfg(not(target_env = "gnu"))] + const RTLD_DEEPBIND: std::os::raw::c_int = 0x0; unsafe { UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into()) } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index beaebf33300..c7614849e01 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -440,7 +440,7 @@ mod tests { file_id: EditionedFileId::current_edition(FileId::from_raw(0)), ast_id: span::ErasedFileAstId::from_raw(0), }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::CURRENT), }; let s = TokenStream { token_trees: vec![ @@ -482,7 +482,7 @@ mod tests { file_id: EditionedFileId::current_edition(FileId::from_raw(0)), ast_id: span::ErasedFileAstId::from_raw(0), }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::CURRENT), }; let subtree_paren_a = vec![ tt::TokenTree::Subtree(tt::Subtree { diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs index dc6e71163b2..15de88ea656 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs @@ -12,7 +12,7 @@ fn test_derive_empty() { "DeriveEmpty", r#"struct S;"#, expect!["SUBTREE $$ 1 1"], - expect!["SUBTREE $$ 42:2@0..100#0 42:2@0..100#0"], + expect!["SUBTREE $$ 42:2@0..100#2 42:2@0..100#2"], ); } @@ -29,12 +29,12 @@ fn test_derive_error() { LITERAL Str #[derive(DeriveError)] struct S ; 1 PUNCH ; [alone] 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT compile_error 42:2@0..100#0 - PUNCH ! [alone] 42:2@0..100#0 - SUBTREE () 42:2@0..100#0 42:2@0..100#0 - LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#0 - PUNCH ; [alone] 42:2@0..100#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT compile_error 42:2@0..100#2 + PUNCH ! [alone] 42:2@0..100#2 + SUBTREE () 42:2@0..100#2 42:2@0..100#2 + LITERAL Str #[derive(DeriveError)] struct S ; 42:2@0..100#2 + PUNCH ; [alone] 42:2@0..100#2"#]], ); } @@ -53,14 +53,14 @@ fn test_fn_like_macro_noop() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT ident 42:2@0..5#0 - PUNCH , [alone] 42:2@5..6#0 - LITERAL Integer 0 42:2@7..8#0 - PUNCH , [alone] 42:2@8..9#0 - LITERAL Integer 1 42:2@10..11#0 - PUNCH , [alone] 42:2@11..12#0 - SUBTREE [] 42:2@13..14#0 42:2@14..15#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT ident 42:2@0..5#2 + PUNCH , [alone] 42:2@5..6#2 + LITERAL Integer 0 42:2@7..8#2 + PUNCH , [alone] 42:2@8..9#2 + LITERAL Integer 1 42:2@10..11#2 + PUNCH , [alone] 42:2@11..12#2 + SUBTREE [] 42:2@13..14#2 42:2@14..15#2"#]], ); } @@ -75,10 +75,10 @@ fn test_fn_like_macro_clone_ident_subtree() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT ident 42:2@0..5#0 - PUNCH , [alone] 42:2@5..6#0 - SUBTREE [] 42:2@7..8#0 42:2@7..8#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT ident 42:2@0..5#2 + PUNCH , [alone] 42:2@5..6#2 + SUBTREE [] 42:2@7..8#2 42:2@7..8#2"#]], ); } @@ -91,8 +91,8 @@ fn test_fn_like_macro_clone_raw_ident() { SUBTREE $$ 1 1 IDENT r#async 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT r#async 42:2@0..7#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT r#async 42:2@0..7#2"#]], ); } @@ -105,8 +105,8 @@ fn test_fn_like_fn_like_span_join() { SUBTREE $$ 1 1 IDENT r#joined 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT r#joined 42:2@0..11#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT r#joined 42:2@0..11#2"#]], ); } @@ -121,10 +121,10 @@ fn test_fn_like_fn_like_span_ops() { IDENT resolved_at_def_site 1 IDENT start_span 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT set_def_site 41:1@0..150#0 - IDENT resolved_at_def_site 42:2@13..33#0 - IDENT start_span 42:2@34..34#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT set_def_site 41:1@0..150#2 + IDENT resolved_at_def_site 42:2@13..33#2 + IDENT start_span 42:2@34..34#2"#]], ); } @@ -143,14 +143,14 @@ fn test_fn_like_mk_literals() { LITERAL Integer 123i64 1 LITERAL Integer 123 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - LITERAL ByteStr byte_string 42:2@0..100#0 - LITERAL Char c 42:2@0..100#0 - LITERAL Str string 42:2@0..100#0 - LITERAL Float 3.14f64 42:2@0..100#0 - LITERAL Float 3.14 42:2@0..100#0 - LITERAL Integer 123i64 42:2@0..100#0 - LITERAL Integer 123 42:2@0..100#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + LITERAL ByteStr byte_string 42:2@0..100#2 + LITERAL Char c 42:2@0..100#2 + LITERAL Str string 42:2@0..100#2 + LITERAL Float 3.14f64 42:2@0..100#2 + LITERAL Float 3.14 42:2@0..100#2 + LITERAL Integer 123i64 42:2@0..100#2 + LITERAL Integer 123 42:2@0..100#2"#]], ); } @@ -164,9 +164,9 @@ fn test_fn_like_mk_idents() { IDENT standard 1 IDENT r#raw 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT standard 42:2@0..100#0 - IDENT r#raw 42:2@0..100#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT standard 42:2@0..100#2 + IDENT r#raw 42:2@0..100#2"#]], ); } @@ -198,27 +198,27 @@ fn test_fn_like_macro_clone_literals() { PUNCH , [alone] 1 LITERAL CStr null 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - LITERAL Integer 1u16 42:2@0..4#0 - PUNCH , [alone] 42:2@4..5#0 - LITERAL Integer 2_u32 42:2@6..11#0 - PUNCH , [alone] 42:2@11..12#0 - PUNCH - [alone] 42:2@13..14#0 - LITERAL Integer 4i64 42:2@14..18#0 - PUNCH , [alone] 42:2@18..19#0 - LITERAL Float 3.14f32 42:2@20..27#0 - PUNCH , [alone] 42:2@27..28#0 - LITERAL Str hello bridge 42:2@29..43#0 - PUNCH , [alone] 42:2@43..44#0 - LITERAL Str suffixedsuffix 42:2@45..61#0 - PUNCH , [alone] 42:2@61..62#0 - LITERAL StrRaw(2) raw 42:2@63..73#0 - PUNCH , [alone] 42:2@73..74#0 - LITERAL Char a 42:2@75..78#0 - PUNCH , [alone] 42:2@78..79#0 - LITERAL Byte b 42:2@80..84#0 - PUNCH , [alone] 42:2@84..85#0 - LITERAL CStr null 42:2@86..93#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + LITERAL Integer 1u16 42:2@0..4#2 + PUNCH , [alone] 42:2@4..5#2 + LITERAL Integer 2_u32 42:2@6..11#2 + PUNCH , [alone] 42:2@11..12#2 + PUNCH - [alone] 42:2@13..14#2 + LITERAL Integer 4i64 42:2@14..18#2 + PUNCH , [alone] 42:2@18..19#2 + LITERAL Float 3.14f32 42:2@20..27#2 + PUNCH , [alone] 42:2@27..28#2 + LITERAL Str hello bridge 42:2@29..43#2 + PUNCH , [alone] 42:2@43..44#2 + LITERAL Str suffixedsuffix 42:2@45..61#2 + PUNCH , [alone] 42:2@61..62#2 + LITERAL StrRaw(2) raw 42:2@63..73#2 + PUNCH , [alone] 42:2@73..74#2 + LITERAL Char a 42:2@75..78#2 + PUNCH , [alone] 42:2@78..79#2 + LITERAL Byte b 42:2@80..84#2 + PUNCH , [alone] 42:2@84..85#2 + LITERAL CStr null 42:2@86..93#2"#]], ); } @@ -239,12 +239,12 @@ fn test_attr_macro() { LITERAL Str #[attr_error(some arguments)] mod m {} 1 PUNCH ; [alone] 1"#]], expect![[r#" - SUBTREE $$ 42:2@0..100#0 42:2@0..100#0 - IDENT compile_error 42:2@0..100#0 - PUNCH ! [alone] 42:2@0..100#0 - SUBTREE () 42:2@0..100#0 42:2@0..100#0 - LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#0 - PUNCH ; [alone] 42:2@0..100#0"#]], + SUBTREE $$ 42:2@0..100#2 42:2@0..100#2 + IDENT compile_error 42:2@0..100#2 + PUNCH ! [alone] 42:2@0..100#2 + SUBTREE () 42:2@0..100#2 42:2@0..100#2 + LITERAL Str #[attr_error(some arguments)] mod m {} 42:2@0..100#2 + PUNCH ; [alone] 42:2@0..100#2"#]], ); } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs index 37d51050f32..4ce4544243a 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs @@ -28,13 +28,18 @@ fn parse_string_spanned( )) } -pub fn assert_expand(macro_name: &str, ra_fixture: &str, expect: Expect, expect_s: Expect) { +pub fn assert_expand( + macro_name: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, + expect: Expect, + expect_s: Expect, +) { assert_expand_impl(macro_name, ra_fixture, None, expect, expect_s); } pub fn assert_expand_attr( macro_name: &str, - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, attr_args: &str, expect: Expect, expect_s: Expect, @@ -76,7 +81,7 @@ fn assert_expand_impl( file_id: EditionedFileId::current_edition(FileId::from_raw(41)), ast_id: ErasedFileAstId::from_raw(1), }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::CURRENT), }; let call_site = Span { range: TextRange::new(0.into(), 100.into()), @@ -84,7 +89,7 @@ fn assert_expand_impl( file_id: EditionedFileId::current_edition(FileId::from_raw(42)), ast_id: ErasedFileAstId::from_raw(2), }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(span::Edition::CURRENT), }; let mixed_site = call_site; diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml index 2e3413f339b..3179c810f69 100644 --- a/src/tools/rust-analyzer/crates/profile/Cargo.toml +++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml @@ -21,7 +21,10 @@ jemalloc-ctl = { version = "0.5.0", package = "tikv-jemalloc-ctl", optional = tr perf-event = "=0.4.7" [target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.52", features = ["Win32_System_Threading", "Win32_System_ProcessStatus"] } +windows-sys = { version = "0.59", features = [ + "Win32_System_Threading", + "Win32_System_ProcessStatus", +] } [features] cpu_profiler = [] diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs index 4d906c2aeb3..e4a61134620 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs @@ -92,6 +92,8 @@ pub struct CargoConfig { pub sysroot_src: Option<AbsPathBuf>, /// rustc private crate source pub rustc_source: Option<RustLibSource>, + /// Extra includes to add to the VFS. + pub extra_includes: Vec<AbsPathBuf>, pub cfg_overrides: CfgOverrides, /// Invoke `cargo check` through the RUSTC_WRAPPER. pub wrap_rustc_in_build_scripts: bool, diff --git a/src/tools/rust-analyzer/crates/project-model/src/tests.rs b/src/tools/rust-analyzer/crates/project-model/src/tests.rs index 681bce3a5a6..f1113831125 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs @@ -49,6 +49,7 @@ fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace { rustc_cfg: Vec::new(), toolchain: None, target_layout: Err("target_data_layout not loaded".into()), + extra_includes: Vec::new(), } } @@ -63,6 +64,7 @@ fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) { toolchain: None, target_layout: Err(Arc::from("test has no data layout")), cfg_overrides: Default::default(), + extra_includes: Vec::new(), }; to_crate_graph(project_workspace, &mut Default::default()) } @@ -284,6 +286,7 @@ fn smoke_test_real_sysroot_cargo() { cfg_overrides: Default::default(), toolchain: None, target_layout: Err("target_data_layout not loaded".into()), + extra_includes: Vec::new(), }; project_workspace.to_crate_graph( &mut { diff --git a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs index afcc8120794..4bf9b59e7d0 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs @@ -66,7 +66,7 @@ fn rustc_print_cfg( QueryConfig::Cargo(sysroot, cargo_toml) => { let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent()); cmd.envs(extra_env); - cmd.args(["rustc"]).args(RUSTC_ARGS); + cmd.args(["rustc", "-Z", "unstable-options"]).args(RUSTC_ARGS); if let Some(target) = target { cmd.args(["--target", target]); } diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs index a345c6bcce4..f98d983ac06 100644 --- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs +++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs @@ -11,9 +11,8 @@ use base_db::{ }; use cfg::{CfgAtom, CfgDiff, CfgOptions}; use intern::{sym, Symbol}; -use itertools::Itertools; use paths::{AbsPath, AbsPathBuf}; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use semver::Version; use span::{Edition, FileId}; use tracing::instrument; @@ -63,6 +62,8 @@ pub struct ProjectWorkspace { pub target_layout: TargetLayoutLoadResult, /// A set of cfg overrides for this workspace. pub cfg_overrides: CfgOverrides, + /// Additional includes to add for the VFS. + pub extra_includes: Vec<AbsPathBuf>, } #[derive(Clone)] @@ -104,7 +105,15 @@ pub enum ProjectWorkspaceKind { impl fmt::Debug for ProjectWorkspace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Make sure this isn't too verbose. - let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides } = self; + let Self { + kind, + sysroot, + rustc_cfg, + toolchain, + target_layout, + cfg_overrides, + extra_includes, + } = self; match kind { ProjectWorkspaceKind::Cargo { cargo, error: _, build_scripts, rustc, set_test } => f .debug_struct("Cargo") @@ -117,6 +126,7 @@ impl fmt::Debug for ProjectWorkspace { ) .field("n_rustc_cfg", &rustc_cfg.len()) .field("n_cfg_overrides", &cfg_overrides.len()) + .field("n_extra_includes", &extra_includes.len()) .field("toolchain", &toolchain) .field("data_layout", &target_layout) .field("set_test", set_test) @@ -130,7 +140,8 @@ impl fmt::Debug for ProjectWorkspace { .field("n_rustc_cfg", &rustc_cfg.len()) .field("toolchain", &toolchain) .field("data_layout", &target_layout) - .field("n_cfg_overrides", &cfg_overrides.len()); + .field("n_cfg_overrides", &cfg_overrides.len()) + .field("n_extra_includes", &extra_includes.len()); debug_struct.finish() } @@ -144,6 +155,7 @@ impl fmt::Debug for ProjectWorkspace { .field("toolchain", &toolchain) .field("data_layout", &target_layout) .field("n_cfg_overrides", &cfg_overrides.len()) + .field("n_extra_includes", &extra_includes.len()) .field("set_test", set_test) .finish(), } @@ -320,6 +332,7 @@ impl ProjectWorkspace { cfg_overrides, toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), + extra_includes: config.extra_includes.clone(), }) } @@ -340,6 +353,7 @@ impl ProjectWorkspace { toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: config.cfg_overrides.clone(), + extra_includes: config.extra_includes.clone(), } } @@ -399,6 +413,7 @@ impl ProjectWorkspace { toolchain, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: config.cfg_overrides.clone(), + extra_includes: config.extra_includes.clone(), }) } @@ -565,13 +580,20 @@ impl ProjectWorkspace { PackageRoot { is_local: krate.is_workspace_member, - include: krate.include.iter().cloned().chain(build_file).collect(), + include: krate + .include + .iter() + .cloned() + .chain(build_file) + .chain(self.extra_includes.iter().cloned()) + .collect(), exclude: krate.exclude.clone(), } }) + .collect::<FxHashSet<_>>() + .into_iter() .chain(mk_sysroot()) - .unique() - .collect(), + .collect::<Vec<_>>(), ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _, set_test: _ } => { cargo .packages() @@ -603,6 +625,8 @@ impl ProjectWorkspace { let mut exclude = vec![pkg_root.join(".git")]; if is_local { + include.extend(self.extra_includes.iter().cloned()); + exclude.push(pkg_root.join("target")); } else { exclude.push(pkg_root.join("tests")); @@ -619,11 +643,6 @@ impl ProjectWorkspace { exclude: Vec::new(), }) })) - .chain(cargo.is_virtual_workspace().then(|| PackageRoot { - is_local: true, - include: vec![cargo.workspace_root().to_path_buf()], - exclude: Vec::new(), - })) .collect() } ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, .. } => { @@ -661,6 +680,8 @@ impl ProjectWorkspace { let mut exclude = vec![pkg_root.join(".git")]; if is_local { + include.extend(self.extra_includes.iter().cloned()); + exclude.push(pkg_root.join("target")); } else { exclude.push(pkg_root.join("tests")); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml index d06130ce8c5..c24cbb4a311 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml @@ -76,7 +76,10 @@ vfs.workspace = true paths.workspace = true [target.'cfg(windows)'.dependencies] -windows-sys = { version = "0.52", features = ["Win32_System_Diagnostics_Debug", "Win32_System_Threading"] } +windows-sys = { version = "0.59", features = [ + "Win32_System_Diagnostics_Debug", + "Win32_System_Threading", +] } [target.'cfg(not(target_env = "msvc"))'.dependencies] jemallocator = { version = "0.5.0", package = "tikv-jemallocator", optional = true } diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index afe3455b780..bcaec520195 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -1051,6 +1051,7 @@ impl flags::AnalysisStats { &InlayHintsConfig { render_colons: false, type_hints: true, + sized_bound: false, discriminant_hints: ide::DiscriminantHints::Always, parameter_hints: true, generic_parameter_hints: ide::GenericParameterHints { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs index 6b0ce4db7c9..199f61e70f0 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs @@ -93,6 +93,7 @@ impl Tester { toolchain: None, target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())), cfg_overrides: Default::default(), + extra_includes: vec![], }; let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: false, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs index 6ca7d9ac057..dc0f722aae6 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs @@ -518,7 +518,7 @@ mod test { use test_fixture::ChangeFixture; use vfs::VfsPath; - fn position(ra_fixture: &str) -> (AnalysisHost, FilePosition) { + fn position(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (AnalysisHost, FilePosition) { let mut host = AnalysisHost::default(); let change_fixture = ChangeFixture::parse(ra_fixture); host.raw_database_mut().apply_change(change_fixture.change); @@ -530,7 +530,7 @@ mod test { /// If expected == "", then assert that there are no symbols (this is basically local symbol) #[track_caller] - fn check_symbol(ra_fixture: &str, expected: &str) { + fn check_symbol(#[rust_analyzer::rust_fixture] ra_fixture: &str, expected: &str) { let (host, position) = position(ra_fixture); let analysis = host.analysis(); diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs index 30f0031905f..3dc4379258f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs @@ -185,6 +185,8 @@ config_data! { inlayHints_genericParameterHints_type_enable: bool = false, /// Whether to show implicit drop hints. inlayHints_implicitDrops_enable: bool = false, + /// Whether to show inlay hints for the implied type parameter `Sized` bound. + inlayHints_implicitSizedBoundHints_enable: bool = false, /// Whether to show inlay type hints for elided lifetimes in function signatures. inlayHints_lifetimeElisionHints_enable: LifetimeElisionDef = LifetimeElisionDef::Never, /// Whether to prefer using parameter names as the name for elided lifetime hints if possible. @@ -324,8 +326,16 @@ config_data! { /// Show documentation. signatureInfo_documentation_enable: bool = true, - /// Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`. - typing_excludeChars: Option<String> = Some("|<".to_owned()), + /// Specify the characters allowed to invoke special on typing triggers. + /// - typing `=` after `let` tries to smartly add `;` if `=` is followed by an existing expression + /// - typing `=` between two expressions adds `;` when in statement position + /// - typing `=` to turn an assignment into an equality comparison removes `;` when in expression position + /// - typing `.` in a chain method call auto-indents + /// - typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression + /// - typing `{` in a use item adds a closing `}` in the right place + /// - typing `>` to complete a return type `->` will insert a whitespace after it + /// - typing `<` in a path or type position inserts a closing `>` after the path or type. + typing_triggerChars: Option<String> = Some("=.".to_owned()), /// Enables automatic discovery of projects using [`DiscoverWorkspaceConfig::command`]. @@ -571,11 +581,8 @@ config_data! { /// avoid checking unnecessary things. cargo_buildScripts_useRustcWrapper: bool = true, /// List of cfg options to enable with the given values. - cargo_cfgs: FxHashMap<String, Option<String>> = { - let mut m = FxHashMap::default(); - m.insert("debug_assertions".to_owned(), None); - m.insert("miri".to_owned(), None); - m + cargo_cfgs: Vec<String> = { + vec!["debug_assertions".into(), "miri".into()] }, /// Extra arguments that are passed to every cargo invocation. cargo_extraArgs: Vec<String> = vec![], @@ -728,6 +735,10 @@ config_data! { /// available on a nightly build. rustfmt_rangeFormatting_enable: bool = false, + /// Additional paths to include in the VFS. Generally for code that is + /// generated or otherwise managed by a build system outside of Cargo, + /// though Cargo might be the eventual consumer. + vfs_extraIncludes: Vec<String> = vec![], /// Workspace symbol search kind. workspace_symbol_search_kind: WorkspaceSymbolSearchKindDef = WorkspaceSymbolSearchKindDef::OnlyTypes, @@ -1620,6 +1631,7 @@ impl Config { InlayHintsConfig { render_colons: self.inlayHints_renderColons().to_owned(), type_hints: self.inlayHints_typeHints_enable().to_owned(), + sized_bound: self.inlayHints_implicitSizedBoundHints_enable().to_owned(), parameter_hints: self.inlayHints_parameterHints_enable().to_owned(), generic_parameter_hints: GenericParameterHints { type_hints: self.inlayHints_genericParameterHints_type_enable().to_owned(), @@ -1926,6 +1938,13 @@ impl Config { }); let sysroot_src = self.cargo_sysrootSrc(source_root).as_ref().map(|sysroot| self.root_path.join(sysroot)); + let extra_includes = self + .vfs_extraIncludes(source_root) + .iter() + .map(String::as_str) + .map(AbsPathBuf::try_from) + .filter_map(Result::ok) + .collect(); CargoConfig { all_targets: *self.cargo_allTargets(source_root), @@ -1940,10 +1959,18 @@ impl Config { sysroot, sysroot_src, rustc_source, + extra_includes, cfg_overrides: project_model::CfgOverrides { global: CfgDiff::new( self.cargo_cfgs(source_root) .iter() + // parse any cfg setting formatted as key=value or just key (without value) + .filter_map(|s| { + let mut sp = s.splitn(2, "="); + let key = sp.next(); + let val = sp.next(); + key.map(|key| (key, val)) + }) .map(|(key, val)| match val { Some(val) => CfgAtom::KeyValue { key: Symbol::intern(key), @@ -2232,8 +2259,8 @@ impl Config { } } - pub fn typing_exclude_chars(&self) -> Option<String> { - self.typing_excludeChars().clone() + pub fn typing_trigger_chars(&self) -> &str { + self.typing_triggerChars().as_deref().unwrap_or_default() } // VSCode is our reference implementation, so we allow ourselves to work around issues by diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs index 7ac70efe2d6..190015d7faa 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs @@ -136,15 +136,13 @@ pub(crate) fn handle_memory_usage(state: &mut GlobalState, _: ()) -> anyhow::Res Ok(out) } -pub(crate) fn handle_syntax_tree( +pub(crate) fn handle_view_syntax_tree( snap: GlobalStateSnapshot, - params: lsp_ext::SyntaxTreeParams, + params: lsp_ext::ViewSyntaxTreeParams, ) -> anyhow::Result<String> { - let _p = tracing::info_span!("handle_syntax_tree").entered(); + let _p = tracing::info_span!("handle_view_syntax_tree").entered(); let id = from_proto::file_id(&snap, ¶ms.text_document.uri)?; - let line_index = snap.file_line_index(id)?; - let text_range = params.range.and_then(|r| from_proto::text_range(&line_index, r).ok()); - let res = snap.analysis.syntax_tree(id, text_range)?; + let res = snap.analysis.view_syntax_tree(id)?; Ok(res) } @@ -436,29 +434,24 @@ pub(crate) fn handle_on_type_formatting( params: lsp_types::DocumentOnTypeFormattingParams, ) -> anyhow::Result<Option<Vec<lsp_ext::SnippetTextEdit>>> { let _p = tracing::info_span!("handle_on_type_formatting").entered(); + let char_typed = params.ch.chars().next().unwrap_or('\0'); + if !snap.config.typing_trigger_chars().contains(char_typed) { + return Ok(None); + } + let mut position = from_proto::file_position(&snap, params.text_document_position)?; let line_index = snap.file_line_index(position.file_id)?; // in `ide`, the `on_type` invariant is that // `text.char_at(position) == typed_char`. position.offset -= TextSize::of('.'); - let char_typed = params.ch.chars().next().unwrap_or('\0'); let text = snap.analysis.file_text(position.file_id)?; if stdx::never!(!text[usize::from(position.offset)..].starts_with(char_typed)) { return Ok(None); } - // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`, - // but it requires precise cursor positioning to work, and one can't - // position the cursor with on_type formatting. So, let's just toggle this - // feature off here, hoping that we'll enable it one day, 😿. - if char_typed == '>' { - return Ok(None); - } - let chars_to_exclude = snap.config.typing_exclude_chars(); - - let edit = snap.analysis.on_char_typed(position, char_typed, chars_to_exclude)?; + let edit = snap.analysis.on_char_typed(position, char_typed)?; let edit = match edit { Some(it) => it, None => return Ok(None), diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs index e7f5a7f5e78..61ec576dd4f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs @@ -47,7 +47,8 @@ use self::lsp::ext as lsp_ext; #[cfg(test)] mod integrated_benchmarks; -use ide::{CompletionItem, CompletionRelevance}; +use hir::Mutability; +use ide::{CompletionItem, CompletionItemRefMode, CompletionRelevance}; use serde::de::DeserializeOwned; use tenthash::TentHasher; @@ -132,8 +133,13 @@ fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8; hasher.update(detail); } hash_completion_relevance(&mut hasher, &item.relevance); - if let Some((mutability, text_size)) = &item.ref_match { - hasher.update(mutability.as_keyword_for_ref()); + if let Some((ref_mode, text_size)) = &item.ref_match { + let prefix = match ref_mode { + CompletionItemRefMode::Reference(Mutability::Shared) => "&", + CompletionItemRefMode::Reference(Mutability::Mut) => "&mut ", + CompletionItemRefMode::Dereference => "*", + }; + hasher.update(prefix); hasher.update(u32::from(*text_size).to_le_bytes()); } for (import_path, import_name) in &item.import_to_add { diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs index f50cbba7acf..134de92feab 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs @@ -108,19 +108,18 @@ impl Request for RebuildProcMacros { const METHOD: &'static str = "rust-analyzer/rebuildProcMacros"; } -pub enum SyntaxTree {} +pub enum ViewSyntaxTree {} -impl Request for SyntaxTree { - type Params = SyntaxTreeParams; +impl Request for ViewSyntaxTree { + type Params = ViewSyntaxTreeParams; type Result = String; - const METHOD: &'static str = "rust-analyzer/syntaxTree"; + const METHOD: &'static str = "rust-analyzer/viewSyntaxTree"; } #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] -pub struct SyntaxTreeParams { +pub struct ViewSyntaxTreeParams { pub text_document: TextDocumentIdentifier, - pub range: Option<Range>, } pub enum ViewHir {} diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs index fe4d02dcb4f..a5516e7f9d4 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs @@ -547,7 +547,18 @@ pub(crate) fn inlay_hint( file_id: FileId, mut inlay_hint: InlayHint, ) -> Cancellable<lsp_types::InlayHint> { - let resolve_range_and_hash = inlay_hint.needs_resolve().map(|range| { + let hint_needs_resolve = |hint: &InlayHint| -> Option<TextRange> { + hint.resolve_parent.filter(|_| { + hint.text_edit.is_some() + || hint + .label + .parts + .iter() + .any(|part| part.linked_location.is_some() || part.tooltip.is_some()) + }) + }; + + let resolve_range_and_hash = hint_needs_resolve(&inlay_hint).map(|range| { ( range, std::hash::BuildHasher::hash_one( @@ -568,7 +579,11 @@ pub(crate) fn inlay_hint( something_to_resolve |= inlay_hint.text_edit.is_some(); None } else { - inlay_hint.text_edit.take().map(|it| text_edit_vec(line_index, it)) + inlay_hint + .text_edit + .take() + .and_then(|it| it.computed()) + .map(|it| text_edit_vec(line_index, it)) }; let (label, tooltip) = inlay_hint_label( snap, @@ -626,7 +641,7 @@ fn inlay_hint_label( *something_to_resolve |= tooltip.is_some(); None } else { - match tooltip { + match tooltip.and_then(|it| it.computed()) { Some(ide::InlayTooltip::String(s)) => { Some(lsp_types::InlayHintTooltip::String(s)) } @@ -650,7 +665,7 @@ fn inlay_hint_label( *something_to_resolve |= part.tooltip.is_some(); None } else { - match part.tooltip { + match part.tooltip.and_then(|it| it.computed()) { Some(ide::InlayTooltip::String(s)) => { Some(lsp_types::InlayHintLabelPartTooltip::String(s)) } @@ -1993,7 +2008,7 @@ fn bar(_: usize) {} #[track_caller] fn check_rendered_snippets_in_source( - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, edit: TextEdit, snippets: SnippetEdit, expect: Expect, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs index 97657b92658..d6dc8b521fd 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs @@ -1145,7 +1145,7 @@ impl GlobalState { .on::<RETRY, lsp_ext::WorkspaceSymbol>(handlers::handle_workspace_symbol) .on::<NO_RETRY, lsp_ext::Ssr>(handlers::handle_ssr) .on::<NO_RETRY, lsp_ext::ViewRecursiveMemoryLayout>(handlers::handle_view_recursive_memory_layout) - .on::<NO_RETRY, lsp_ext::SyntaxTree>(handlers::handle_syntax_tree) + .on::<NO_RETRY, lsp_ext::ViewSyntaxTree>(handlers::handle_view_syntax_tree) .on::<NO_RETRY, lsp_ext::ViewHir>(handlers::handle_view_hir) .on::<NO_RETRY, lsp_ext::ViewMir>(handlers::handle_view_mir) .on::<NO_RETRY, lsp_ext::InterpretFunction>(handlers::handle_interpret_function) diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs index 503b3ee43a1..3edfb812cf5 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs @@ -18,7 +18,11 @@ pub(crate) enum TestState { Started, Ok, Ignored, - Failed { stdout: String }, + Failed { + // the stdout field is not always present depending on cargo test flags + #[serde(skip_serializing_if = "String::is_empty", default)] + stdout: String, + }, } #[derive(Debug, Deserialize)] diff --git a/src/tools/rust-analyzer/crates/span/src/hygiene.rs b/src/tools/rust-analyzer/crates/span/src/hygiene.rs index 87a948df550..6becc8e41ed 100644 --- a/src/tools/rust-analyzer/crates/span/src/hygiene.rs +++ b/src/tools/rust-analyzer/crates/span/src/hygiene.rs @@ -26,7 +26,7 @@ use crate::InternId; #[cfg(feature = "ra-salsa")] use ra_salsa::{InternId, InternValue}; -use crate::MacroCallId; +use crate::{Edition, MacroCallId}; /// Interned [`SyntaxContextData`]. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -59,11 +59,20 @@ impl fmt::Display for SyntaxContextId { } impl SyntaxContextId { + #[inline] + pub fn remove_root_edition(&mut self) { + if self.is_root() { + *self = Self::root(Edition::Edition2015); + } + } + /// The root context, which is the parent of all other contexts. All [`FileId`]s have this context. - pub const ROOT: Self = SyntaxContextId(unsafe { InternId::new_unchecked(0) }); + pub const fn root(edition: Edition) -> Self { + SyntaxContextId(unsafe { InternId::new_unchecked(edition as u32) }) + } pub fn is_root(self) -> bool { - self == Self::ROOT + self.into_u32() <= Edition::LATEST as u32 } /// Deconstruct a `SyntaxContextId` into a raw `u32`. @@ -89,6 +98,7 @@ pub struct SyntaxContextData { // per crate. Though that is likely not a problem as `MacroCallId`s are already crate calling dependent. pub outer_expn: Option<MacroCallId>, pub outer_transparency: Transparency, + pub edition: Edition, pub parent: SyntaxContextId, /// This context, but with all transparent and semi-transparent expansions filtered away. pub opaque: SyntaxContextId, @@ -98,10 +108,10 @@ pub struct SyntaxContextData { #[cfg(feature = "ra-salsa")] impl InternValue for SyntaxContextData { - type Key = (SyntaxContextId, Option<MacroCallId>, Transparency); + type Key = (SyntaxContextId, Option<MacroCallId>, Transparency, Edition); fn into_key(&self) -> Self::Key { - (self.parent, self.outer_expn, self.outer_transparency) + (self.parent, self.outer_expn, self.outer_transparency, self.edition) } } @@ -118,13 +128,14 @@ impl std::fmt::Debug for SyntaxContextData { } impl SyntaxContextData { - pub fn root() -> Self { + pub fn root(edition: Edition) -> Self { SyntaxContextData { outer_expn: None, outer_transparency: Transparency::Opaque, - parent: SyntaxContextId::ROOT, - opaque: SyntaxContextId::ROOT, - opaque_and_semitransparent: SyntaxContextId::ROOT, + parent: SyntaxContextId::root(edition), + opaque: SyntaxContextId::root(edition), + opaque_and_semitransparent: SyntaxContextId::root(edition), + edition, } } } diff --git a/src/tools/rust-analyzer/crates/span/src/map.rs b/src/tools/rust-analyzer/crates/span/src/map.rs index 66bbce18594..dc35de67fd8 100644 --- a/src/tools/rust-analyzer/crates/span/src/map.rs +++ b/src/tools/rust-analyzer/crates/span/src/map.rs @@ -208,7 +208,7 @@ impl RealSpanMap { Span { range: range - offset, anchor: SpanAnchor { file_id: self.file_id, ast_id }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(self.file_id.edition()), } } } diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml index bf0d6df9ad8..1ebb48c577a 100644 --- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml +++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml @@ -23,7 +23,7 @@ itertools.workspace = true [target.'cfg(windows)'.dependencies] miow = "0.6.0" -windows-sys = { version = "0.52", features = ["Win32_Foundation"] } +windows-sys = { version = "0.59", features = ["Win32_Foundation"] } [features] # Uncomment to enable for the whole crate graph diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs index ed8b1908d60..19801c49e43 100644 --- a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs +++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs @@ -1,6 +1,6 @@ //! Conversions between [`SyntaxNode`] and [`tt::TokenTree`]. -use std::fmt; +use std::{fmt, hash::Hash}; use intern::Symbol; use rustc_hash::{FxHashMap, FxHashSet}; @@ -58,7 +58,7 @@ pub mod dummy_test_span_utils { ), ast_id: span::ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), }; pub struct DummyTestSpanMap; @@ -74,7 +74,7 @@ pub mod dummy_test_span_utils { ), ast_id: span::ROOT_ERASED_FILE_AST_ID, }, - ctx: SyntaxContextId::ROOT, + ctx: SyntaxContextId::root(Edition::CURRENT), } } } @@ -141,15 +141,16 @@ where pub fn token_tree_to_syntax_node<Ctx>( tt: &tt::TopSubtree<SpanData<Ctx>>, entry_point: parser::TopEntryPoint, - edition: parser::Edition, + span_to_edition: &mut dyn FnMut(Ctx) -> Edition, + top_edition: Edition, ) -> (Parse<SyntaxNode>, SpanMap<Ctx>) where - SpanData<Ctx>: Copy + fmt::Debug, - Ctx: PartialEq, + Ctx: Copy + fmt::Debug + PartialEq + PartialEq + Eq + Hash, { let buffer = tt.view().strip_invisible(); - let parser_input = to_parser_input(edition, buffer); - let parser_output = entry_point.parse(&parser_input, edition); + let parser_input = to_parser_input(buffer, span_to_edition); + // It matters what edition we parse with even when we escape all identifiers correctly. + let parser_output = entry_point.parse(&parser_input, top_edition); let mut tree_sink = TtTreeSink::new(buffer.cursor()); for event in parser_output.iter() { match event { diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs index 1bbb05f5507..0dcb2be316c 100644 --- a/src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs +++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs @@ -2,17 +2,20 @@ //! format that works for our parser. use std::fmt; +use std::hash::Hash; -use span::Edition; +use rustc_hash::FxHashMap; +use span::{Edition, SpanData}; use syntax::{SyntaxKind, SyntaxKind::*, T}; -pub fn to_parser_input<S: Copy + fmt::Debug>( - edition: Edition, - buffer: tt::TokenTreesView<'_, S>, +pub fn to_parser_input<Ctx: Copy + fmt::Debug + PartialEq + Eq + Hash>( + buffer: tt::TokenTreesView<'_, SpanData<Ctx>>, + span_to_edition: &mut dyn FnMut(Ctx) -> Edition, ) -> parser::Input { let mut res = parser::Input::default(); let mut current = buffer.cursor(); + let mut syntax_context_to_edition_cache = FxHashMap::default(); while !current.eof() { let tt = current.token_tree(); @@ -57,20 +60,25 @@ pub fn to_parser_input<S: Copy + fmt::Debug>( res.was_joint(); } } - tt::Leaf::Ident(ident) => match ident.sym.as_str() { - "_" => res.push(T![_]), - i if i.starts_with('\'') => res.push(LIFETIME_IDENT), - _ if ident.is_raw.yes() => res.push(IDENT), - text => match SyntaxKind::from_keyword(text, edition) { - Some(kind) => res.push(kind), - None => { - let contextual_keyword = - SyntaxKind::from_contextual_keyword(text, edition) - .unwrap_or(SyntaxKind::IDENT); - res.push_ident(contextual_keyword); - } - }, - }, + tt::Leaf::Ident(ident) => { + let edition = *syntax_context_to_edition_cache + .entry(ident.span.ctx) + .or_insert_with(|| span_to_edition(ident.span.ctx)); + match ident.sym.as_str() { + "_" => res.push(T![_]), + i if i.starts_with('\'') => res.push(LIFETIME_IDENT), + _ if ident.is_raw.yes() => res.push(IDENT), + text => match SyntaxKind::from_keyword(text, edition) { + Some(kind) => res.push(kind), + None => { + let contextual_keyword = + SyntaxKind::from_contextual_keyword(text, edition) + .unwrap_or(SyntaxKind::IDENT); + res.push_ident(contextual_keyword); + } + }, + } + } tt::Leaf::Punct(punct) => { let kind = SyntaxKind::from_char(punct.char) .unwrap_or_else(|| panic!("{punct:#?} is not a valid punct")); diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs index de40d638be3..579f3ba8b4f 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs @@ -153,8 +153,8 @@ impl<N: AstNode + Clone> AstNodeEdit for N {} #[test] fn test_increase_indent() { let arm_list = { - let arm = make::match_arm(iter::once(make::wildcard_pat().into()), None, make::expr_unit()); - make::match_arm_list(vec![arm.clone(), arm]) + let arm = make::match_arm(make::wildcard_pat().into(), None, make::ext::expr_unit()); + make::match_arm_list([arm.clone(), arm]) }; assert_eq!( arm_list.syntax().to_string(), diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs index 9466755576b..93faeb40c32 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs @@ -10,7 +10,7 @@ use crate::{ FormatArgsArg, FormatArgsExpr, MacroDef, Static, TokenTree, }, AstToken, - SyntaxKind::*, + SyntaxKind::{self, *}, SyntaxNode, SyntaxToken, T, }; @@ -50,6 +50,27 @@ impl From<ast::IfExpr> for ElseBranch { } } +impl AstNode for ElseBranch { + fn can_cast(kind: SyntaxKind) -> bool { + ast::BlockExpr::can_cast(kind) || ast::IfExpr::can_cast(kind) + } + + fn cast(syntax: SyntaxNode) -> Option<Self> { + if let Some(block_expr) = ast::BlockExpr::cast(syntax.clone()) { + Some(Self::Block(block_expr)) + } else { + ast::IfExpr::cast(syntax).map(Self::IfExpr) + } + } + + fn syntax(&self) -> &SyntaxNode { + match self { + ElseBranch::Block(block_expr) => block_expr.syntax(), + ElseBranch::IfExpr(if_expr) => if_expr.syntax(), + } + } +} + impl ast::IfExpr { pub fn condition(&self) -> Option<ast::Expr> { // If the condition is a BlockExpr, check if the then body is missing. diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs index 282cbc4b3a4..dca231604fa 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs @@ -63,6 +63,9 @@ pub mod ext { Some(expr) } + pub fn expr_unit() -> ast::Expr { + expr_tuple([]).into() + } pub fn expr_unreachable() -> ast::Expr { expr_from_text("unreachable!()") } @@ -546,10 +549,6 @@ pub fn hacky_block_expr( ast_from_text(&format!("fn f() {buf}")) } -pub fn expr_unit() -> ast::Expr { - expr_from_text("()") -} - pub fn expr_literal(text: &str) -> ast::Literal { assert_eq!(text.trim(), text); ast_from_text(&format!("fn f() {{ let _ = {text}; }}")) @@ -559,8 +558,8 @@ pub fn expr_const_value(text: &str) -> ast::ConstArg { ast_from_text(&format!("trait Foo<const N: usize = {text}> {{}}")) } -pub fn expr_empty_block() -> ast::Expr { - expr_from_text("{}") +pub fn expr_empty_block() -> ast::BlockExpr { + ast_from_text("const C: () = {};") } pub fn expr_path(path: ast::Path) -> ast::Expr { expr_from_text(&path.to_string()) @@ -600,14 +599,14 @@ pub fn expr_try(expr: ast::Expr) -> ast::Expr { pub fn expr_await(expr: ast::Expr) -> ast::Expr { expr_from_text(&format!("{expr}.await")) } -pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr { +pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::MatchExpr { expr_from_text(&format!("match {expr} {match_arm_list}")) } pub fn expr_if( condition: ast::Expr, then_branch: ast::BlockExpr, else_branch: Option<ast::ElseBranch>, -) -> ast::Expr { +) -> ast::IfExpr { let else_branch = match else_branch { Some(ast::ElseBranch::Block(block)) => format!("else {block}"), Some(ast::ElseBranch::IfExpr(if_expr)) => format!("else {if_expr}"), @@ -623,7 +622,7 @@ pub fn expr_loop(block: ast::BlockExpr) -> ast::Expr { expr_from_text(&format!("loop {block}")) } -pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr { +pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::PrefixExpr { let token = token(op); expr_from_text(&format!("{token}{expr}")) } @@ -656,14 +655,14 @@ pub fn expr_field(receiver: ast::Expr, field: &str) -> ast::Expr { pub fn expr_paren(expr: ast::Expr) -> ast::Expr { expr_from_text(&format!("({expr})")) } -pub fn expr_tuple(elements: impl IntoIterator<Item = ast::Expr>) -> ast::Expr { +pub fn expr_tuple(elements: impl IntoIterator<Item = ast::Expr>) -> ast::TupleExpr { let expr = elements.into_iter().format(", "); expr_from_text(&format!("({expr})")) } pub fn expr_assignment(lhs: ast::Expr, rhs: ast::Expr) -> ast::Expr { expr_from_text(&format!("{lhs} = {rhs}")) } -fn expr_from_text(text: &str) -> ast::Expr { +fn expr_from_text<E: Into<ast::Expr> + AstNode>(text: &str) -> E { ast_from_text(&format!("const C: () = {text};")) } pub fn expr_let(pattern: ast::Pat, expr: ast::Expr) -> ast::LetExpr { @@ -788,15 +787,21 @@ pub fn path_pat(path: ast::Path) -> ast::Pat { } } -pub fn match_arm( - pats: impl IntoIterator<Item = ast::Pat>, - guard: Option<ast::Expr>, - expr: ast::Expr, -) -> ast::MatchArm { - let pats_str = pats.into_iter().join(" | "); +/// Returns a `Pat` if the path has just one segment, an `OrPat` otherwise. +pub fn or_pat(pats: impl IntoIterator<Item = ast::Pat>, leading_pipe: bool) -> ast::Pat { + let leading_pipe = if leading_pipe { "| " } else { "" }; + let pats = pats.into_iter().join(" | "); + + return from_text(&format!("{leading_pipe}{pats}")); + fn from_text(text: &str) -> ast::Pat { + ast_from_text(&format!("fn f({text}: ())")) + } +} + +pub fn match_arm(pat: ast::Pat, guard: Option<ast::MatchGuard>, expr: ast::Expr) -> ast::MatchArm { return match guard { - Some(guard) => from_text(&format!("{pats_str} if {guard} => {expr}")), - None => from_text(&format!("{pats_str} => {expr}")), + Some(guard) => from_text(&format!("{pat} {guard} => {expr}")), + None => from_text(&format!("{pat} => {expr}")), }; fn from_text(text: &str) -> ast::MatchArm { @@ -817,6 +822,14 @@ pub fn match_arm_with_guard( } } +pub fn match_guard(condition: ast::Expr) -> ast::MatchGuard { + return from_text(&format!("if {condition}")); + + fn from_text(text: &str) -> ast::MatchGuard { + ast_from_text(&format!("fn f() {{ match () {{() {text} => () }}")) + } +} + pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList { let arms_str = arms.into_iter().fold(String::new(), |mut acc, arm| { let needs_comma = arm.expr().is_none_or(|it| !it.is_block_like()); diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs index 81c7e15bcbc..56f94b965e3 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs @@ -185,6 +185,14 @@ impl ast::Attr { Some((self.simple_name()?, tt)) } + pub fn as_simple_path(&self) -> Option<ast::Path> { + let meta = self.meta()?; + if meta.eq_token().is_some() || meta.token_tree().is_some() { + return None; + } + self.path() + } + pub fn simple_name(&self) -> Option<SmolStr> { let path = self.meta()?.path()?; match (path.segment(), path.qualifier()) { diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs index bea6bfeafcf..572622db544 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -1,6 +1,9 @@ //! Wrappers over [`make`] constructors use crate::{ - ast::{self, make, HasGenericParams, HasName, HasTypeBounds, HasVisibility}, + ast::{ + self, make, HasArgList, HasGenericArgs, HasGenericParams, HasName, HasTypeBounds, + HasVisibility, + }, syntax_editor::SyntaxMappingBuilder, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken, }; @@ -12,6 +15,14 @@ impl SyntaxFactory { make::name(name).clone_for_update() } + pub fn name_ref(&self, name: &str) -> ast::NameRef { + make::name_ref(name).clone_for_update() + } + + pub fn lifetime(&self, text: &str) -> ast::Lifetime { + make::lifetime(text).clone_for_update() + } + pub fn ty(&self, text: &str) -> ast::Type { make::ty(text).clone_for_update() } @@ -24,6 +35,20 @@ impl SyntaxFactory { ast } + pub fn ty_path(&self, path: ast::Path) -> ast::PathType { + let ast::Type::PathType(ast) = make::ty_path(path.clone()).clone_for_update() else { + unreachable!() + }; + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + pub fn type_param( &self, name: ast::Name, @@ -46,6 +71,71 @@ impl SyntaxFactory { ast } + pub fn path_segment(&self, name_ref: ast::NameRef) -> ast::PathSegment { + let ast = make::path_segment(name_ref.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(name_ref.syntax().clone(), ast.name_ref().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn path_segment_generics( + &self, + name_ref: ast::NameRef, + generic_arg_list: ast::GenericArgList, + ) -> ast::PathSegment { + let ast::Type::PathType(path) = make::ty(&format!("{name_ref}{generic_arg_list}")) else { + unreachable!(); + }; + + let ast = path.path().unwrap().segment().unwrap().clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(name_ref.syntax().clone(), ast.name_ref().unwrap().syntax().clone()); + builder.map_node( + generic_arg_list.syntax().clone(), + ast.generic_arg_list().unwrap().syntax().clone(), + ); + builder.finish(&mut mapping); + } + + ast + } + + pub fn path_unqualified(&self, segment: ast::PathSegment) -> ast::Path { + let ast = make::path_unqualified(segment.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(segment.syntax().clone(), ast.segment().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn path_from_segments( + &self, + segments: impl IntoIterator<Item = ast::PathSegment>, + is_abs: bool, + ) -> ast::Path { + let (segments, input) = iterator_input(segments); + let ast = make::path_from_segments(segments, is_abs).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_children(input.into_iter(), ast.segments().map(|it| it.syntax().clone())); + builder.finish(&mut mapping); + } + + ast + } + pub fn ident_pat(&self, ref_: bool, mut_: bool, name: ast::Name) -> ast::IdentPat { let ast = make::ident_pat(ref_, mut_, name.clone()).clone_for_update(); @@ -58,6 +148,32 @@ impl SyntaxFactory { ast } + pub fn wildcard_pat(&self) -> ast::WildcardPat { + make::wildcard_pat().clone_for_update() + } + + pub fn literal_pat(&self, text: &str) -> ast::LiteralPat { + make::literal_pat(text).clone_for_update() + } + + pub fn tuple_struct_pat( + &self, + path: ast::Path, + fields: impl IntoIterator<Item = ast::Pat>, + ) -> ast::TupleStructPat { + let (fields, input) = iterator_input(fields); + let ast = make::tuple_struct_pat(path.clone(), fields).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone()); + builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone())); + builder.finish(&mut mapping); + } + + ast + } + pub fn block_expr( &self, statements: impl IntoIterator<Item = ast::Stmt>, @@ -95,7 +211,20 @@ impl SyntaxFactory { } pub fn expr_empty_block(&self) -> ast::BlockExpr { - ast::BlockExpr { syntax: make::expr_empty_block().syntax().clone_for_update() } + make::expr_empty_block().clone_for_update() + } + + pub fn expr_tuple(&self, fields: impl IntoIterator<Item = ast::Expr>) -> ast::TupleExpr { + let (fields, input) = iterator_input(fields); + let ast = make::expr_tuple(fields).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone())); + builder.finish(&mut mapping); + } + + ast } pub fn expr_bin(&self, lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::BinExpr { @@ -115,6 +244,10 @@ impl SyntaxFactory { ast } + pub fn expr_literal(&self, text: &str) -> ast::Literal { + make::expr_literal(text).clone_for_update() + } + pub fn expr_path(&self, path: ast::Path) -> ast::Expr { let ast::Expr::PathExpr(ast) = make::expr_path(path.clone()).clone_for_update() else { unreachable!() @@ -129,6 +262,49 @@ impl SyntaxFactory { ast.into() } + pub fn expr_prefix(&self, op: SyntaxKind, expr: ast::Expr) -> ast::PrefixExpr { + let ast = make::expr_prefix(op, expr.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn expr_call(&self, expr: ast::Expr, arg_list: ast::ArgList) -> ast::CallExpr { + // FIXME: `make::expr_call`` should return a `CallExpr`, not just an `Expr` + let ast::Expr::CallExpr(ast) = + make::expr_call(expr.clone(), arg_list.clone()).clone_for_update() + else { + unreachable!() + }; + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone()); + builder.map_node(arg_list.syntax().clone(), ast.arg_list().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn arg_list(&self, args: impl IntoIterator<Item = ast::Expr>) -> ast::ArgList { + let (args, input) = iterator_input(args); + let ast = make::arg_list(args).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax.clone()); + builder.map_children(input.into_iter(), ast.args().map(|it| it.syntax().clone())); + builder.finish(&mut mapping); + } + + ast + } + pub fn expr_ref(&self, expr: ast::Expr, exclusive: bool) -> ast::Expr { let ast::Expr::RefExpr(ast) = make::expr_ref(expr.clone(), exclusive).clone_for_update() else { @@ -160,6 +336,125 @@ impl SyntaxFactory { ast } + pub fn expr_if( + &self, + condition: ast::Expr, + then_branch: ast::BlockExpr, + else_branch: Option<ast::ElseBranch>, + ) -> ast::IfExpr { + let ast = make::expr_if(condition.clone(), then_branch.clone(), else_branch.clone()) + .clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(condition.syntax().clone(), ast.condition().unwrap().syntax().clone()); + builder.map_node( + then_branch.syntax().clone(), + ast.then_branch().unwrap().syntax().clone(), + ); + + if let Some(else_branch) = else_branch { + builder.map_node( + else_branch.syntax().clone(), + ast.else_branch().unwrap().syntax().clone(), + ); + } + builder.finish(&mut mapping); + } + + ast + } + + pub fn expr_let(&self, pattern: ast::Pat, expr: ast::Expr) -> ast::LetExpr { + let ast = make::expr_let(pattern.clone(), expr.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(pattern.syntax().clone(), ast.pat().unwrap().syntax().clone()); + builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn expr_stmt(&self, expr: ast::Expr) -> ast::ExprStmt { + let ast = make::expr_stmt(expr.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn expr_match(&self, expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::MatchExpr { + let ast = make::expr_match(expr.clone(), match_arm_list.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone()); + builder.map_node( + match_arm_list.syntax().clone(), + ast.match_arm_list().unwrap().syntax().clone(), + ); + builder.finish(&mut mapping); + } + + ast + } + + pub fn match_arm( + &self, + pat: ast::Pat, + guard: Option<ast::MatchGuard>, + expr: ast::Expr, + ) -> ast::MatchArm { + let ast = make::match_arm(pat.clone(), guard.clone(), expr.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone()); + if let Some(guard) = guard { + builder.map_node(guard.syntax().clone(), ast.guard().unwrap().syntax().clone()); + } + builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn match_guard(&self, condition: ast::Expr) -> ast::MatchGuard { + let ast = make::match_guard(condition.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(condition.syntax().clone(), ast.condition().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn match_arm_list( + &self, + match_arms: impl IntoIterator<Item = ast::MatchArm>, + ) -> ast::MatchArmList { + let (match_arms, input) = iterator_input(match_arms); + let ast = make::match_arm_list(match_arms).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_children(input.into_iter(), ast.arms().map(|it| it.syntax().clone())); + builder.finish(&mut mapping); + } + + ast + } + pub fn let_stmt( &self, pattern: ast::Pat, @@ -185,6 +480,30 @@ impl SyntaxFactory { ast } + pub fn type_arg(&self, ty: ast::Type) -> ast::TypeArg { + let ast = make::type_arg(ty.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(ty.syntax().clone(), ast.ty().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + + pub fn lifetime_arg(&self, lifetime: ast::Lifetime) -> ast::LifetimeArg { + let ast = make::lifetime_arg(lifetime.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + builder.map_node(lifetime.syntax().clone(), ast.lifetime().unwrap().syntax().clone()); + builder.finish(&mut mapping); + } + + ast + } + pub fn item_const( &self, visibility: Option<ast::Visibility>, @@ -252,12 +571,17 @@ impl SyntaxFactory { ast } - pub fn turbofish_generic_arg_list( + pub fn generic_arg_list( &self, generic_args: impl IntoIterator<Item = ast::GenericArg>, + is_turbo: bool, ) -> ast::GenericArgList { let (generic_args, input) = iterator_input(generic_args); - let ast = make::turbofish_generic_arg_list(generic_args.clone()).clone_for_update(); + let ast = if is_turbo { + make::turbofish_generic_arg_list(generic_args).clone_for_update() + } else { + make::generic_arg_list(generic_args).clone_for_update() + }; if let Some(mut mapping) = self.mappings() { let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); @@ -503,11 +827,41 @@ impl SyntaxFactory { make::token(kind) } - pub fn whitespace(&self, text: &str) -> ast::SyntaxToken { + pub fn whitespace(&self, text: &str) -> SyntaxToken { make::tokens::whitespace(text) } } +// `ext` constructors +impl SyntaxFactory { + pub fn ident_path(&self, ident: &str) -> ast::Path { + self.path_unqualified(self.path_segment(self.name_ref(ident))) + } + + pub fn expr_unit(&self) -> ast::Expr { + self.expr_tuple([]).into() + } + + pub fn ty_option(&self, t: ast::Type) -> ast::PathType { + let generic_arg_list = self.generic_arg_list([self.type_arg(t).into()], false); + let path = self.path_unqualified( + self.path_segment_generics(self.name_ref("Option"), generic_arg_list), + ); + + self.ty_path(path) + } + + pub fn ty_result(&self, t: ast::Type, e: ast::Type) -> ast::PathType { + let generic_arg_list = + self.generic_arg_list([self.type_arg(t).into(), self.type_arg(e).into()], false); + let path = self.path_unqualified( + self.path_segment_generics(self.name_ref("Result"), generic_arg_list), + ); + + self.ty_path(path) + } +} + // We need to collect `input` here instead of taking `impl IntoIterator + Clone`, // because if we took `impl IntoIterator + Clone`, that could be something like an // `Iterator::map` with a closure that also makes use of a `SyntaxFactory` constructor. diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs index 992a847663a..b82181ae13a 100644 --- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs +++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs @@ -335,7 +335,7 @@ mod tests { #[test] fn basic_usage() { let root = make::match_arm( - [make::wildcard_pat().into()], + make::wildcard_pat().into(), None, make::expr_tuple([ make::expr_bin_op( @@ -344,7 +344,8 @@ mod tests { make::expr_literal("2").into(), ), make::expr_literal("true").into(), - ]), + ]) + .into(), ); let to_wrap = root.syntax().descendants().find_map(ast::TupleExpr::cast).unwrap(); @@ -549,7 +550,7 @@ mod tests { None, None, make::param_list(None, []), - make::block_expr([], Some(make::expr_unit())), + make::block_expr([], Some(make::ext::expr_unit())), Some(make::ret_type(make::ty_unit())), false, false, diff --git a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml index c860e7b1183..95f4cb9d67e 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml +++ b/src/tools/rust-analyzer/crates/test-fixture/Cargo.toml @@ -2,6 +2,8 @@ name = "test-fixture" version = "0.0.0" rust-version.workspace = true +description = "Test fixtures for rust-analyzer." + edition.workspace = true license.workspace = true authors.workspace = true diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs index 0e72d796875..866379d940e 100644 --- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs +++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs @@ -30,7 +30,9 @@ pub const WORKSPACE: base_db::SourceRootId = base_db::SourceRootId(0); pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { #[track_caller] - fn with_single_file(ra_fixture: &str) -> (Self, EditionedFileId) { + fn with_single_file( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + ) -> (Self, EditionedFileId) { let fixture = ChangeFixture::parse(ra_fixture); let mut db = Self::default(); fixture.change.apply(&mut db); @@ -39,7 +41,9 @@ pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { } #[track_caller] - fn with_many_files(ra_fixture: &str) -> (Self, Vec<EditionedFileId>) { + fn with_many_files( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + ) -> (Self, Vec<EditionedFileId>) { let fixture = ChangeFixture::parse(ra_fixture); let mut db = Self::default(); fixture.change.apply(&mut db); @@ -48,7 +52,7 @@ pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { } #[track_caller] - fn with_files(ra_fixture: &str) -> Self { + fn with_files(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> Self { let fixture = ChangeFixture::parse(ra_fixture); let mut db = Self::default(); fixture.change.apply(&mut db); @@ -58,7 +62,7 @@ pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { #[track_caller] fn with_files_extra_proc_macros( - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, proc_macros: Vec<(String, ProcMacro)>, ) -> Self { let fixture = ChangeFixture::parse_with_proc_macros(ra_fixture, proc_macros); @@ -69,21 +73,23 @@ pub trait WithFixture: Default + ExpandDatabase + SourceRootDatabase + 'static { } #[track_caller] - fn with_position(ra_fixture: &str) -> (Self, FilePosition) { + fn with_position(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (Self, FilePosition) { let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture); let offset = range_or_offset.expect_offset(); (db, FilePosition { file_id, offset }) } #[track_caller] - fn with_range(ra_fixture: &str) -> (Self, FileRange) { + fn with_range(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> (Self, FileRange) { let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture); let range = range_or_offset.expect_range(); (db, FileRange { file_id, range }) } #[track_caller] - fn with_range_or_offset(ra_fixture: &str) -> (Self, EditionedFileId, RangeOrOffset) { + fn with_range_or_offset( + #[rust_analyzer::rust_fixture] ra_fixture: &str, + ) -> (Self, EditionedFileId, RangeOrOffset) { let fixture = ChangeFixture::parse(ra_fixture); let mut db = Self::default(); fixture.change.apply(&mut db); @@ -116,12 +122,12 @@ pub struct ChangeFixture { const SOURCE_ROOT_PREFIX: &str = "/"; impl ChangeFixture { - pub fn parse(ra_fixture: &str) -> ChangeFixture { + pub fn parse(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> ChangeFixture { Self::parse_with_proc_macros(ra_fixture, Vec::new()) } pub fn parse_with_proc_macros( - ra_fixture: &str, + #[rust_analyzer::rust_fixture] ra_fixture: &str, mut proc_macro_defs: Vec<(String, ProcMacro)>, ) -> ChangeFixture { let FixtureWithProjectMeta { @@ -376,8 +382,8 @@ impl ChangeFixture { } } -fn default_test_proc_macros() -> [(String, ProcMacro); 8] { - [ +fn default_test_proc_macros() -> Box<[(String, ProcMacro)]> { + Box::new([ ( r#" #[proc_macro_attribute] @@ -498,7 +504,22 @@ pub fn issue_17479(input: TokenStream) -> TokenStream { disabled: false, }, ), - ] + ( + r#" +#[proc_macro_attribute] +pub fn issue_18898(_attr: TokenStream, input: TokenStream) -> TokenStream { + input +} +"# + .into(), + ProcMacro { + name: Symbol::intern("issue_18898"), + kind: ProcMacroKind::Bang, + expander: sync::Arc::new(Issue18898ProcMacroExpander), + disabled: false, + }, + ), + ]) } fn filter_test_proc_macros( @@ -801,3 +822,54 @@ impl ProcMacroExpander for Issue17479ProcMacroExpander { }) } } + +// Reads ident type within string quotes, for issue #17479. +#[derive(Debug)] +struct Issue18898ProcMacroExpander; +impl ProcMacroExpander for Issue18898ProcMacroExpander { + fn expand( + &self, + subtree: &TopSubtree, + _: Option<&TopSubtree>, + _: &Env, + def_site: Span, + _: Span, + _: Span, + _: Option<String>, + ) -> Result<TopSubtree, ProcMacroExpansionError> { + let span = subtree + .token_trees() + .flat_tokens() + .last() + .ok_or_else(|| ProcMacroExpansionError::Panic("malformed input".to_owned()))? + .first_span(); + let overly_long_subtree = quote! {span => + { + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + let a = 5; + } + }; + Ok(quote! { def_site => + fn foo() { + #overly_long_subtree + } + }) + } +} diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs index 54c9db7aacc..7fe26d53bf2 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs @@ -168,7 +168,7 @@ impl FixtureWithProjectMeta { /// That will set toolchain to nightly and include predefined proc macros and a subset of /// `libcore` into the fixture, see `minicore.rs` for what's available. Note that toolchain /// defaults to stable. - pub fn parse(ra_fixture: &str) -> Self { + pub fn parse(#[rust_analyzer::rust_fixture] ra_fixture: &str) -> Self { let fixture = trim_indent(ra_fixture); let mut fixture = fixture.as_str(); let mut toolchain = None; diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs index 4a2346193b4..fd06736a252 100644 --- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs +++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs @@ -32,7 +32,7 @@ //! error: fmt //! fmt: option, result, transmute, coerce_unsized, copy, clone, derive //! fn: tuple -//! from: sized +//! from: sized, result //! future: pin //! coroutine: pin //! dispatch_from_dyn: unsize, pin @@ -332,6 +332,25 @@ pub mod convert { t } } + + pub trait TryFrom<T>: Sized { + type Error; + fn try_from(value: T) -> Result<Self, Self::Error>; + } + pub trait TryInto<T>: Sized { + type Error; + fn try_into(self) -> Result<T, Self::Error>; + } + + impl<T, U> TryInto<U> for T + where + U: TryFrom<T>, + { + type Error = U::Error; + fn try_into(self) -> Result<U, U::Error> { + U::try_from(self) + } + } // endregion:from // region:as_ref @@ -1510,7 +1529,7 @@ pub mod iter { impl<T, const N: usize> IntoIterator for [T; N] { type Item = T; type IntoIter = IntoIter<T, N>; - fn into_iter(self) -> I { + fn into_iter(self) -> Self::IntoIter { IntoIter { data: self, range: IndexRange { start: 0, end: loop {} } } } } @@ -1520,6 +1539,29 @@ pub mod iter { loop {} } } + pub struct Iter<'a, T> { + slice: &'a [T], + } + impl<'a, T> IntoIterator for &'a [T; N] { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + fn into_iter(self) -> Self::IntoIter { + loop {} + } + } + impl<'a, T> IntoIterator for &'a [T] { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + fn into_iter(self) -> Self::IntoIter { + loop {} + } + } + impl<'a, T> Iterator for Iter<'a, T> { + type Item = &'a T; + fn next(&mut self) -> Option<T> { + loop {} + } + } } pub use self::collect::IntoIterator; } @@ -1532,6 +1574,15 @@ pub mod str { pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str { "" } + pub trait FromStr: Sized { + type Err; + fn from_str(s: &str) -> Result<Self, Self::Err>; + } + impl str { + pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> { + FromStr::from_str(self) + } + } } // endregion:str @@ -1791,7 +1842,7 @@ pub mod prelude { cmp::{Eq, PartialEq}, // :eq cmp::{Ord, PartialOrd}, // :ord convert::AsRef, // :as_ref - convert::{From, Into}, // :from + convert::{From, Into, TryFrom, TryInto}, // :from default::Default, // :default iter::{IntoIterator, Iterator}, // :iterator macros::builtin::{derive, derive_const}, // :derive @@ -1806,6 +1857,7 @@ pub mod prelude { option::Option::{self, None, Some}, // :option panic, // :panic result::Result::{self, Err, Ok}, // :result + str::FromStr, // :str }; } diff --git a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml index 09296dc6dd5..bc54d7168f0 100644 --- a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml +++ b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml @@ -16,7 +16,7 @@ doctest = false tracing.workspace = true walkdir = "2.3.2" crossbeam-channel.workspace = true -notify = "6.1.1" +notify = "8.0.0" rayon = "1.10.0" stdx.workspace = true diff --git a/src/tools/rust-analyzer/docs/dev/README.md b/src/tools/rust-analyzer/docs/dev/README.md index cd0f49174cd..3ba492e0959 100644 --- a/src/tools/rust-analyzer/docs/dev/README.md +++ b/src/tools/rust-analyzer/docs/dev/README.md @@ -154,19 +154,21 @@ There are also several VS Code commands which might be of interest: * `rust-analyzer: Status` shows some memory-usage statistics. -* `rust-analyzer: Syntax Tree` shows syntax tree of the current file/selection. - * `rust-analyzer: View Hir` shows the HIR expressions within the function containing the cursor. - You can hover over syntax nodes in the opened text file to see the appropriate - rust code that it refers to and the rust editor will also highlight the proper - text range. +* If `rust-analyzer.showSyntaxTree` is enabled in settings, `Rust Syntax Tree: Focus on Rust Syntax Tree View` shows the syntax tree of the current file. + + You can click on nodes in the rust editor to go to the corresponding syntax node. + + You can click on `Reveal Syntax Element` next to a syntax node to go to the corresponding rust code and highlight the proper text range. If you trigger Go to Definition in the inspected Rust source file, - the syntax tree read-only editor should scroll to and select the + the syntax tree view should scroll to and select the appropriate syntax node token. -  + You can click on `Copy` next to a syntax node to copy a text representation of the node. + +  ## Profiling diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md index 21ac3a5a269..a632fc6f5fb 100644 --- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md +++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md @@ -1,5 +1,5 @@ <!--- -lsp/ext.rs hash: 6dd762ae19630ec0 +lsp/ext.rs hash: 2d8604825c458288 If you need to change the above hash to make the test pass, please check if you need to adjust this doc as well and ping this issue: @@ -710,6 +710,23 @@ interface SyntaxTreeParams { Returns textual representation of a parse tree for the file/selected region. Primarily for debugging, but very useful for all people working on rust-analyzer itself. +## View Syntax Tree + +**Method:** `rust-analyzer/viewSyntaxTree` + +**Request:** + +```typescript +interface ViewSyntaxTreeParams { + textDocument: TextDocumentIdentifier, +} +``` + +**Response:** `string` + +Returns json representation of the file's syntax tree. +Used to create a treeView for debugging and working on rust-analyzer itself. + ## View Hir **Method:** `rust-analyzer/viewHir` diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc index 5b86766aa8e..bd091db58d3 100644 --- a/src/tools/rust-analyzer/docs/user/generated_config.adoc +++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc @@ -94,10 +94,10 @@ avoid checking unnecessary things. -- Default: ---- -{ - "miri": null, - "debug_assertions": null -} +[ + "debug_assertions", + "miri" +] ---- List of cfg options to enable with the given values. @@ -716,6 +716,11 @@ Whether to show generic type parameter name inlay hints. -- Whether to show implicit drop hints. -- +[[rust-analyzer.inlayHints.implicitSizedBoundHints.enable]]rust-analyzer.inlayHints.implicitSizedBoundHints.enable (default: `false`):: ++ +-- +Whether to show inlay hints for the implied type parameter `Sized` bound. +-- [[rust-analyzer.inlayHints.lifetimeElisionHints.enable]]rust-analyzer.inlayHints.lifetimeElisionHints.enable (default: `"never"`):: + -- @@ -1046,10 +1051,25 @@ Show full signature of the callable. Only shows parameters if disabled. -- Show documentation. -- -[[rust-analyzer.typing.excludeChars]]rust-analyzer.typing.excludeChars (default: `"|<"`):: +[[rust-analyzer.typing.triggerChars]]rust-analyzer.typing.triggerChars (default: `"=."`):: ++ +-- +Specify the characters allowed to invoke special on typing triggers. +- typing `=` after `let` tries to smartly add `;` if `=` is followed by an existing expression +- typing `=` between two expressions adds `;` when in statement position +- typing `=` to turn an assignment into an equality comparison removes `;` when in expression position +- typing `.` in a chain method call auto-indents +- typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression +- typing `{` in a use item adds a closing `}` in the right place +- typing `>` to complete a return type `->` will insert a whitespace after it +- typing `<` in a path or type position inserts a closing `>` after the path or type. +-- +[[rust-analyzer.vfs.extraIncludes]]rust-analyzer.vfs.extraIncludes (default: `[]`):: + -- -Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`. +Additional paths to include in the VFS. Generally for code that is +generated or otherwise managed by a build system outside of Cargo, +though Cargo might be the eventual consumer. -- [[rust-analyzer.workspace.discoverConfig]]rust-analyzer.workspace.discoverConfig (default: `null`):: + diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json index 80246bf3fea..8b066377f2b 100644 --- a/src/tools/rust-analyzer/editors/code/package.json +++ b/src/tools/rust-analyzer/editors/code/package.json @@ -109,11 +109,6 @@ ], "commands": [ { - "command": "rust-analyzer.syntaxTree", - "title": "Show Syntax Tree", - "category": "rust-analyzer (debug command)" - }, - { "command": "rust-analyzer.viewHir", "title": "View Hir", "category": "rust-analyzer (debug command)" @@ -289,6 +284,30 @@ "category": "rust-analyzer" }, { + "command": "rust-analyzer.syntaxTreeReveal", + "title": "Reveal Syntax Element", + "icon": "$(search)", + "category": "rust-analyzer (syntax tree)" + }, + { + "command": "rust-analyzer.syntaxTreeCopy", + "title": "Copy", + "icon": "$(copy)", + "category": "rust-analyzer (syntax tree)" + }, + { + "command": "rust-analyzer.syntaxTreeHideWhitespace", + "title": "Hide Whitespace", + "icon": "$(filter)", + "category": "rust-analyzer (syntax tree)" + }, + { + "command": "rust-analyzer.syntaxTreeShowWhitespace", + "title": "Show Whitespace", + "icon": "$(filter-filled)", + "category": "rust-analyzer (syntax tree)" + }, + { "command": "rust-analyzer.viewMemoryLayout", "title": "View Memory Layout", "category": "rust-analyzer" @@ -345,6 +364,11 @@ "default": true, "type": "boolean" }, + "rust-analyzer.showSyntaxTree": { + "markdownDescription": "Whether to show the syntax tree view.", + "default": false, + "type": "boolean" + }, "rust-analyzer.testExplorer": { "markdownDescription": "Whether to show the test explorer.", "default": false, @@ -791,11 +815,14 @@ "properties": { "rust-analyzer.cargo.cfgs": { "markdownDescription": "List of cfg options to enable with the given values.", - "default": { - "miri": null, - "debug_assertions": null - }, - "type": "object" + "default": [ + "debug_assertions", + "miri" + ], + "type": "array", + "items": { + "type": "string" + } } } }, @@ -2081,6 +2108,16 @@ { "title": "inlayHints", "properties": { + "rust-analyzer.inlayHints.implicitSizedBoundHints.enable": { + "markdownDescription": "Whether to show inlay hints for the implied type parameter `Sized` bound.", + "default": false, + "type": "boolean" + } + } + }, + { + "title": "inlayHints", + "properties": { "rust-analyzer.inlayHints.lifetimeElisionHints.enable": { "markdownDescription": "Whether to show inlay type hints for elided lifetimes in function signatures.", "default": "never", @@ -2708,9 +2745,9 @@ { "title": "typing", "properties": { - "rust-analyzer.typing.excludeChars": { - "markdownDescription": "Specify the characters to exclude from triggering typing assists. The default trigger characters are `.`, `=`, `<`, `>`, `{`, and `(`.", - "default": "|<", + "rust-analyzer.typing.triggerChars": { + "markdownDescription": "Specify the characters allowed to invoke special on typing triggers.\n- typing `=` after `let` tries to smartly add `;` if `=` is followed by an existing expression\n- typing `=` between two expressions adds `;` when in statement position\n- typing `=` to turn an assignment into an equality comparison removes `;` when in expression position\n- typing `.` in a chain method call auto-indents\n- typing `{` or `(` in front of an expression inserts a closing `}` or `)` after the expression\n- typing `{` in a use item adds a closing `}` in the right place\n- typing `>` to complete a return type `->` will insert a whitespace after it\n- typing `<` in a path or type position inserts a closing `>` after the path or type.", + "default": "=.", "type": [ "null", "string" @@ -2719,6 +2756,19 @@ } }, { + "title": "vfs", + "properties": { + "rust-analyzer.vfs.extraIncludes": { + "markdownDescription": "Additional paths to include in the VFS. Generally for code that is\ngenerated or otherwise managed by a build system outside of Cargo,\nthough Cargo might be the eventual consumer.", + "default": [], + "type": "array", + "items": { + "type": "string" + } + } + } + }, + { "title": "workspace", "properties": { "rust-analyzer.workspace.discoverConfig": { @@ -2928,17 +2978,6 @@ "pattern": "$rustc" } ], - "colors": [ - { - "id": "rust_analyzer.syntaxTreeBorder", - "description": "Color of the border displayed in the Rust source code for the selected syntax node (see \"Show Syntax Tree\" command)", - "defaults": { - "dark": "#ffffff", - "light": "#b700ff", - "highContrast": "#b700ff" - } - } - ], "semanticTokenTypes": [ { "id": "angle", @@ -3259,10 +3298,6 @@ "menus": { "commandPalette": [ { - "command": "rust-analyzer.syntaxTree", - "when": "inRustProject" - }, - { "command": "rust-analyzer.viewHir", "when": "inRustProject" }, @@ -3344,6 +3379,22 @@ }, { "command": "rust-analyzer.openWalkthrough" + }, + { + "command": "rust-analyzer.syntaxTreeReveal", + "when": "false" + }, + { + "command": "rust-analyzer.syntaxTreeCopy", + "when": "false" + }, + { + "command": "rust-analyzer.syntaxTreeHideWhitespace", + "when": "false" + }, + { + "command": "rust-analyzer.syntaxTreeShowWhitespace", + "when": "false" } ], "editor/context": [ @@ -3357,6 +3408,30 @@ "when": "inRustProject && editorTextFocus && editorLangId == rust", "group": "navigation@1001" } + ], + "view/title": [ + { + "command": "rust-analyzer.syntaxTreeHideWhitespace", + "group": "navigation", + "when": "view == rustSyntaxTree && !rustSyntaxTree.hideWhitespace" + }, + { + "command": "rust-analyzer.syntaxTreeShowWhitespace", + "group": "navigation", + "when": "view == rustSyntaxTree && rustSyntaxTree.hideWhitespace" + } + ], + "view/item/context": [ + { + "command": "rust-analyzer.syntaxTreeCopy", + "group": "inline", + "when": "view == rustSyntaxTree" + }, + { + "command": "rust-analyzer.syntaxTreeReveal", + "group": "inline", + "when": "view == rustSyntaxTree" + } ] }, "views": { @@ -3366,6 +3441,22 @@ "name": "Rust Dependencies", "when": "inRustProject && config.rust-analyzer.showDependenciesExplorer" } + ], + "rustSyntaxTreeContainer": [ + { + "id": "rustSyntaxTree", + "name": "Rust Syntax Tree", + "when": "inRustProject && config.rust-analyzer.showSyntaxTree" + } + ] + }, + "viewsContainers": { + "activitybar": [ + { + "id": "rustSyntaxTreeContainer", + "title": "Rust Syntax Tree", + "icon": "$(list-tree)" + } ] }, "jsonValidation": [ diff --git a/src/tools/rust-analyzer/editors/code/src/ast_inspector.ts b/src/tools/rust-analyzer/editors/code/src/ast_inspector.ts deleted file mode 100644 index 35b705c477e..00000000000 --- a/src/tools/rust-analyzer/editors/code/src/ast_inspector.ts +++ /dev/null @@ -1,216 +0,0 @@ -import * as vscode from "vscode"; - -import type { Ctx, Disposable } from "./ctx"; -import { type RustEditor, isRustEditor, unwrapUndefinable } from "./util"; - -// FIXME: consider implementing this via the Tree View API? -// https://code.visualstudio.com/api/extension-guides/tree-view -export class AstInspector implements vscode.HoverProvider, vscode.DefinitionProvider, Disposable { - private readonly astDecorationType = vscode.window.createTextEditorDecorationType({ - borderColor: new vscode.ThemeColor("rust_analyzer.syntaxTreeBorder"), - borderStyle: "solid", - borderWidth: "2px", - }); - private rustEditor: undefined | RustEditor; - - // Lazy rust token range -> syntax tree file range. - private readonly rust2Ast = new Lazy(() => { - const astEditor = this.findAstTextEditor(); - if (!this.rustEditor || !astEditor) return undefined; - - const buf: [vscode.Range, vscode.Range][] = []; - for (let i = 0; i < astEditor.document.lineCount; ++i) { - const astLine = astEditor.document.lineAt(i); - - // Heuristically look for nodes with quoted text (which are token nodes) - const isTokenNode = astLine.text.lastIndexOf('"') >= 0; - if (!isTokenNode) continue; - - const rustRange = this.parseRustTextRange(this.rustEditor.document, astLine.text); - if (!rustRange) continue; - - buf.push([rustRange, this.findAstNodeRange(astLine)]); - } - return buf; - }); - - constructor(ctx: Ctx) { - ctx.pushExtCleanup( - vscode.languages.registerHoverProvider({ scheme: "rust-analyzer" }, this), - ); - ctx.pushExtCleanup(vscode.languages.registerDefinitionProvider({ language: "rust" }, this)); - vscode.workspace.onDidCloseTextDocument( - this.onDidCloseTextDocument, - this, - ctx.subscriptions, - ); - vscode.workspace.onDidChangeTextDocument( - this.onDidChangeTextDocument, - this, - ctx.subscriptions, - ); - vscode.window.onDidChangeVisibleTextEditors( - this.onDidChangeVisibleTextEditors, - this, - ctx.subscriptions, - ); - } - dispose() { - this.setRustEditor(undefined); - } - - private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) { - if ( - this.rustEditor && - event.document.uri.toString() === this.rustEditor.document.uri.toString() - ) { - this.rust2Ast.reset(); - } - } - - private onDidCloseTextDocument(doc: vscode.TextDocument) { - if (this.rustEditor && doc.uri.toString() === this.rustEditor.document.uri.toString()) { - this.setRustEditor(undefined); - } - } - - private onDidChangeVisibleTextEditors(editors: readonly vscode.TextEditor[]) { - if (!this.findAstTextEditor()) { - this.setRustEditor(undefined); - return; - } - this.setRustEditor(editors.find(isRustEditor)); - } - - private findAstTextEditor(): undefined | vscode.TextEditor { - return vscode.window.visibleTextEditors.find( - (it) => it.document.uri.scheme === "rust-analyzer", - ); - } - - private setRustEditor(newRustEditor: undefined | RustEditor) { - if (this.rustEditor && this.rustEditor !== newRustEditor) { - this.rustEditor.setDecorations(this.astDecorationType, []); - this.rust2Ast.reset(); - } - this.rustEditor = newRustEditor; - } - - // additional positional params are omitted - provideDefinition( - doc: vscode.TextDocument, - pos: vscode.Position, - ): vscode.ProviderResult<vscode.DefinitionLink[]> { - if (!this.rustEditor || doc.uri.toString() !== this.rustEditor.document.uri.toString()) { - return; - } - - const astEditor = this.findAstTextEditor(); - if (!astEditor) return; - - const rust2AstRanges = this.rust2Ast - .get() - ?.find(([rustRange, _]) => rustRange.contains(pos)); - if (!rust2AstRanges) return; - - const [rustFileRange, astFileRange] = rust2AstRanges; - - astEditor.revealRange(astFileRange); - astEditor.selection = new vscode.Selection(astFileRange.start, astFileRange.end); - - return [ - { - targetRange: astFileRange, - targetUri: astEditor.document.uri, - originSelectionRange: rustFileRange, - targetSelectionRange: astFileRange, - }, - ]; - } - - // additional positional params are omitted - provideHover( - doc: vscode.TextDocument, - hoverPosition: vscode.Position, - ): vscode.ProviderResult<vscode.Hover> { - if (!this.rustEditor) return; - - const astFileLine = doc.lineAt(hoverPosition.line); - - const rustFileRange = this.parseRustTextRange(this.rustEditor.document, astFileLine.text); - if (!rustFileRange) return; - - this.rustEditor.setDecorations(this.astDecorationType, [rustFileRange]); - this.rustEditor.revealRange(rustFileRange); - - const rustSourceCode = this.rustEditor.document.getText(rustFileRange); - const astFileRange = this.findAstNodeRange(astFileLine); - - return new vscode.Hover(["```rust\n" + rustSourceCode + "\n```"], astFileRange); - } - - private findAstNodeRange(astLine: vscode.TextLine): vscode.Range { - const lineOffset = astLine.range.start; - const begin = lineOffset.translate(undefined, astLine.firstNonWhitespaceCharacterIndex); - const end = lineOffset.translate(undefined, astLine.text.trimEnd().length); - return new vscode.Range(begin, end); - } - - private parseRustTextRange( - doc: vscode.TextDocument, - astLine: string, - ): undefined | vscode.Range { - const parsedRange = /(\d+)\.\.(\d+)/.exec(astLine); - if (!parsedRange) return; - - const [begin, end] = parsedRange.slice(1).map((off) => this.positionAt(doc, +off)); - const actualBegin = unwrapUndefinable(begin); - const actualEnd = unwrapUndefinable(end); - return new vscode.Range(actualBegin, actualEnd); - } - - // Memoize the last value, otherwise the CPU is at 100% single core - // with quadratic lookups when we build rust2Ast cache - cache?: { doc: vscode.TextDocument; offset: number; line: number }; - - positionAt(doc: vscode.TextDocument, targetOffset: number): vscode.Position { - if (doc.eol === vscode.EndOfLine.LF) { - return doc.positionAt(targetOffset); - } - - // Dirty workaround for crlf line endings - // We are still in this prehistoric era of carriage returns here... - - let line = 0; - let offset = 0; - - const cache = this.cache; - if (cache?.doc === doc && cache.offset <= targetOffset) { - ({ line, offset } = cache); - } - - while (true) { - const lineLenWithLf = doc.lineAt(line).text.length + 1; - if (offset + lineLenWithLf > targetOffset) { - this.cache = { doc, offset, line }; - return doc.positionAt(targetOffset + line); - } - offset += lineLenWithLf; - line += 1; - } - } -} - -class Lazy<T> { - val: undefined | T; - - constructor(private readonly compute: () => undefined | T) {} - - get() { - return this.val ?? (this.val = this.compute()); - } - - reset() { - this.val = undefined; - } -} diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts index 73e39c900e7..b3aa04af7ed 100644 --- a/src/tools/rust-analyzer/editors/code/src/commands.ts +++ b/src/tools/rust-analyzer/editors/code/src/commands.ts @@ -15,7 +15,6 @@ import { createTaskFromRunnable, createCargoArgs, } from "./run"; -import { AstInspector } from "./ast_inspector"; import { isRustDocument, isCargoRunnableArgs, @@ -31,8 +30,8 @@ import type { LanguageClient } from "vscode-languageclient/node"; import { HOVER_REFERENCE_COMMAND } from "./client"; import type { DependencyId } from "./dependencies_provider"; import { log } from "./util"; +import type { SyntaxElement } from "./syntax_tree_provider"; -export * from "./ast_inspector"; export * from "./run"; export function analyzerStatus(ctx: CtxInit): Cmd { @@ -288,13 +287,13 @@ export function openCargoToml(ctx: CtxInit): Cmd { export function revealDependency(ctx: CtxInit): Cmd { return async (editor: RustEditor) => { - if (!ctx.dependencies?.isInitialized()) { + if (!ctx.dependenciesProvider?.isInitialized()) { return; } const documentPath = editor.document.uri.fsPath; - const dep = ctx.dependencies?.getDependency(documentPath); + const dep = ctx.dependenciesProvider?.getDependency(documentPath); if (dep) { - await ctx.treeView?.reveal(dep, { select: true, expand: true }); + await ctx.dependencyTreeView?.reveal(dep, { select: true, expand: true }); } else { await revealParentChain(editor.document, ctx); } @@ -340,10 +339,10 @@ async function revealParentChain(document: RustDocument, ctx: CtxInit) { // a open file referencing the old version return; } - } while (!ctx.dependencies?.contains(documentPath)); + } while (!ctx.dependenciesProvider?.contains(documentPath)); parentChain.reverse(); for (const idx in parentChain) { - const treeView = ctx.treeView; + const treeView = ctx.dependencyTreeView; if (!treeView) { continue; } @@ -357,6 +356,77 @@ export async function execRevealDependency(e: RustEditor): Promise<void> { await vscode.commands.executeCommand("rust-analyzer.revealDependency", e); } +export function syntaxTreeReveal(): Cmd { + return async (element: SyntaxElement) => { + const activeEditor = vscode.window.activeTextEditor; + + if (activeEditor !== undefined) { + const start = activeEditor.document.positionAt(element.start); + const end = activeEditor.document.positionAt(element.end); + + const newSelection = new vscode.Selection(start, end); + + activeEditor.selection = newSelection; + activeEditor.revealRange(newSelection); + } + }; +} + +function elementToString( + activeDocument: vscode.TextDocument, + element: SyntaxElement, + depth: number = 0, +): string { + let result = " ".repeat(depth); + const start = element.istart ?? element.start; + const end = element.iend ?? element.end; + + result += `${element.kind}@${start}..${end}`; + + if (element.type === "Token") { + const startPosition = activeDocument.positionAt(element.start); + const endPosition = activeDocument.positionAt(element.end); + const text = activeDocument.getText(new vscode.Range(startPosition, endPosition)); + // JSON.stringify quotes and escapes the string for us. + result += ` ${JSON.stringify(text)}\n`; + } else { + result += "\n"; + for (const child of element.children) { + result += elementToString(activeDocument, child, depth + 1); + } + } + + return result; +} + +export function syntaxTreeCopy(): Cmd { + return async (element: SyntaxElement) => { + const activeDocument = vscode.window.activeTextEditor?.document; + if (!activeDocument) { + return; + } + + const result = elementToString(activeDocument, element); + await vscode.env.clipboard.writeText(result); + }; +} + +export function syntaxTreeHideWhitespace(ctx: CtxInit): Cmd { + return async () => { + if (ctx.syntaxTreeProvider !== undefined) { + await ctx.syntaxTreeProvider.toggleWhitespace(); + } + }; +} + +export function syntaxTreeShowWhitespace(ctx: CtxInit): Cmd { + return async () => { + if (ctx.syntaxTreeProvider !== undefined) { + await ctx.syntaxTreeProvider.toggleWhitespace(); + } + }; +} + export function ssr(ctx: CtxInit): Cmd { return async () => { const editor = vscode.window.activeTextEditor; @@ -426,89 +496,6 @@ export function serverVersion(ctx: CtxInit): Cmd { }; } -// Opens the virtual file that will show the syntax tree -// -// The contents of the file come from the `TextDocumentContentProvider` -export function syntaxTree(ctx: CtxInit): Cmd { - const tdcp = new (class implements vscode.TextDocumentContentProvider { - readonly uri = vscode.Uri.parse("rust-analyzer-syntax-tree://syntaxtree/tree.rast"); - readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>(); - constructor() { - vscode.workspace.onDidChangeTextDocument( - this.onDidChangeTextDocument, - this, - ctx.subscriptions, - ); - vscode.window.onDidChangeActiveTextEditor( - this.onDidChangeActiveTextEditor, - this, - ctx.subscriptions, - ); - } - - private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) { - if (isRustDocument(event.document)) { - // We need to order this after language server updates, but there's no API for that. - // Hence, good old sleep(). - void sleep(10).then(() => this.eventEmitter.fire(this.uri)); - } - } - private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) { - if (editor && isRustEditor(editor)) { - this.eventEmitter.fire(this.uri); - } - } - - async provideTextDocumentContent( - uri: vscode.Uri, - ct: vscode.CancellationToken, - ): Promise<string> { - const rustEditor = ctx.activeRustEditor; - if (!rustEditor) return ""; - const client = ctx.client; - - // When the range based query is enabled we take the range of the selection - const range = - uri.query === "range=true" && !rustEditor.selection.isEmpty - ? client.code2ProtocolConverter.asRange(rustEditor.selection) - : null; - - const params = { textDocument: { uri: rustEditor.document.uri.toString() }, range }; - return client.sendRequest(ra.syntaxTree, params, ct); - } - - get onDidChange(): vscode.Event<vscode.Uri> { - return this.eventEmitter.event; - } - })(); - - ctx.pushExtCleanup(new AstInspector(ctx)); - ctx.pushExtCleanup( - vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-syntax-tree", tdcp), - ); - ctx.pushExtCleanup( - vscode.languages.setLanguageConfiguration("ra_syntax_tree", { - brackets: [["[", ")"]], - }), - ); - - return async () => { - const editor = vscode.window.activeTextEditor; - const rangeEnabled = !!editor && !editor.selection.isEmpty; - - const uri = rangeEnabled ? vscode.Uri.parse(`${tdcp.uri.toString()}?range=true`) : tdcp.uri; - - const document = await vscode.workspace.openTextDocument(uri); - - tdcp.eventEmitter.fire(uri); - - void (await vscode.window.showTextDocument(document, { - viewColumn: vscode.ViewColumn.Two, - preserveFocus: true, - })); - }; -} - function viewHirOrMir(ctx: CtxInit, xir: "hir" | "mir"): Cmd { const viewXir = xir === "hir" ? "viewHir" : "viewMir"; const requestType = xir === "hir" ? ra.viewHir : ra.viewMir; diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts index 720c473c5b4..d1467a4e824 100644 --- a/src/tools/rust-analyzer/editors/code/src/config.ts +++ b/src/tools/rust-analyzer/editors/code/src/config.ts @@ -351,6 +351,10 @@ export class Config { return this.get<boolean>("showDependenciesExplorer"); } + get showSyntaxTree() { + return this.get<boolean>("showSyntaxTree"); + } + get statusBarClickAction() { return this.get<string>("statusBar.clickAction"); } diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts index 37a54abf71f..5550bfa6558 100644 --- a/src/tools/rust-analyzer/editors/code/src/ctx.ts +++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts @@ -19,6 +19,7 @@ import { RustDependenciesProvider, type DependencyId, } from "./dependencies_provider"; +import { SyntaxTreeProvider, type SyntaxElement } from "./syntax_tree_provider"; import { execRevealDependency } from "./commands"; import { PersistentState } from "./persistent_state"; import { bootstrap } from "./bootstrap"; @@ -84,8 +85,12 @@ export class Ctx implements RustAnalyzerExtensionApi { private commandFactories: Record<string, CommandFactory>; private commandDisposables: Disposable[]; private unlinkedFiles: vscode.Uri[]; - private _dependencies: RustDependenciesProvider | undefined; - private _treeView: vscode.TreeView<Dependency | DependencyFile | DependencyId> | undefined; + private _dependenciesProvider: RustDependenciesProvider | undefined; + private _dependencyTreeView: + | vscode.TreeView<Dependency | DependencyFile | DependencyId> + | undefined; + private _syntaxTreeProvider: SyntaxTreeProvider | undefined; + private _syntaxTreeView: vscode.TreeView<SyntaxElement> | undefined; private lastStatus: ServerStatusParams | { health: "stopped" } = { health: "stopped" }; private _serverVersion: string; private statusBarActiveEditorListener: Disposable; @@ -102,12 +107,20 @@ export class Ctx implements RustAnalyzerExtensionApi { return this._client; } - get treeView() { - return this._treeView; + get dependencyTreeView() { + return this._dependencyTreeView; } - get dependencies() { - return this._dependencies; + get dependenciesProvider() { + return this._dependenciesProvider; + } + + get syntaxTreeView() { + return this._syntaxTreeView; + } + + get syntaxTreeProvider() { + return this._syntaxTreeProvider; } constructor( @@ -278,6 +291,9 @@ export class Ctx implements RustAnalyzerExtensionApi { if (this.config.showDependenciesExplorer) { this.prepareTreeDependenciesView(client); } + if (this.config.showSyntaxTree) { + this.prepareSyntaxTreeView(client); + } } private prepareTreeDependenciesView(client: lc.LanguageClient) { @@ -285,13 +301,13 @@ export class Ctx implements RustAnalyzerExtensionApi { ...this, client: client, }; - this._dependencies = new RustDependenciesProvider(ctxInit); - this._treeView = vscode.window.createTreeView("rustDependencies", { - treeDataProvider: this._dependencies, + this._dependenciesProvider = new RustDependenciesProvider(ctxInit); + this._dependencyTreeView = vscode.window.createTreeView("rustDependencies", { + treeDataProvider: this._dependenciesProvider, showCollapseAll: true, }); - this.pushExtCleanup(this._treeView); + this.pushExtCleanup(this._dependencyTreeView); vscode.window.onDidChangeActiveTextEditor(async (e) => { // we should skip documents that belong to the current workspace if (this.shouldRevealDependency(e)) { @@ -303,7 +319,7 @@ export class Ctx implements RustAnalyzerExtensionApi { } }); - this.treeView?.onDidChangeVisibility(async (e) => { + this.dependencyTreeView?.onDidChangeVisibility(async (e) => { if (e.visible) { const activeEditor = vscode.window.activeTextEditor; if (this.shouldRevealDependency(activeEditor)) { @@ -322,10 +338,60 @@ export class Ctx implements RustAnalyzerExtensionApi { e !== undefined && isRustEditor(e) && !isDocumentInWorkspace(e.document) && - (this.treeView?.visible || false) + (this.dependencyTreeView?.visible || false) ); } + private prepareSyntaxTreeView(client: lc.LanguageClient) { + const ctxInit: CtxInit = { + ...this, + client: client, + }; + this._syntaxTreeProvider = new SyntaxTreeProvider(ctxInit); + this._syntaxTreeView = vscode.window.createTreeView("rustSyntaxTree", { + treeDataProvider: this._syntaxTreeProvider, + showCollapseAll: true, + }); + + this.pushExtCleanup(this._syntaxTreeView); + + vscode.window.onDidChangeActiveTextEditor(async () => { + if (this.syntaxTreeView?.visible) { + await this.syntaxTreeProvider?.refresh(); + } + }); + + vscode.workspace.onDidChangeTextDocument(async () => { + if (this.syntaxTreeView?.visible) { + await this.syntaxTreeProvider?.refresh(); + } + }); + + vscode.window.onDidChangeTextEditorSelection(async (e) => { + if (!this.syntaxTreeView?.visible || !isRustEditor(e.textEditor)) { + return; + } + + const selection = e.selections[0]; + if (selection === undefined) { + return; + } + + const start = e.textEditor.document.offsetAt(selection.start); + const end = e.textEditor.document.offsetAt(selection.end); + const result = this.syntaxTreeProvider?.getElementByRange(start, end); + if (result !== undefined) { + await this.syntaxTreeView?.reveal(result); + } + }); + + this._syntaxTreeView.onDidChangeVisibility(async (e) => { + if (e.visible) { + await this.syntaxTreeProvider?.refresh(); + } + }); + } + async restart() { // FIXME: We should re-use the client, that is ctx.deactivate() if none of the configs have changed await this.stopAndDispose(); @@ -423,7 +489,8 @@ export class Ctx implements RustAnalyzerExtensionApi { } else { statusBar.command = "rust-analyzer.openLogs"; } - this.dependencies?.refresh(); + this.dependenciesProvider?.refresh(); + void this.syntaxTreeProvider?.refresh(); break; case "warning": statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground"); diff --git a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts index d52e314e219..af86d9efd14 100644 --- a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts +++ b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts @@ -48,6 +48,9 @@ export const runFlycheck = new lc.NotificationType<{ export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>( "rust-analyzer/syntaxTree", ); +export const viewSyntaxTree = new lc.RequestType<ViewSyntaxTreeParams, string, void>( + "rust-analyzer/viewSyntaxTree", +); export const viewCrateGraph = new lc.RequestType<ViewCrateGraphParams, string, void>( "rust-analyzer/viewCrateGraph", ); @@ -157,6 +160,7 @@ export type SyntaxTreeParams = { textDocument: lc.TextDocumentIdentifier; range: lc.Range | null; }; +export type ViewSyntaxTreeParams = { textDocument: lc.TextDocumentIdentifier }; export type ViewCrateGraphParams = { full: boolean }; export type ViewItemTreeParams = { textDocument: lc.TextDocumentIdentifier }; diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts index fdf43f66f94..c84b69b66cd 100644 --- a/src/tools/rust-analyzer/editors/code/src/main.ts +++ b/src/tools/rust-analyzer/editors/code/src/main.ts @@ -158,7 +158,6 @@ function createCommands(): Record<string, CommandFactory> { matchingBrace: { enabled: commands.matchingBrace }, joinLines: { enabled: commands.joinLines }, parentModule: { enabled: commands.parentModule }, - syntaxTree: { enabled: commands.syntaxTree }, viewHir: { enabled: commands.viewHir }, viewMir: { enabled: commands.viewMir }, interpretFunction: { enabled: commands.interpretFunction }, @@ -199,6 +198,10 @@ function createCommands(): Record<string, CommandFactory> { rename: { enabled: commands.rename }, openLogs: { enabled: commands.openLogs }, revealDependency: { enabled: commands.revealDependency }, + syntaxTreeReveal: { enabled: commands.syntaxTreeReveal }, + syntaxTreeCopy: { enabled: commands.syntaxTreeCopy }, + syntaxTreeHideWhitespace: { enabled: commands.syntaxTreeHideWhitespace }, + syntaxTreeShowWhitespace: { enabled: commands.syntaxTreeShowWhitespace }, }; } diff --git a/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts b/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts new file mode 100644 index 00000000000..c7e8007e838 --- /dev/null +++ b/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts @@ -0,0 +1,301 @@ +import * as vscode from "vscode"; + +import { isRustEditor, setContextValue } from "./util"; +import type { CtxInit } from "./ctx"; +import * as ra from "./lsp_ext"; + +export class SyntaxTreeProvider implements vscode.TreeDataProvider<SyntaxElement> { + private _onDidChangeTreeData: vscode.EventEmitter<SyntaxElement | undefined | void> = + new vscode.EventEmitter<SyntaxElement | undefined | void>(); + readonly onDidChangeTreeData: vscode.Event<SyntaxElement | undefined | void> = + this._onDidChangeTreeData.event; + ctx: CtxInit; + root: SyntaxNode | undefined; + hideWhitespace: boolean = false; + + constructor(ctx: CtxInit) { + this.ctx = ctx; + } + + getTreeItem(element: SyntaxElement): vscode.TreeItem { + return new SyntaxTreeItem(element); + } + + getChildren(element?: SyntaxElement): vscode.ProviderResult<SyntaxElement[]> { + return this.getRawChildren(element); + } + + getParent(element: SyntaxElement): vscode.ProviderResult<SyntaxElement> { + return element.parent; + } + + resolveTreeItem( + item: SyntaxTreeItem, + element: SyntaxElement, + _token: vscode.CancellationToken, + ): vscode.ProviderResult<SyntaxTreeItem> { + const editor = vscode.window.activeTextEditor; + + if (editor !== undefined) { + const start = editor.document.positionAt(element.start); + const end = editor.document.positionAt(element.end); + const range = new vscode.Range(start, end); + + const text = editor.document.getText(range); + item.tooltip = new vscode.MarkdownString().appendCodeblock(text, "rust"); + } + + return item; + } + + private getRawChildren(element?: SyntaxElement): SyntaxElement[] { + if (element?.type === "Node") { + if (this.hideWhitespace) { + return element.children.filter((e) => e.kind !== "WHITESPACE"); + } + + return element.children; + } + + if (element?.type === "Token") { + return []; + } + + if (element === undefined && this.root !== undefined) { + return [this.root]; + } + + return []; + } + + async refresh(): Promise<void> { + const editor = vscode.window.activeTextEditor; + + if (editor && isRustEditor(editor)) { + const params = { textDocument: { uri: editor.document.uri.toString() }, range: null }; + const fileText = await this.ctx.client.sendRequest(ra.viewSyntaxTree, params); + this.root = JSON.parse(fileText, (_key, value: SyntaxElement) => { + if (value.type === "Node") { + for (const child of value.children) { + child.parent = value; + } + } + + return value; + }); + } else { + this.root = undefined; + } + + this._onDidChangeTreeData.fire(); + } + + getElementByRange(start: number, end: number): SyntaxElement | undefined { + if (this.root === undefined) { + return undefined; + } + + let result: SyntaxElement = this.root; + + if (this.root.start === start && this.root.end === end) { + return result; + } + + let children = this.getRawChildren(this.root); + + outer: while (true) { + for (const child of children) { + if (child.start <= start && child.end >= end) { + result = child; + if (start === end && start === child.end) { + // When the cursor is on the very end of a token, + // we assume the user wants the next token instead. + continue; + } + + if (child.type === "Token") { + return result; + } else { + children = this.getRawChildren(child); + continue outer; + } + } + } + + return result; + } + } + + async toggleWhitespace() { + this.hideWhitespace = !this.hideWhitespace; + this._onDidChangeTreeData.fire(); + await setContextValue("rustSyntaxTree.hideWhitespace", this.hideWhitespace); + } +} + +export type SyntaxNode = { + type: "Node"; + kind: string; + start: number; + end: number; + istart?: number; + iend?: number; + children: SyntaxElement[]; + parent?: SyntaxElement; +}; + +type SyntaxToken = { + type: "Token"; + kind: string; + start: number; + end: number; + istart?: number; + iend?: number; + parent?: SyntaxElement; +}; + +export type SyntaxElement = SyntaxNode | SyntaxToken; + +export class SyntaxTreeItem extends vscode.TreeItem { + constructor(private readonly element: SyntaxElement) { + super(element.kind); + const icon = getIcon(element.kind); + if (element.type === "Node") { + this.contextValue = "syntaxNode"; + this.iconPath = icon ?? new vscode.ThemeIcon("list-tree"); + this.collapsibleState = vscode.TreeItemCollapsibleState.Expanded; + } else { + this.contextValue = "syntaxToken"; + this.iconPath = icon ?? new vscode.ThemeIcon("symbol-string"); + this.collapsibleState = vscode.TreeItemCollapsibleState.None; + } + + if (element.istart !== undefined && element.iend !== undefined) { + this.description = `${this.element.istart}..${this.element.iend}`; + } else { + this.description = `${this.element.start}..${this.element.end}`; + } + } +} + +function getIcon(kind: string): vscode.ThemeIcon | undefined { + const icon = iconTable[kind]; + + if (icon !== undefined) { + return icon; + } + + if (kind.endsWith("_KW")) { + return new vscode.ThemeIcon( + "symbol-keyword", + new vscode.ThemeColor("symbolIcon.keywordForeground"), + ); + } + + if (operators.includes(kind)) { + return new vscode.ThemeIcon( + "symbol-operator", + new vscode.ThemeColor("symbolIcon.operatorForeground"), + ); + } + + return undefined; +} + +const iconTable: Record<string, vscode.ThemeIcon> = { + CALL_EXPR: new vscode.ThemeIcon("call-outgoing"), + COMMENT: new vscode.ThemeIcon("comment"), + ENUM: new vscode.ThemeIcon("symbol-enum", new vscode.ThemeColor("symbolIcon.enumForeground")), + FN: new vscode.ThemeIcon( + "symbol-function", + new vscode.ThemeColor("symbolIcon.functionForeground"), + ), + FLOAT_NUMBER: new vscode.ThemeIcon( + "symbol-number", + new vscode.ThemeColor("symbolIcon.numberForeground"), + ), + INDEX_EXPR: new vscode.ThemeIcon( + "symbol-array", + new vscode.ThemeColor("symbolIcon.arrayForeground"), + ), + INT_NUMBER: new vscode.ThemeIcon( + "symbol-number", + new vscode.ThemeColor("symbolIcon.numberForeground"), + ), + LITERAL: new vscode.ThemeIcon( + "symbol-misc", + new vscode.ThemeColor("symbolIcon.miscForeground"), + ), + MODULE: new vscode.ThemeIcon( + "symbol-module", + new vscode.ThemeColor("symbolIcon.moduleForeground"), + ), + METHOD_CALL_EXPR: new vscode.ThemeIcon("call-outgoing"), + PARAM: new vscode.ThemeIcon( + "symbol-parameter", + new vscode.ThemeColor("symbolIcon.parameterForeground"), + ), + RECORD_FIELD: new vscode.ThemeIcon( + "symbol-field", + new vscode.ThemeColor("symbolIcon.fieldForeground"), + ), + SOURCE_FILE: new vscode.ThemeIcon("file-code"), + STRING: new vscode.ThemeIcon("quote"), + STRUCT: new vscode.ThemeIcon( + "symbol-struct", + new vscode.ThemeColor("symbolIcon.structForeground"), + ), + TRAIT: new vscode.ThemeIcon( + "symbol-interface", + new vscode.ThemeColor("symbolIcon.interfaceForeground"), + ), + TYPE_PARAM: new vscode.ThemeIcon( + "symbol-type-parameter", + new vscode.ThemeColor("symbolIcon.typeParameterForeground"), + ), + VARIANT: new vscode.ThemeIcon( + "symbol-enum-member", + new vscode.ThemeColor("symbolIcon.enumMemberForeground"), + ), + WHITESPACE: new vscode.ThemeIcon("whitespace"), +}; + +const operators = [ + "PLUS", + "PLUSEQ", + "MINUS", + "MINUSEQ", + "STAR", + "STAREQ", + "SLASH", + "SLASHEQ", + "PERCENT", + "PERCENTEQ", + "CARET", + "CARETEQ", + "AMP", + "AMPEQ", + "AMP2", + "PIPE", + "PIPEEQ", + "PIPE2", + "SHL", + "SHLEQ", + "SHR", + "SHREQ", + "EQ", + "EQ2", + "BANG", + "NEQ", + "L_ANGLE", + "LTEQ", + "R_ANGLE", + "GTEQ", + "COLON2", + "THIN_ARROW", + "FAT_ARROW", + "DOT", + "DOT2", + "DOT2EQ", + "AT", +]; diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs index 11f98f50790..074bc43388a 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs @@ -181,15 +181,15 @@ impl Message { Ok(Some(msg)) } - pub fn write(self, w: &mut impl Write) -> io::Result<()> { + pub fn write(&self, w: &mut impl Write) -> io::Result<()> { self._write(w) } - fn _write(self, w: &mut dyn Write) -> io::Result<()> { + fn _write(&self, w: &mut dyn Write) -> io::Result<()> { #[derive(Serialize)] - struct JsonRpc { + struct JsonRpc<'a> { jsonrpc: &'static str, #[serde(flatten)] - msg: Message, + msg: &'a Message, } let text = serde_json::to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?; write_msg_text(w, &text) diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs b/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs index 36d728456f7..48400abf229 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/socket.rs @@ -15,8 +15,11 @@ pub(crate) fn socket_transport( stream: TcpStream, ) -> (Sender<Message>, Receiver<Message>, IoThreads) { let (reader_receiver, reader) = make_reader(stream.try_clone().unwrap()); - let (writer_sender, writer) = make_write(stream); - let io_threads = make_io_threads(reader, writer); + let (writer_sender, writer, messages_to_drop) = make_write(stream); + let dropper = std::thread::spawn(move || { + messages_to_drop.into_iter().for_each(drop); + }); + let io_threads = make_io_threads(reader, writer, dropper); (writer_sender, reader_receiver, io_threads) } @@ -36,11 +39,21 @@ fn make_reader(stream: TcpStream) -> (Receiver<Message>, thread::JoinHandle<io:: (reader_receiver, reader) } -fn make_write(mut stream: TcpStream) -> (Sender<Message>, thread::JoinHandle<io::Result<()>>) { +fn make_write( + mut stream: TcpStream, +) -> (Sender<Message>, thread::JoinHandle<io::Result<()>>, Receiver<Message>) { let (writer_sender, writer_receiver) = bounded::<Message>(0); + let (drop_sender, drop_receiver) = bounded::<Message>(0); let writer = thread::spawn(move || { - writer_receiver.into_iter().try_for_each(|it| it.write(&mut stream)).unwrap(); + writer_receiver + .into_iter() + .try_for_each(|it| { + let result = it.write(&mut stream); + let _ = drop_sender.send(it); + result + }) + .unwrap(); Ok(()) }); - (writer_sender, writer) + (writer_sender, writer, drop_receiver) } diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs index 279a6bce080..8344c9f56b5 100644 --- a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs +++ b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs @@ -11,15 +11,24 @@ use crate::Message; /// Creates an LSP connection via stdio. pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThreads) { + let (drop_sender, drop_receiver) = bounded::<Message>(0); let (writer_sender, writer_receiver) = bounded::<Message>(0); let writer = thread::Builder::new() .name("LspServerWriter".to_owned()) .spawn(move || { let stdout = stdout(); let mut stdout = stdout.lock(); - writer_receiver.into_iter().try_for_each(|it| it.write(&mut stdout)) + writer_receiver.into_iter().try_for_each(|it| { + let result = it.write(&mut stdout); + let _ = drop_sender.send(it); + result + }) }) .unwrap(); + let dropper = thread::Builder::new() + .name("LspMessageDropper".to_owned()) + .spawn(move || drop_receiver.into_iter().for_each(drop)) + .unwrap(); let (reader_sender, reader_receiver) = bounded::<Message>(0); let reader = thread::Builder::new() .name("LspServerReader".to_owned()) @@ -41,7 +50,7 @@ pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThread Ok(()) }) .unwrap(); - let threads = IoThreads { reader, writer }; + let threads = IoThreads { reader, writer, dropper }; (writer_sender, reader_receiver, threads) } @@ -49,13 +58,15 @@ pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThread pub(crate) fn make_io_threads( reader: thread::JoinHandle<io::Result<()>>, writer: thread::JoinHandle<io::Result<()>>, + dropper: thread::JoinHandle<()>, ) -> IoThreads { - IoThreads { reader, writer } + IoThreads { reader, writer, dropper } } pub struct IoThreads { reader: thread::JoinHandle<io::Result<()>>, writer: thread::JoinHandle<io::Result<()>>, + dropper: thread::JoinHandle<()>, } impl IoThreads { @@ -64,6 +75,12 @@ impl IoThreads { Ok(r) => r?, Err(err) => std::panic::panic_any(err), } + match self.dropper.join() { + Ok(_) => (), + Err(err) => { + std::panic::panic_any(err); + } + } match self.writer.join() { Ok(r) => r, Err(err) => { diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version index 517fdfe18ed..2d9a927c638 100644 --- a/src/tools/rust-analyzer/rust-version +++ b/src/tools/rust-analyzer/rust-version @@ -1 +1 @@ -fb546ee09b226bc4dd4b712d35a372d923c4fa54 +9a1d156f38c51441ee51e5a068f1d0caf4bb0f27 diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 575716eb6dd..6f0fd09b353 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -1,5 +1,3 @@ -run-make/cat-and-grep-sanity-check/Makefile -run-make/jobserver-error/Makefile run-make/split-debuginfo/Makefile run-make/symbol-mangling-hashed/Makefile run-make/translation/Makefile diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index d4cbc37f6d2..faa0db27b2b 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -253,6 +253,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "bitflags", "blake3", "block-buffer", + "bstr", "byteorder", // via ruzstd in object in thorin-dwp "cc", "cfg-if", @@ -438,6 +439,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "windows-implement", "windows-interface", "windows-result", + "windows-strings", "windows-sys", "windows-targets", "windows_aarch64_gnullvm", diff --git a/src/tools/tidy/src/ext_tool_checks.rs b/src/tools/tidy/src/ext_tool_checks.rs index 6269d91c7ec..2a4cff1d12e 100644 --- a/src/tools/tidy/src/ext_tool_checks.rs +++ b/src/tools/tidy/src/ext_tool_checks.rs @@ -89,74 +89,45 @@ fn check_impl( if python_lint { eprintln!("linting python files"); - let mut cfg_args_ruff = cfg_args.clone(); - let mut file_args_ruff = file_args.clone(); - - let mut cfg_path = root_path.to_owned(); - cfg_path.extend(RUFF_CONFIG_PATH); - let mut cache_dir = outdir.to_owned(); - cache_dir.extend(RUFF_CACHE_PATH); - - cfg_args_ruff.extend([ - "--config".as_ref(), - cfg_path.as_os_str(), - "--cache-dir".as_ref(), - cache_dir.as_os_str(), - ]); - - if file_args_ruff.is_empty() { - file_args_ruff.push(root_path.as_os_str()); - } - - let mut args = merge_args(&cfg_args_ruff, &file_args_ruff); - args.insert(0, "check".as_ref()); - let res = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); + let py_path = py_path.as_ref().unwrap(); + let res = run_ruff(root_path, outdir, py_path, &cfg_args, &file_args, &["check".as_ref()]); if res.is_err() && show_diff { eprintln!("\npython linting failed! Printing diff suggestions:"); - args.insert(1, "--diff".as_ref()); - let _ = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); + let _ = run_ruff(root_path, outdir, py_path, &cfg_args, &file_args, &[ + "check".as_ref(), + "--diff".as_ref(), + ]); } // Rethrow error let _ = res?; } if python_fmt { - let mut cfg_args_ruff = cfg_args.clone(); - let mut file_args_ruff = file_args.clone(); - + let mut args: Vec<&OsStr> = vec!["format".as_ref()]; if bless { eprintln!("formatting python files"); } else { eprintln!("checking python file formatting"); - cfg_args_ruff.push("--check".as_ref()); - } - - let mut cfg_path = root_path.to_owned(); - cfg_path.extend(RUFF_CONFIG_PATH); - let mut cache_dir = outdir.to_owned(); - cache_dir.extend(RUFF_CACHE_PATH); - - cfg_args_ruff.extend(["--config".as_ref(), cfg_path.as_os_str()]); - - if file_args_ruff.is_empty() { - file_args_ruff.push(root_path.as_os_str()); + args.push("--check".as_ref()); } - let mut args = merge_args(&cfg_args_ruff, &file_args_ruff); - args.insert(0, "format".as_ref()); - let res = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); + let py_path = py_path.as_ref().unwrap(); + let res = run_ruff(root_path, outdir, py_path, &cfg_args, &file_args, &args); - if res.is_err() && show_diff { - eprintln!("\npython formatting does not match! Printing diff:"); - - args.insert(0, "--diff".as_ref()); - let _ = py_runner(py_path.as_ref().unwrap(), true, None, "ruff", &args); - } if res.is_err() && !bless { + if show_diff { + eprintln!("\npython formatting does not match! Printing diff:"); + + let _ = run_ruff(root_path, outdir, py_path, &cfg_args, &file_args, &[ + "format".as_ref(), + "--diff".as_ref(), + ]); + } eprintln!("rerun tidy with `--extra-checks=py:fmt --bless` to reformat Python code"); } + // Rethrow error let _ = res?; } @@ -247,6 +218,38 @@ fn check_impl( Ok(()) } +fn run_ruff( + root_path: &Path, + outdir: &Path, + py_path: &Path, + cfg_args: &[&OsStr], + file_args: &[&OsStr], + ruff_args: &[&OsStr], +) -> Result<(), Error> { + let mut cfg_args_ruff = cfg_args.into_iter().copied().collect::<Vec<_>>(); + let mut file_args_ruff = file_args.into_iter().copied().collect::<Vec<_>>(); + + let mut cfg_path = root_path.to_owned(); + cfg_path.extend(RUFF_CONFIG_PATH); + let mut cache_dir = outdir.to_owned(); + cache_dir.extend(RUFF_CACHE_PATH); + + cfg_args_ruff.extend([ + "--config".as_ref(), + cfg_path.as_os_str(), + "--cache-dir".as_ref(), + cache_dir.as_os_str(), + ]); + + if file_args_ruff.is_empty() { + file_args_ruff.push(root_path.as_os_str()); + } + + let mut args: Vec<&OsStr> = ruff_args.into_iter().copied().collect(); + args.extend(merge_args(&cfg_args_ruff, &file_args_ruff)); + py_runner(py_path, true, None, "ruff", &args) +} + /// Helper to create `cfg1 cfg2 -- file1 file2` output fn merge_args<'a>(cfg_args: &[&'a OsStr], file_args: &[&'a OsStr]) -> Vec<&'a OsStr> { let mut args = cfg_args.to_owned(); @@ -321,8 +324,16 @@ fn get_or_create_venv(venv_path: &Path, src_reqs_path: &Path) -> Result<PathBuf, fn create_venv_at_path(path: &Path) -> Result<(), Error> { /// Preferred python versions in order. Newest to oldest then current /// development versions - const TRY_PY: &[&str] = - &["python3.11", "python3.10", "python3.9", "python3", "python", "python3.12", "python3.13"]; + const TRY_PY: &[&str] = &[ + "python3.13", + "python3.12", + "python3.11", + "python3.10", + "python3.9", + "python3", + "python", + "python3.14", + ]; let mut sys_py = None; let mut found = Vec::new(); @@ -357,22 +368,40 @@ fn create_venv_at_path(path: &Path) -> Result<(), Error> { return Err(ret); }; - eprintln!("creating virtual environment at '{}' using '{sys_py}'", path.display()); - let out = Command::new(sys_py).args(["-m", "virtualenv"]).arg(path).output().unwrap(); + // First try venv, which should be packaged in the Python3 standard library. + // If it is not available, try to create the virtual environment using the + // virtualenv package. + if try_create_venv(sys_py, path, "venv").is_ok() { + return Ok(()); + } + try_create_venv(sys_py, path, "virtualenv") +} + +fn try_create_venv(python: &str, path: &Path, module: &str) -> Result<(), Error> { + eprintln!( + "creating virtual environment at '{}' using '{python}' and '{module}'", + path.display() + ); + let out = Command::new(python).args(["-m", module]).arg(path).output().unwrap(); if out.status.success() { return Ok(()); } let stderr = String::from_utf8_lossy(&out.stderr); - let err = if stderr.contains("No module named virtualenv") { + let err = if stderr.contains(&format!("No module named {module}")) { Error::Generic(format!( - "virtualenv not found: you may need to install it \ - (`{sys_py} -m pip install virtualenv`)" + r#"{module} not found: you may need to install it: +`{python} -m pip install {module}` +If you see an error about "externally managed environment" when running the above command, +either install `{module}` using your system package manager +(e.g. `sudo apt-get install {python}-{module}`) or create a virtual environment manually, install +`{module}` in it and then activate it before running tidy. +"# )) } else { Error::Generic(format!( - "failed to create venv at '{}' using {sys_py}: {stderr}", + "failed to create venv at '{}' using {python} -m {module}: {stderr}", path.display() )) }; diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 54de2ef8314..839d23fb9a7 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -183,7 +183,6 @@ ui/async-await/issue-67252-unnamed-future.rs ui/async-await/issue-67651.rs ui/async-await/issue-67765-async-diagnostic.rs ui/async-await/issue-68112.rs -ui/async-await/issue-68523-start.rs ui/async-await/issue-68523.rs ui/async-await/issue-69446-fnmut-capture.rs ui/async-await/issue-70594.rs @@ -410,7 +409,6 @@ ui/closure_context/issue-26046-fn-once.rs ui/closure_context/issue-42065.rs ui/closures/2229_closure_analysis/issue-118144.rs ui/closures/2229_closure_analysis/issue-87378.rs -ui/closures/2229_closure_analysis/issue-87987.rs ui/closures/2229_closure_analysis/issue-88118-2.rs ui/closures/2229_closure_analysis/issue-88476.rs ui/closures/2229_closure_analysis/issue-89606.rs @@ -1387,7 +1385,6 @@ ui/issue-18502.rs ui/issue-24106.rs ui/issue-76387-llvm-miscompile.rs ui/issues-71798.rs -ui/issues/auxiliary/issue-111011.rs ui/issues/auxiliary/issue-11224.rs ui/issues/auxiliary/issue-11508.rs ui/issues/auxiliary/issue-11529.rs @@ -2205,7 +2202,6 @@ ui/issues/issue-3895.rs ui/issues/issue-38954.rs ui/issues/issue-38987.rs ui/issues/issue-39089.rs -ui/issues/issue-39175.rs ui/issues/issue-39211.rs ui/issues/issue-39367.rs ui/issues/issue-39548.rs @@ -2395,7 +2391,6 @@ ui/issues/issue-50618.rs ui/issues/issue-5062.rs ui/issues/issue-5067.rs ui/issues/issue-50688.rs -ui/issues/issue-50714-1.rs ui/issues/issue-50714.rs ui/issues/issue-50761.rs ui/issues/issue-50781.rs @@ -2630,7 +2625,6 @@ ui/issues/issue-9259.rs ui/issues/issue-92741.rs ui/issues/issue-9382.rs ui/issues/issue-9446.rs -ui/issues/issue-9575.rs ui/issues/issue-9719.rs ui/issues/issue-9725.rs ui/issues/issue-9737.rs @@ -2645,7 +2639,6 @@ ui/issues/issue-9968.rs ui/issues/issue-99838.rs ui/iterators/issue-28098.rs ui/iterators/issue-58952-filter-type-length.rs -ui/lang-items/issue-19660.rs ui/lang-items/issue-83471.rs ui/lang-items/issue-87573.rs ui/late-bound-lifetimes/issue-36381.rs @@ -3702,7 +3695,6 @@ ui/rfcs/rfc-2005-default-binding-mode/issue-44912-or.rs ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs ui/rfcs/rfc-2093-infer-outlives/issue-54467.rs ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-main.rs -ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs ui/rfcs/rfc-2396-target_feature-11/issue-108655-inline-always-closure.rs ui/rfcs/rfc-2396-target_feature-11/issue-99876.rs ui/rfcs/rfc-2497-if-let-chains/issue-88498.rs @@ -3862,7 +3854,6 @@ ui/suggestions/issue-106443-sugg-clone-for-arg.rs ui/suggestions/issue-106443-sugg-clone-for-bound.rs ui/suggestions/issue-107860.rs ui/suggestions/issue-108470.rs -ui/suggestions/issue-109195.rs ui/suggestions/issue-109291.rs ui/suggestions/issue-109396.rs ui/suggestions/issue-109436.rs diff --git a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs index 00edf99a30d..ee92d302db3 100644 --- a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs +++ b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs @@ -58,7 +58,7 @@ pub fn check(tests_path: impl AsRef<Path>, bad: &mut bool) { let mut expected_revisions = BTreeSet::new(); - let contents = std::fs::read_to_string(test).unwrap(); + let Ok(contents) = std::fs::read_to_string(test) else { continue }; // Collect directives. iter_header(&contents, &mut |HeaderLine { revision, directive, .. }| { diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 401169c838f..d66ba157d10 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use ignore::Walk; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1667; +const ISSUES_ENTRY_LIMIT: u32 = 1658; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml index 965e9b01a44..f8ae91f9e6f 100644 --- a/src/tools/wasm-component-ld/Cargo.toml +++ b/src/tools/wasm-component-ld/Cargo.toml @@ -10,4 +10,4 @@ name = "wasm-component-ld" path = "src/main.rs" [dependencies] -wasm-component-ld = "0.5.11" +wasm-component-ld = "0.5.12" diff --git a/tests/assembly/powerpc64-struct-abi.rs b/tests/assembly/powerpc64-struct-abi.rs index 7052937acf6..db08a514819 100644 --- a/tests/assembly/powerpc64-struct-abi.rs +++ b/tests/assembly/powerpc64-struct-abi.rs @@ -50,9 +50,9 @@ struct ThreeU8s(u8, u8, u8); // CHECK-LABEL: read_large // aix: lwz [[REG1:.*]], 16(4) -// aix-NEXT: lxvd2x 0, 0, 4 +// aix-NEXT: lxv{{d2x|w4x}} 0, 0, 4 // aix-NEXT: stw [[REG1]], 16(3) -// aix-NEXT: stxvd2x 0, 0, 3 +// aix-NEXT: stxv{{d2x|w4x}} 0, 0, 3 // be: lwz [[REG1:.*]], 16(4) // be-NEXT: stw [[REG1]], 16(3) // be-NEXT: ld [[REG2:.*]], 8(4) @@ -118,8 +118,8 @@ extern "C" fn read_small(x: &ThreeU8s) -> ThreeU8s { // aix-NEXT: std 4, 56(1) // aix-NEXT: stw [[REG1]], 16(6) // aix-NEXT: addi [[REG2:.*]], 1, 48 -// aix-NEXT: lxvd2x 0, 0, [[REG2]] -// aix-NEXT: stxvd2x 0, 0, 6 +// aix-NEXT: lxv{{d2x|w4x}} 0, 0, [[REG2]] +// aix-NEXT: stxv{{d2x|w4x}} 0, 0, 6 // elf: std 3, 0(6) // be-NEXT: rldicl [[REG1:.*]], 5, 32, 32 // elf-NEXT: std 4, 8(6) diff --git a/tests/assembly/simd-intrinsic-gather.rs b/tests/assembly/simd-intrinsic-gather.rs index d2b5a1507f0..29b0df64065 100644 --- a/tests/assembly/simd-intrinsic-gather.rs +++ b/tests/assembly/simd-intrinsic-gather.rs @@ -35,8 +35,8 @@ pub unsafe extern "C" fn gather_f64x4(mask: m64x4, ptrs: pf64x4) -> f64x4 { // FIXME: This should also get checked to generate a gather instruction for avx2. // Currently llvm scalarizes this code, see https://github.com/llvm/llvm-project/issues/59789 // - // x86-avx512: vpsllq ymm0, ymm0, 63 - // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NOT: vpsllq + // x86-avx512: vpmovq2m k1, ymm0 // x86-avx512-NEXT: vpxor xmm0, xmm0, xmm0 // x86-avx512-NEXT: vgatherqpd ymm0 {k1}, {{(ymmword)|(qword)}} ptr [1*ymm1] simd_gather(f64x4([0_f64, 0_f64, 0_f64, 0_f64]), ptrs, mask) diff --git a/tests/assembly/simd-intrinsic-mask-load.rs b/tests/assembly/simd-intrinsic-mask-load.rs index b650e1cee30..89b35ed7734 100644 --- a/tests/assembly/simd-intrinsic-mask-load.rs +++ b/tests/assembly/simd-intrinsic-mask-load.rs @@ -47,9 +47,9 @@ extern "rust-intrinsic" { pub unsafe extern "C" fn load_i8x16(mask: m8x16, pointer: *const i8) -> i8x16 { // Since avx2 supports no masked loads for bytes, the code tests each individual bit // and jumps to code that inserts individual bytes. - // x86-avx2: vpsllw xmm0, xmm0, 7 - // x86-avx2-NEXT: vpmovmskb eax, xmm0 - // x86-avx2-NEXT: vpxor xmm0, xmm0 + // x86-avx2-NOT: vpsllw + // x86-avx2-DAG: vpmovmskb eax + // x86-avx2-DAG: vpxor // x86-avx2-NEXT: test al, 1 // x86-avx2-NEXT: jne // x86-avx2-NEXT: test al, 2 @@ -58,8 +58,8 @@ pub unsafe extern "C" fn load_i8x16(mask: m8x16, pointer: *const i8) -> i8x16 { // x86-avx2-NEXT: vmovd xmm0, [[REG]] // x86-avx2-DAG: vpinsrb xmm0, xmm0, byte ptr [rdi + 1], 1 // - // x86-avx512: vpsllw xmm0, xmm0, 7 - // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NOT: vpsllw + // x86-avx512: vpmovb2m k1, xmm0 // x86-avx512-NEXT: vmovdqu8 xmm0 {k1} {z}, xmmword ptr [rdi] simd_masked_load(mask, pointer, i8x16([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) } @@ -67,11 +67,11 @@ pub unsafe extern "C" fn load_i8x16(mask: m8x16, pointer: *const i8) -> i8x16 { // CHECK-LABEL: load_f32x8 #[no_mangle] pub unsafe extern "C" fn load_f32x8(mask: m32x8, pointer: *const f32) -> f32x8 { - // x86-avx2: vpslld ymm0, ymm0, 31 - // x86-avx2-NEXT: vmaskmovps ymm0, ymm0, ymmword ptr [rdi] + // x86-avx2-NOT: vpslld + // x86-avx2: vmaskmovps ymm0, ymm0, ymmword ptr [rdi] // - // x86-avx512: vpslld ymm0, ymm0, 31 - // x86-avx512-NEXT: vpmovd2m k1, ymm0 + // x86-avx512-NOT: vpslld + // x86-avx512: vpmovd2m k1, ymm0 // x86-avx512-NEXT: vmovups ymm0 {k1} {z}, ymmword ptr [rdi] simd_masked_load(mask, pointer, f32x8([0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32])) } @@ -79,11 +79,10 @@ pub unsafe extern "C" fn load_f32x8(mask: m32x8, pointer: *const f32) -> f32x8 { // CHECK-LABEL: load_f64x4 #[no_mangle] pub unsafe extern "C" fn load_f64x4(mask: m64x4, pointer: *const f64) -> f64x4 { - // x86-avx2: vpsllq ymm0, ymm0, 63 - // x86-avx2-NEXT: vmaskmovpd ymm0, ymm0, ymmword ptr [rdi] + // x86-avx2-NOT: vpsllq + // x86-avx2: vmaskmovpd ymm0, ymm0, ymmword ptr [rdi] // - // x86-avx512: vpsllq ymm0, ymm0, 63 - // x86-avx512-NEXT: vpmovq2m k1, ymm0 - // x86-avx512-NEXT: vmovupd ymm0 {k1} {z}, ymmword ptr [rdi] + // x86-avx512-NOT: vpsllq + // x86-avx512: vpmovq2m k1, ymm0 simd_masked_load(mask, pointer, f64x4([0_f64, 0_f64, 0_f64, 0_f64])) } diff --git a/tests/assembly/simd-intrinsic-mask-reduce.rs b/tests/assembly/simd-intrinsic-mask-reduce.rs index 61d7aa59093..8ac55990c73 100644 --- a/tests/assembly/simd-intrinsic-mask-reduce.rs +++ b/tests/assembly/simd-intrinsic-mask-reduce.rs @@ -31,29 +31,30 @@ extern "rust-intrinsic" { // CHECK-LABEL: mask_reduce_all: #[no_mangle] pub unsafe extern "C" fn mask_reduce_all(m: mask8x16) -> bool { - // x86: psllw xmm0, 7 - // x86-NEXT: pmovmskb eax, xmm0 - // x86-NEXT: {{cmp ax, -1|xor eax, 65535}} + // x86-NOT: psllw + // x86: pmovmskb eax, xmm0 + // x86-NEXT: {{cmp ax, -1|cmp eax, 65535|xor eax, 65535}} // x86-NEXT: sete al // - // aarch64: shl v0.16b, v0.16b, #7 - // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 - // aarch64-NEXT: uminv b0, v0.16b - // aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0 - // aarch64-NEXT: and w0, [[REG]], #0x1 + // aarch64-NOT: shl + // aarch64: cmge v0.16b, v0.16b, #0 + // aarch64-DAG: mov [[REG1:[a-z0-9]+]], #1 + // aarch64-DAG: umaxv b0, v0.16b + // aarch64-NEXT: fmov [[REG2:[a-z0-9]+]], s0 + // aarch64-NEXT: bic w0, [[REG1]], [[REG2]] simd_reduce_all(m) } // CHECK-LABEL: mask_reduce_any: #[no_mangle] pub unsafe extern "C" fn mask_reduce_any(m: mask8x16) -> bool { - // x86: psllw xmm0, 7 - // x86-NEXT: pmovmskb + // x86-NOT: psllw + // x86: pmovmskb // x86-NEXT: test eax, eax // x86-NEXT: setne al // - // aarch64: shl v0.16b, v0.16b, #7 - // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 + // aarch64-NOT: shl + // aarch64: cmlt v0.16b, v0.16b, #0 // aarch64-NEXT: umaxv b0, v0.16b // aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0 // aarch64-NEXT: and w0, [[REG]], #0x1 diff --git a/tests/assembly/simd-intrinsic-mask-store.rs b/tests/assembly/simd-intrinsic-mask-store.rs index 95a3b28b967..1686fd5dd88 100644 --- a/tests/assembly/simd-intrinsic-mask-store.rs +++ b/tests/assembly/simd-intrinsic-mask-store.rs @@ -47,8 +47,8 @@ extern "rust-intrinsic" { pub unsafe extern "C" fn store_i8x16(mask: m8x16, pointer: *mut i8, value: i8x16) { // Since avx2 supports no masked stores for bytes, the code tests each individual bit // and jumps to code that extracts individual bytes to memory. - // x86-avx2: vpsllw xmm0, xmm0, 7 - // x86-avx2-NEXT: vpmovmskb eax, xmm0 + // x86-avx2-NOT: vpsllw + // x86-avx2: vpmovmskb eax, xmm0 // x86-avx2-NEXT: test al, 1 // x86-avx2-NEXT: jne // x86-avx2-NEXT: test al, 2 @@ -56,8 +56,8 @@ pub unsafe extern "C" fn store_i8x16(mask: m8x16, pointer: *mut i8, value: i8x16 // x86-avx2-DAG: vpextrb byte ptr [rdi + 1], xmm1, 1 // x86-avx2-DAG: vpextrb byte ptr [rdi], xmm1, 0 // - // x86-avx512: vpsllw xmm0, xmm0, 7 - // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NOT: vpsllw + // x86-avx512: vpmovb2m k1, xmm0 // x86-avx512-NEXT: vmovdqu8 xmmword ptr [rdi] {k1}, xmm1 simd_masked_store(mask, pointer, value) } @@ -65,11 +65,11 @@ pub unsafe extern "C" fn store_i8x16(mask: m8x16, pointer: *mut i8, value: i8x16 // CHECK-LABEL: store_f32x8 #[no_mangle] pub unsafe extern "C" fn store_f32x8(mask: m32x8, pointer: *mut f32, value: f32x8) { - // x86-avx2: vpslld ymm0, ymm0, 31 - // x86-avx2-NEXT: vmaskmovps ymmword ptr [rdi], ymm0, ymm1 + // x86-avx2-NOT: vpslld + // x86-avx2: vmaskmovps ymmword ptr [rdi], ymm0, ymm1 // - // x86-avx512: vpslld ymm0, ymm0, 31 - // x86-avx512-NEXT: vpmovd2m k1, ymm0 + // x86-avx512-NOT: vpslld + // x86-avx512: vpmovd2m k1, ymm0 // x86-avx512-NEXT: vmovups ymmword ptr [rdi] {k1}, ymm1 simd_masked_store(mask, pointer, value) } @@ -77,11 +77,11 @@ pub unsafe extern "C" fn store_f32x8(mask: m32x8, pointer: *mut f32, value: f32x // CHECK-LABEL: store_f64x4 #[no_mangle] pub unsafe extern "C" fn store_f64x4(mask: m64x4, pointer: *mut f64, value: f64x4) { - // x86-avx2: vpsllq ymm0, ymm0, 63 - // x86-avx2-NEXT: vmaskmovpd ymmword ptr [rdi], ymm0, ymm1 + // x86-avx2-NOT: vpsllq + // x86-avx2: vmaskmovpd ymmword ptr [rdi], ymm0, ymm1 // - // x86-avx512: vpsllq ymm0, ymm0, 63 - // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NOT: vpsllq + // x86-avx512: vpmovq2m k1, ymm0 // x86-avx512-NEXT: vmovupd ymmword ptr [rdi] {k1}, ymm1 simd_masked_store(mask, pointer, value) } diff --git a/tests/assembly/simd-intrinsic-scatter.rs b/tests/assembly/simd-intrinsic-scatter.rs index f7e08e33faa..3f4d7569c59 100644 --- a/tests/assembly/simd-intrinsic-scatter.rs +++ b/tests/assembly/simd-intrinsic-scatter.rs @@ -32,8 +32,8 @@ extern "rust-intrinsic" { // CHECK-LABEL: scatter_f64x4 #[no_mangle] pub unsafe extern "C" fn scatter_f64x4(values: f64x4, ptrs: pf64x4, mask: m64x4) { - // x86-avx512: vpsllq ymm2, ymm2, 63 - // x86-avx512-NEXT: vpmovq2m k1, ymm2 + // x86-avx512-NOT: vpsllq + // x86-avx512: vpmovq2m k1, ymm2 // x86-avx512-NEXT: vscatterqpd {{(ymmword)|(qword)}} ptr [1*ymm1] {k1}, ymm0 simd_scatter(values, ptrs, mask) } diff --git a/tests/assembly/simd-intrinsic-select.rs b/tests/assembly/simd-intrinsic-select.rs index 57fd36fd9e3..803abf2eeb3 100644 --- a/tests/assembly/simd-intrinsic-select.rs +++ b/tests/assembly/simd-intrinsic-select.rs @@ -58,15 +58,15 @@ extern "rust-intrinsic" { // CHECK-LABEL: select_i8x16 #[no_mangle] pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16 { - // x86-avx2: vpsllw xmm0, xmm0, 7 - // x86-avx2-NEXT: vpblendvb xmm0, xmm2, xmm1, xmm0 + // x86-avx2-NOT: vpsllw + // x86-avx2: vpblendvb xmm0, xmm2, xmm1, xmm0 // - // x86-avx512: vpsllw xmm0, xmm0, 7 - // x86-avx512-NEXT: vpmovb2m k1, xmm0 + // x86-avx512-NOT: vpsllw + // x86-avx512: vpmovb2m k1, xmm0 // x86-avx512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1 // - // aarch64: shl v0.16b, v0.16b, #7 - // aarch64-NEXT: cmlt v0.16b, v0.16b, #0 + // aarch64-NOT: shl + // aarch64: cmlt v0.16b, v0.16b, #0 // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b simd_select(mask, a, b) } @@ -74,15 +74,15 @@ pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16 // CHECK-LABEL: select_f32x4 #[no_mangle] pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4 { - // x86-avx2: vpslld xmm0, xmm0, 31 - // x86-avx2-NEXT: vblendvps xmm0, xmm2, xmm1, xmm0 + // x86-avx2-NOT: vpslld + // x86-avx2: vblendvps xmm0, xmm2, xmm1, xmm0 // - // x86-avx512: vpslld xmm0, xmm0, 31 - // x86-avx512-NEXT: vpmovd2m k1, xmm0 + // x86-avx512-NOT: vpslld + // x86-avx512: vpmovd2m k1, xmm0 // x86-avx512-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1 // - // aarch64: shl v0.4s, v0.4s, #31 - // aarch64-NEXT: cmlt v0.4s, v0.4s, #0 + // aarch64-NOT: shl + // aarch64: cmlt v0.4s, v0.4s, #0 // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b simd_select(mask, a, b) } @@ -90,15 +90,15 @@ pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4 // CHECK-LABEL: select_f64x2 #[no_mangle] pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 { - // x86-avx2: vpsllq xmm0, xmm0, 63 - // x86-avx2-NEXT: vblendvpd xmm0, xmm2, xmm1, xmm0 + // x86-avx2-NOT: vpsllq + // x86-avx2: vblendvpd xmm0, xmm2, xmm1, xmm0 // - // x86-avx512: vpsllq xmm0, xmm0, 63 - // x86-avx512-NEXT: vpmovq2m k1, xmm0 + // x86-avx512-NOT: vpsllq + // x86-avx512: vpmovq2m k1, xmm0 // x86-avx512-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1 // - // aarch64: shl v0.2d, v0.2d, #63 - // aarch64-NEXT: cmlt v0.2d, v0.2d, #0 + // aarch64-NOT: shl + // aarch64: cmlt v0.2d, v0.2d, #0 // aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b simd_select(mask, a, b) } @@ -108,11 +108,11 @@ pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 { // The parameter is a 256 bit vector which in the C abi is only valid for avx targets. // - // x86-avx2: vpsllq ymm0, ymm0, 63 - // x86-avx2-NEXT: vblendvpd ymm0, ymm2, ymm1, ymm0 + // x86-avx2-NOT: vpsllq + // x86-avx2: vblendvpd ymm0, ymm2, ymm1, ymm0 // - // x86-avx512: vpsllq ymm0, ymm0, 63 - // x86-avx512-NEXT: vpmovq2m k1, ymm0 + // x86-avx512-NOT: vpsllq + // x86-avx512: vpmovq2m k1, ymm0 // x86-avx512-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1 simd_select(mask, a, b) } @@ -122,8 +122,8 @@ pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 { // The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets. // - // x86-avx512: vpsllq zmm0, zmm0, 63 - // x86-avx512-NEXT: vpmovq2m k1, zmm0 + // x86-avx512-NOT: vpsllq + // x86-avx512: vpmovq2m k1, zmm0 // x86-avx512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1 simd_select(mask, a, b) } diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs index acfa868c2df..0ff886653a4 100644 --- a/tests/assembly/targets/targets-elf.rs +++ b/tests/assembly/targets/targets-elf.rs @@ -57,6 +57,12 @@ //@ revisions: aarch64_unknown_nto_qnx710 //@ [aarch64_unknown_nto_qnx710] compile-flags: --target aarch64-unknown-nto-qnx710 //@ [aarch64_unknown_nto_qnx710] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_nto_qnx710_iosock +//@ [aarch64_unknown_nto_qnx710_iosock] compile-flags: --target aarch64-unknown-nto-qnx710_iosock +//@ [aarch64_unknown_nto_qnx710_iosock] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_nto_qnx800 +//@ [aarch64_unknown_nto_qnx800] compile-flags: --target aarch64-unknown-nto-qnx800 +//@ [aarch64_unknown_nto_qnx800] needs-llvm-components: aarch64 //@ revisions: aarch64_unknown_openbsd //@ [aarch64_unknown_openbsd] compile-flags: --target aarch64-unknown-openbsd //@ [aarch64_unknown_openbsd] needs-llvm-components: aarch64 @@ -66,6 +72,9 @@ //@ revisions: aarch64_unknown_teeos //@ [aarch64_unknown_teeos] compile-flags: --target aarch64-unknown-teeos //@ [aarch64_unknown_teeos] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_nuttx +//@ [aarch64_unknown_nuttx] compile-flags: --target aarch64-unknown-nuttx +//@ [aarch64_unknown_nuttx] needs-llvm-components: aarch64 //@ revisions: aarch64_unknown_trusty //@ [aarch64_unknown_trusty] compile-flags: --target aarch64-unknown-trusty //@ [aarch64_unknown_trusty] needs-llvm-components: aarch64 @@ -177,6 +186,12 @@ //@ revisions: armv7a_none_eabihf //@ [armv7a_none_eabihf] compile-flags: --target armv7a-none-eabihf //@ [armv7a_none_eabihf] needs-llvm-components: arm +//@ revisions: armv7a_nuttx_eabi +//@ [armv7a_nuttx_eabi] compile-flags: --target armv7a-nuttx-eabi +//@ [armv7a_nuttx_eabi] needs-llvm-components: arm +//@ revisions: armv7a_nuttx_eabihf +//@ [armv7a_nuttx_eabihf] compile-flags: --target armv7a-nuttx-eabihf +//@ [armv7a_nuttx_eabihf] needs-llvm-components: arm //@ revisions: armv7r_none_eabi //@ [armv7r_none_eabi] compile-flags: --target armv7r-none-eabi //@ [armv7r_none_eabi] needs-llvm-components: arm @@ -555,6 +570,12 @@ //@ revisions: x86_64_pc_nto_qnx710 //@ [x86_64_pc_nto_qnx710] compile-flags: --target x86_64-pc-nto-qnx710 //@ [x86_64_pc_nto_qnx710] needs-llvm-components: x86 +//@ revisions: x86_64_pc_nto_qnx710_iosock +//@ [x86_64_pc_nto_qnx710_iosock] compile-flags: --target x86_64-pc-nto-qnx710_iosock +//@ [x86_64_pc_nto_qnx710_iosock] needs-llvm-components: x86 +//@ revisions: x86_64_pc_nto_qnx800 +//@ [x86_64_pc_nto_qnx800] compile-flags: --target x86_64-pc-nto-qnx800 +//@ [x86_64_pc_nto_qnx800] needs-llvm-components: x86 //@ revisions: x86_64_pc_solaris //@ [x86_64_pc_solaris] compile-flags: --target x86_64-pc-solaris //@ [x86_64_pc_solaris] needs-llvm-components: x86 @@ -621,6 +642,12 @@ //@ revisions: thumbv6m_nuttx_eabi //@ [thumbv6m_nuttx_eabi] compile-flags: --target thumbv6m-nuttx-eabi //@ [thumbv6m_nuttx_eabi] needs-llvm-components: arm +//@ revisions: thumbv7a_nuttx_eabi +//@ [thumbv7a_nuttx_eabi] compile-flags: --target thumbv7a-nuttx-eabi +//@ [thumbv7a_nuttx_eabi] needs-llvm-components: arm +//@ revisions: thumbv7a_nuttx_eabihf +//@ [thumbv7a_nuttx_eabihf] compile-flags: --target thumbv7a-nuttx-eabihf +//@ [thumbv7a_nuttx_eabihf] needs-llvm-components: arm //@ revisions: thumbv7m_nuttx_eabi //@ [thumbv7m_nuttx_eabi] compile-flags: --target thumbv7m-nuttx-eabi //@ [thumbv7m_nuttx_eabi] needs-llvm-components: arm diff --git a/tests/assembly/wasm32-naked-fn.rs b/tests/assembly/wasm32-naked-fn.rs new file mode 100644 index 00000000000..4911a6bd08f --- /dev/null +++ b/tests/assembly/wasm32-naked-fn.rs @@ -0,0 +1,199 @@ +// FIXME: add wasm32-unknown when the wasm32-unknown-unknown ABI is fixed +// see https://github.com/rust-lang/rust/issues/115666 +//@ revisions: wasm64-unknown wasm32-wasip1 +//@ add-core-stubs +//@ assembly-output: emit-asm +//@ [wasm64-unknown] compile-flags: --target wasm64-unknown-unknown +//@ [wasm32-wasip1] compile-flags: --target wasm32-wasip1 +//@ [wasm64-unknown] needs-llvm-components: webassembly +//@ [wasm32-wasip1] needs-llvm-components: webassembly + +#![crate_type = "lib"] +#![feature(no_core, naked_functions, asm_experimental_arch, f128, linkage, fn_align)] +#![no_core] + +extern crate minicore; +use minicore::*; + +// CHECK: .section .text.nop,"",@ +// CHECK: .globl nop +// CHECK-LABEL: nop: +// CHECK: .functype nop () -> () +// CHECK-NOT: .size +// CHECK: end_function +#[no_mangle] +#[naked] +unsafe extern "C" fn nop() { + naked_asm!("nop") +} + +// CHECK: .section .text.weak_aligned_nop,"",@ +// CHECK: .weak weak_aligned_nop +// CHECK-LABEL: nop: +// CHECK: .functype weak_aligned_nop () -> () +// CHECK-NOT: .size +// CHECK: end_function +#[no_mangle] +#[naked] +#[linkage = "weak"] +// wasm functions cannot be aligned, so this has no effect +#[repr(align(32))] +unsafe extern "C" fn weak_aligned_nop() { + naked_asm!("nop") +} + +// CHECK-LABEL: fn_i8_i8: +// CHECK-NEXT: .functype fn_i8_i8 (i32) -> (i32) +// +// CHECK-NEXT: local.get 0 +// CHECK-NEXT: local.get 0 +// CHECK-NEXT: i32.mul +// +// CHECK-NEXT: end_function +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_i8_i8(num: i8) -> i8 { + naked_asm!("local.get 0", "local.get 0", "i32.mul") +} + +// CHECK-LABEL: fn_i8_i8_i8: +// CHECK: .functype fn_i8_i8_i8 (i32, i32) -> (i32) +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_i8_i8_i8(a: i8, b: i8) -> i8 { + naked_asm!("local.get 1", "local.get 0", "i32.mul") +} + +// CHECK-LABEL: fn_unit_i8: +// CHECK: .functype fn_unit_i8 () -> (i32) +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_unit_i8() -> i8 { + naked_asm!("i32.const 42") +} + +// CHECK-LABEL: fn_i8_unit: +// CHECK: .functype fn_i8_unit (i32) -> () +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_i8_unit(_: i8) { + naked_asm!("nop") +} + +// CHECK-LABEL: fn_i32_i32: +// CHECK: .functype fn_i32_i32 (i32) -> (i32) +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_i32_i32(num: i32) -> i32 { + naked_asm!("local.get 0", "local.get 0", "i32.mul") +} + +// CHECK-LABEL: fn_i64_i64: +// CHECK: .functype fn_i64_i64 (i64) -> (i64) +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_i64_i64(num: i64) -> i64 { + naked_asm!("local.get 0", "local.get 0", "i64.mul") +} + +// CHECK-LABEL: fn_i128_i128: +// wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> () +// wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> () +#[allow(improper_ctypes_definitions)] +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_i128_i128(num: i128) -> i128 { + naked_asm!( + "local.get 0", + "local.get 2", + "i64.store 8", + "local.get 0", + "local.get 1", + "i64.store 0", + ) +} + +// CHECK-LABEL: fn_f128_f128: +// wasm32-wasip1: .functype fn_f128_f128 (i32, i64, i64) -> () +// wasm64-unknown: .functype fn_f128_f128 (i64, i64, i64) -> () +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_f128_f128(num: f128) -> f128 { + naked_asm!( + "local.get 0", + "local.get 2", + "i64.store 8", + "local.get 0", + "local.get 1", + "i64.store 0", + ) +} + +#[repr(C)] +struct Compound { + a: u16, + b: i64, +} + +// CHECK-LABEL: fn_compound_compound: +// wasm32-wasip1: .functype fn_compound_compound (i32, i32) -> () +// wasm64-unknown: .functype fn_compound_compound (i64, i64) -> () +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_compound_compound(_: Compound) -> Compound { + // this is the wasm32-wasip1 assembly + naked_asm!( + "local.get 0", + "local.get 1", + "i64.load 8", + "i64.store 8", + "local.get 0", + "local.get 1", + "i32.load16_u 0", + "i32.store16 0", + ) +} + +#[repr(C)] +struct WrapperI32(i32); + +// CHECK-LABEL: fn_wrapperi32_wrapperi32: +// CHECK: .functype fn_wrapperi32_wrapperi32 (i32) -> (i32) +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_wrapperi32_wrapperi32(_: WrapperI32) -> WrapperI32 { + naked_asm!("local.get 0") +} + +#[repr(C)] +struct WrapperI64(i64); + +// CHECK-LABEL: fn_wrapperi64_wrapperi64: +// CHECK: .functype fn_wrapperi64_wrapperi64 (i64) -> (i64) +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_wrapperi64_wrapperi64(_: WrapperI64) -> WrapperI64 { + naked_asm!("local.get 0") +} + +#[repr(C)] +struct WrapperF32(f32); + +// CHECK-LABEL: fn_wrapperf32_wrapperf32: +// CHECK: .functype fn_wrapperf32_wrapperf32 (f32) -> (f32) +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_wrapperf32_wrapperf32(_: WrapperF32) -> WrapperF32 { + naked_asm!("local.get 0") +} + +#[repr(C)] +struct WrapperF64(f64); + +// CHECK-LABEL: fn_wrapperf64_wrapperf64: +// CHECK: .functype fn_wrapperf64_wrapperf64 (f64) -> (f64) +#[no_mangle] +#[naked] +unsafe extern "C" fn fn_wrapperf64_wrapperf64(_: WrapperF64) -> WrapperF64 { + naked_asm!("local.get 0") +} diff --git a/tests/assembly/x86_64-bigint-helpers.rs b/tests/assembly/x86_64-bigint-helpers.rs index 198e5543539..3ad253a2bd0 100644 --- a/tests/assembly/x86_64-bigint-helpers.rs +++ b/tests/assembly/x86_64-bigint-helpers.rs @@ -2,6 +2,9 @@ //@ assembly-output: emit-asm //@ compile-flags: --crate-type=lib -O -C target-cpu=x86-64-v4 //@ compile-flags: -C llvm-args=-x86-asm-syntax=intel +//@ revisions: llvm-pre-20 llvm-20 +//@ [llvm-20] min-llvm-version: 20 +//@ [llvm-pre-20] max-llvm-major-version: 19 #![no_std] #![feature(bigint_helper_methods)] @@ -20,12 +23,16 @@ pub unsafe extern "sysv64" fn bigint_chain_carrying_add( n: usize, mut carry: bool, ) -> bool { - // CHECK: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8] - // CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8] - // CHECK: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]] - // CHECK: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16] - // CHECK: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16] - // CHECK: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]] + // llvm-pre-20: mov [[TEMP:r..]], qword ptr [rsi + 8*[[IND:r..]] + 8] + // llvm-pre-20: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8] + // llvm-pre-20: mov qword ptr [rdi + 8*[[IND]] + 8], [[TEMP]] + // llvm-pre-20: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 16] + // llvm-pre-20: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 16] + // llvm-pre-20: mov qword ptr [rdi + 8*[[IND]] + 16], [[TEMP]] + // llvm-20: adc [[TEMP:r..]], qword ptr [rdx + 8*[[IND:r..]]] + // llvm-20: mov qword ptr [rdi + 8*[[IND]]], [[TEMP]] + // llvm-20: mov [[TEMP]], qword ptr [rsi + 8*[[IND]] + 8] + // llvm-20: adc [[TEMP]], qword ptr [rdx + 8*[[IND]] + 8] for i in 0..n { (*dest.add(i), carry) = u64::carrying_add(*src1.add(i), *src2.add(i), carry); } diff --git a/tests/codegen-units/item-collection/cross-crate-closures.rs b/tests/codegen-units/item-collection/cross-crate-closures.rs index cb86cf18c0c..75a77cc2671 100644 --- a/tests/codegen-units/item-collection/cross-crate-closures.rs +++ b/tests/codegen-units/item-collection/cross-crate-closures.rs @@ -3,14 +3,14 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] -#![feature(start)] +#![no_main] //@ aux-build:cgu_extern_closures.rs extern crate cgu_extern_closures; -//~ MONO_ITEM fn start @@ cross_crate_closures-cgu.0[Internal] -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +//~ MONO_ITEM fn main @@ cross_crate_closures-cgu.0[External] +#[no_mangle] +extern "C" fn main(_: core::ffi::c_int, _: *const *const u8) -> core::ffi::c_int { //~ MONO_ITEM fn cgu_extern_closures::inlined_fn @@ cross_crate_closures-cgu.0[Internal] //~ MONO_ITEM fn cgu_extern_closures::inlined_fn::{closure#0} @@ cross_crate_closures-cgu.0[Internal] let _ = cgu_extern_closures::inlined_fn(1, 2); diff --git a/tests/codegen-units/item-collection/cross-crate-generic-functions.rs b/tests/codegen-units/item-collection/cross-crate-generic-functions.rs index d36f7067b32..4382bfdf8d8 100644 --- a/tests/codegen-units/item-collection/cross-crate-generic-functions.rs +++ b/tests/codegen-units/item-collection/cross-crate-generic-functions.rs @@ -1,14 +1,14 @@ //@ compile-flags:-Zprint-mono-items=eager #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] //@ aux-build:cgu_generic_function.rs extern crate cgu_generic_function; //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn cgu_generic_function::bar::<u32> //~ MONO_ITEM fn cgu_generic_function::foo::<u32> let _ = cgu_generic_function::foo(1u32); diff --git a/tests/codegen-units/item-collection/cross-crate-trait-method.rs b/tests/codegen-units/item-collection/cross-crate-trait-method.rs index 99777760315..917354166f5 100644 --- a/tests/codegen-units/item-collection/cross-crate-trait-method.rs +++ b/tests/codegen-units/item-collection/cross-crate-trait-method.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no -Copt-level=0 #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] //@ aux-build:cgu_export_trait_method.rs extern crate cgu_export_trait_method; @@ -9,8 +9,8 @@ extern crate cgu_export_trait_method; use cgu_export_trait_method::Trait; //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { // The object code of these methods is contained in the external crate, so // calling them should *not* introduce codegen items in the current crate. let _: (u32, u32) = Trait::without_default_impl(0); diff --git a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs index d87ad41e70d..e1887b93b93 100644 --- a/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/tests/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zinline-in-all-cgus //@ compile-flags:-Zinline-mir=no -#![feature(start)] +#![crate_type = "lib"] //~ MONO_ITEM fn std::ptr::drop_in_place::<StructWithDtor> - shim(Some(StructWithDtor)) @@ drop_in_place_intrinsic-cgu.0[Internal] struct StructWithDtor(u32); @@ -14,8 +14,8 @@ impl Drop for StructWithDtor { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn std::ptr::drop_in_place::<[StructWithDtor; 2]> - shim(Some([StructWithDtor; 2])) @@ drop_in_place_intrinsic-cgu.0[Internal] let x = [StructWithDtor(0), StructWithDtor(1)]; diff --git a/tests/codegen-units/item-collection/function-as-argument.rs b/tests/codegen-units/item-collection/function-as-argument.rs index 4be713dc367..146a53bb911 100644 --- a/tests/codegen-units/item-collection/function-as-argument.rs +++ b/tests/codegen-units/item-collection/function-as-argument.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] fn take_fn_once<T1, T2, F: FnOnce(T1, T2)>(f: F, x: T1, y: T2) { (f)(x, y) @@ -14,8 +14,8 @@ fn take_fn_pointer<T1, T2>(f: fn(T1, T2), x: T1, y: T2) { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn take_fn_once::<u32, &str, fn(u32, &str) {function::<u32, &str>}> //~ MONO_ITEM fn function::<u32, &str> //~ MONO_ITEM fn <fn(u32, &str) {function::<u32, &str>} as std::ops::FnOnce<(u32, &str)>>::call_once - shim(fn(u32, &str) {function::<u32, &str>}) diff --git a/tests/codegen-units/item-collection/generic-drop-glue.rs b/tests/codegen-units/item-collection/generic-drop-glue.rs index d861d269fae..6ecf98a032f 100644 --- a/tests/codegen-units/item-collection/generic-drop-glue.rs +++ b/tests/codegen-units/item-collection/generic-drop-glue.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] struct StructWithDrop<T1, T2> { x: T1, @@ -44,8 +44,8 @@ impl Drop for NonGenericWithDrop { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn std::ptr::drop_in_place::<StructWithDrop<i8, char>> - shim(Some(StructWithDrop<i8, char>)) @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn <StructWithDrop<i8, char> as std::ops::Drop>::drop let _ = StructWithDrop { x: 0i8, y: 'a' }.x; diff --git a/tests/codegen-units/item-collection/generic-functions.rs b/tests/codegen-units/item-collection/generic-functions.rs index 2d7c70c9c4c..4a890790702 100644 --- a/tests/codegen-units/item-collection/generic-functions.rs +++ b/tests/codegen-units/item-collection/generic-functions.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] fn foo1<T1>(a: T1) -> (T1, u32) { (a, 1) @@ -22,8 +22,8 @@ pub fn lifetime_only<'a>(a: &'a u32) -> &'a u32 { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn foo1::<i32> let _ = foo1(2i32); //~ MONO_ITEM fn foo1::<i64> diff --git a/tests/codegen-units/item-collection/generic-impl.rs b/tests/codegen-units/item-collection/generic-impl.rs index f6e49f6e6df..5a43bd64b2a 100644 --- a/tests/codegen-units/item-collection/generic-impl.rs +++ b/tests/codegen-units/item-collection/generic-impl.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] struct Struct<T> { x: T, @@ -38,8 +38,8 @@ impl<'a> LifeTimeOnly<'a> { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn Struct::<i32>::new //~ MONO_ITEM fn id::<i32> //~ MONO_ITEM fn Struct::<i32>::get::<i16> diff --git a/tests/codegen-units/item-collection/impl-in-non-instantiated-generic.rs b/tests/codegen-units/item-collection/impl-in-non-instantiated-generic.rs index 0b7f30187b5..d916fa6a825 100644 --- a/tests/codegen-units/item-collection/impl-in-non-instantiated-generic.rs +++ b/tests/codegen-units/item-collection/impl-in-non-instantiated-generic.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] trait SomeTrait { fn foo(&self); @@ -19,8 +19,8 @@ pub fn generic_function<T>(x: T) -> (T, i32) { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { 0i64.foo(); 0 diff --git a/tests/codegen-units/item-collection/instantiation-through-vtable.rs b/tests/codegen-units/item-collection/instantiation-through-vtable.rs index 59dd4311a03..9087fc6410a 100644 --- a/tests/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/tests/codegen-units/item-collection/instantiation-through-vtable.rs @@ -2,7 +2,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-in-all-cgus -Zmir-opt-level=0 #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] trait Trait { fn foo(&self) -> u32; @@ -21,8 +21,8 @@ impl<T> Trait for Struct<T> { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { let s1 = Struct { _a: 0u32 }; //~ MONO_ITEM fn std::ptr::drop_in_place::<Struct<u32>> - shim(None) @@ instantiation_through_vtable-cgu.0[Internal] diff --git a/tests/codegen-units/item-collection/items-within-generic-items.rs b/tests/codegen-units/item-collection/items-within-generic-items.rs index 7798d2b46d2..56d21d5895c 100644 --- a/tests/codegen-units/item-collection/items-within-generic-items.rs +++ b/tests/codegen-units/item-collection/items-within-generic-items.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Copt-level=0 #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] fn generic_fn<T>(a: T) -> (T, i32) { //~ MONO_ITEM fn generic_fn::nested_fn @@ -22,8 +22,8 @@ fn generic_fn<T>(a: T) -> (T, i32) { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn generic_fn::<i64> let _ = generic_fn(0i64); //~ MONO_ITEM fn generic_fn::<u16> diff --git a/tests/codegen-units/item-collection/non-generic-closures.rs b/tests/codegen-units/item-collection/non-generic-closures.rs index 8847a249b1e..4dbc0b62b97 100644 --- a/tests/codegen-units/item-collection/non-generic-closures.rs +++ b/tests/codegen-units/item-collection/non-generic-closures.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] //~ MONO_ITEM fn temporary @@ non_generic_closures-cgu.0[Internal] fn temporary() { @@ -40,9 +40,9 @@ fn assigned_to_variable_executed_directly() { f(4); } -//~ MONO_ITEM fn start @@ non_generic_closures-cgu.0[Internal] -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +//~ MONO_ITEM fn start @@ non_generic_closures-cgu.0[External] +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { temporary(); assigned_to_variable_but_not_executed(); assigned_to_variable_executed_directly(); diff --git a/tests/codegen-units/item-collection/non-generic-drop-glue.rs b/tests/codegen-units/item-collection/non-generic-drop-glue.rs index f7bb2f3f2f4..c4d7942ba1e 100644 --- a/tests/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/tests/codegen-units/item-collection/non-generic-drop-glue.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] //~ MONO_ITEM fn std::ptr::drop_in_place::<StructWithDrop> - shim(Some(StructWithDrop)) @@ non_generic_drop_glue-cgu.0[Internal] struct StructWithDrop { @@ -34,8 +34,8 @@ enum EnumNoDrop { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { let _ = StructWithDrop { x: 0 }.x; let _ = StructNoDrop { x: 0 }.x; let _ = match EnumWithDrop::A(0) { diff --git a/tests/codegen-units/item-collection/non-generic-functions.rs b/tests/codegen-units/item-collection/non-generic-functions.rs index d4d7d221827..4b86b1088f1 100644 --- a/tests/codegen-units/item-collection/non-generic-functions.rs +++ b/tests/codegen-units/item-collection/non-generic-functions.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] //~ MONO_ITEM fn foo fn foo() { @@ -62,8 +62,8 @@ impl Struct { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { foo(); bar(); Struct::foo(); diff --git a/tests/codegen-units/item-collection/static-init.rs b/tests/codegen-units/item-collection/static-init.rs index 44b80ef73a4..5e3d06790a2 100644 --- a/tests/codegen-units/item-collection/static-init.rs +++ b/tests/codegen-units/item-collection/static-init.rs @@ -1,16 +1,16 @@ //@ compile-flags:-Zprint-mono-items=eager -#![feature(start)] +#![crate_type = "lib"] -pub static FN: fn() = foo::<i32>; +static FN: fn() = foo::<i32>; -pub fn foo<T>() {} +fn foo<T>() {} //~ MONO_ITEM fn foo::<i32> //~ MONO_ITEM static FN //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { 0 } diff --git a/tests/codegen-units/item-collection/statics-and-consts.rs b/tests/codegen-units/item-collection/statics-and-consts.rs index 1e3782f0c6e..54297a40851 100644 --- a/tests/codegen-units/item-collection/statics-and-consts.rs +++ b/tests/codegen-units/item-collection/statics-and-consts.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] static STATIC1: i64 = { const STATIC1_CONST1: i64 = 2; @@ -38,8 +38,8 @@ fn foo() { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { foo(); let _ = STATIC1; diff --git a/tests/codegen-units/item-collection/trait-implementations.rs b/tests/codegen-units/item-collection/trait-implementations.rs index e4c444499e0..3b67d4f22bd 100644 --- a/tests/codegen-units/item-collection/trait-implementations.rs +++ b/tests/codegen-units/item-collection/trait-implementations.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] pub trait SomeTrait { fn foo(&self); @@ -42,8 +42,8 @@ impl<T> SomeGenericTrait<T> for f32 { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn <i32 as SomeTrait>::bar::<char> 0i32.bar('x'); diff --git a/tests/codegen-units/item-collection/trait-method-as-argument.rs b/tests/codegen-units/item-collection/trait-method-as-argument.rs index 10cf2a0e967..d425ea19988 100644 --- a/tests/codegen-units/item-collection/trait-method-as-argument.rs +++ b/tests/codegen-units/item-collection/trait-method-as-argument.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] trait Trait: Sized { fn foo(self) -> Self { @@ -30,8 +30,8 @@ fn take_foo_mut<T, F: FnMut(T) -> T>(mut f: F, arg: T) -> T { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn take_foo_once::<u32, fn(u32) -> u32 {<u32 as Trait>::foo}> //~ MONO_ITEM fn <u32 as Trait>::foo //~ MONO_ITEM fn <fn(u32) -> u32 {<u32 as Trait>::foo} as std::ops::FnOnce<(u32,)>>::call_once - shim(fn(u32) -> u32 {<u32 as Trait>::foo}) diff --git a/tests/codegen-units/item-collection/trait-method-default-impl.rs b/tests/codegen-units/item-collection/trait-method-default-impl.rs index fd73786a402..cd0a4b89031 100644 --- a/tests/codegen-units/item-collection/trait-method-default-impl.rs +++ b/tests/codegen-units/item-collection/trait-method-default-impl.rs @@ -1,7 +1,7 @@ //@ compile-flags:-Zprint-mono-items=eager -Zinline-mir=no #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] trait SomeTrait { fn foo(&self) {} @@ -39,8 +39,8 @@ impl<T1> SomeGenericTrait<T1> for u32 { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn <i8 as SomeTrait>::bar::<char> let _ = 1i8.bar('c'); diff --git a/tests/codegen-units/item-collection/transitive-drop-glue.rs b/tests/codegen-units/item-collection/transitive-drop-glue.rs index 7c879dee1a1..18954fab86f 100644 --- a/tests/codegen-units/item-collection/transitive-drop-glue.rs +++ b/tests/codegen-units/item-collection/transitive-drop-glue.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] //~ MONO_ITEM fn std::ptr::drop_in_place::<Root> - shim(Some(Root)) @@ transitive_drop_glue-cgu.0[Internal] struct Root(#[allow(dead_code)] Intermediate); @@ -26,8 +26,8 @@ impl<T> Drop for LeafGen<T> { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { let _ = Root(Intermediate(Leaf)); //~ MONO_ITEM fn std::ptr::drop_in_place::<RootGen<u32>> - shim(Some(RootGen<u32>)) @@ transitive_drop_glue-cgu.0[Internal] diff --git a/tests/codegen-units/item-collection/tuple-drop-glue.rs b/tests/codegen-units/item-collection/tuple-drop-glue.rs index 9d8b0cdd384..2e70d0151eb 100644 --- a/tests/codegen-units/item-collection/tuple-drop-glue.rs +++ b/tests/codegen-units/item-collection/tuple-drop-glue.rs @@ -3,7 +3,7 @@ //@ compile-flags:-Zinline-in-all-cgus #![deny(dead_code)] -#![feature(start)] +#![crate_type = "lib"] //~ MONO_ITEM fn std::ptr::drop_in_place::<Dropped> - shim(Some(Dropped)) @@ tuple_drop_glue-cgu.0[Internal] struct Dropped; @@ -14,8 +14,8 @@ impl Drop for Dropped { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { //~ MONO_ITEM fn std::ptr::drop_in_place::<(u32, Dropped)> - shim(Some((u32, Dropped))) @@ tuple_drop_glue-cgu.0[Internal] let x = (0u32, Dropped); diff --git a/tests/codegen-units/item-collection/unsizing.rs b/tests/codegen-units/item-collection/unsizing.rs index 5ea8b47962a..23e6003dc19 100644 --- a/tests/codegen-units/item-collection/unsizing.rs +++ b/tests/codegen-units/item-collection/unsizing.rs @@ -5,7 +5,7 @@ #![deny(dead_code)] #![feature(coerce_unsized)] #![feature(unsize)] -#![feature(start)] +#![crate_type = "lib"] use std::marker::Unsize; use std::ops::CoerceUnsized; @@ -45,8 +45,8 @@ struct Wrapper<T: ?Sized>(#[allow(dead_code)] *const T); impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> {} //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { // simple case let bool_sized = &true; //~ MONO_ITEM fn std::ptr::drop_in_place::<bool> - shim(None) @@ unsizing-cgu.0[Internal] diff --git a/tests/codegen-units/partitioning/methods-are-with-self-type.rs b/tests/codegen-units/partitioning/methods-are-with-self-type.rs index 7c9045e8f1a..94d06829c6c 100644 --- a/tests/codegen-units/partitioning/methods-are-with-self-type.rs +++ b/tests/codegen-units/partitioning/methods-are-with-self-type.rs @@ -46,6 +46,7 @@ mod type2 { } //~ MONO_ITEM fn start @@ methods_are_with_self_type[External] +#[no_mangle] pub fn start() { //~ MONO_ITEM fn mod1::<impl SomeGenericType<u32, u64>>::method @@ methods_are_with_self_type.volatile[External] SomeGenericType(0u32, 0u64).method(); diff --git a/tests/codegen-units/partitioning/vtable-through-const.rs b/tests/codegen-units/partitioning/vtable-through-const.rs index a9186cea9c8..3880bba6f6b 100644 --- a/tests/codegen-units/partitioning/vtable-through-const.rs +++ b/tests/codegen-units/partitioning/vtable-through-const.rs @@ -2,11 +2,13 @@ //@ incremental //@ compile-flags:-Zprint-mono-items=lazy //@ compile-flags:-Zinline-in-all-cgus +// Need to disable optimizations to ensure consistent output across all CI runners. +//@ compile-flags:-Copt-level=0 // This test case makes sure, that references made through constants are // recorded properly in the InliningMap. -#![feature(start)] +#![crate_type = "lib"] mod mod1 { struct NeedsDrop; @@ -51,8 +53,8 @@ mod mod1 { fn do_something_else(&self) {} } - //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait2>::do_something @@ vtable_through_const-mod1.volatile[Internal] - //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait2>::do_something_else @@ vtable_through_const-mod1.volatile[Internal] + //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait2>::do_something @@ vtable_through_const-mod1.volatile[External] + //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait2>::do_something_else @@ vtable_through_const-mod1.volatile[External] impl Trait2 for NeedsDrop {} pub trait Trait2Gen<T> { @@ -76,9 +78,9 @@ mod mod1 { } //~ MONO_ITEM fn start -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn <mod1::NeedsDrop as std::ops::Drop>::drop @@ vtable_through_const-fallback.cgu[Internal] +#[no_mangle] +pub fn start(_: isize, _: *const *const u8) -> isize { + //~ MONO_ITEM fn <mod1::NeedsDrop as std::ops::Drop>::drop @@ vtable_through_const-fallback.cgu[External] //~ MONO_ITEM fn std::ptr::drop_in_place::<mod1::NeedsDrop> - shim(Some(mod1::NeedsDrop)) @@ vtable_through_const-fallback.cgu[External] // Since Trait1::do_something() is instantiated via its default implementation, @@ -95,8 +97,8 @@ fn start(_: isize, _: *const *const u8) -> isize { // Same as above //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait1Gen<u8>>::do_something @@ vtable_through_const-mod1.volatile[External] //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait1Gen<u8>>::do_something_else @@ vtable_through_const-mod1.volatile[External] - //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait2Gen<u8>>::do_something @@ vtable_through_const-mod1.volatile[Internal] - //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait2Gen<u8>>::do_something_else @@ vtable_through_const-mod1.volatile[Internal] + //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait2Gen<u8>>::do_something @@ vtable_through_const-mod1.volatile[External] + //~ MONO_ITEM fn <mod1::NeedsDrop as mod1::Trait2Gen<u8>>::do_something_else @@ vtable_through_const-mod1.volatile[External] mod1::TRAIT1_GEN_REF.do_something(0u8); //~ MONO_ITEM fn mod1::id::<char> @@ vtable_through_const-mod1.volatile[External] diff --git a/tests/codegen/gdb_debug_script_load.rs b/tests/codegen/gdb_debug_script_load.rs index 30d518c0bcb..3e92eba10b1 100644 --- a/tests/codegen/gdb_debug_script_load.rs +++ b/tests/codegen/gdb_debug_script_load.rs @@ -4,14 +4,34 @@ //@ ignore-wasm //@ ignore-emscripten -//@ compile-flags: -g -C no-prepopulate-passes +//@ compile-flags: -g -C no-prepopulate-passes -Cpanic=abort -#![feature(start)] +#![feature(lang_items)] +#![no_std] +#[panic_handler] +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn rust_eh_personality() { + loop {} +} + +// Needs rustc to generate `main` as that's where the magic load is inserted. +// IOW, we cannot write this test with `#![no_main]`. // CHECK-LABEL: @main // CHECK: load volatile i8, {{.+}} @__rustc_debug_gdb_scripts_section__ -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[lang = "start"] +fn lang_start<T: 'static>( + _main: fn() -> T, + _argc: isize, + _argv: *const *const u8, + _sigpipe: u8, +) -> isize { return 0; } + +fn main() {} diff --git a/tests/codegen/hint/cold_path.rs b/tests/codegen/hint/cold_path.rs new file mode 100644 index 00000000000..dac72073f85 --- /dev/null +++ b/tests/codegen/hint/cold_path.rs @@ -0,0 +1,54 @@ +//@ compile-flags: -O +#![crate_type = "lib"] +#![feature(cold_path)] + +use std::hint::cold_path; + +#[inline(never)] +#[no_mangle] +pub fn path_a() { + println!("path a"); +} + +#[inline(never)] +#[no_mangle] +pub fn path_b() { + println!("path b"); +} + +#[no_mangle] +pub fn test1(x: bool) { + if x { + path_a(); + } else { + cold_path(); + path_b(); + } + + // CHECK-LABEL: @test1( + // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM:[0-9]+]] + // CHECK: bb2: + // CHECK: path_b + // CHECK: bb1: + // CHECK: path_a +} + +#[no_mangle] +pub fn test2(x: i32) { + match x > 0 { + true => path_a(), + false => { + cold_path(); + path_b() + } + } + + // CHECK-LABEL: @test2( + // CHECK: br i1 %_2, label %bb2, label %bb1, !prof ![[NUM]] + // CHECK: bb1: + // CHECK: path_b + // CHECK: bb2: + // CHECK: path_a +} + +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} diff --git a/tests/codegen/hint/likely.rs b/tests/codegen/hint/likely.rs new file mode 100644 index 00000000000..2f589cc99d2 --- /dev/null +++ b/tests/codegen/hint/likely.rs @@ -0,0 +1,81 @@ +//@ compile-flags: -O +#![crate_type = "lib"] +#![feature(likely_unlikely)] + +use std::hint::likely; + +#[inline(never)] +#[no_mangle] +pub fn path_a() { + println!("path a"); +} + +#[inline(never)] +#[no_mangle] +pub fn path_b() { + println!("path b"); +} + +#[no_mangle] +pub fn test1(x: bool) { + if likely(x) { + path_a(); + } else { + path_b(); + } + + // CHECK-LABEL: @test1( + // CHECK: br i1 %x, label %bb2, label %bb3, !prof ![[NUM:[0-9]+]] + // CHECK: bb3: + // CHECK: path_b + // CHECK: bb2: + // CHECK: path_a +} + +#[no_mangle] +pub fn test2(x: i32) { + match likely(x > 0) { + true => path_a(), + false => path_b(), + } + + // CHECK-LABEL: @test2( + // CHECK: br i1 %_2, label %bb2, label %bb3, !prof ![[NUM]] + // CHECK: bb3: + // CHECK: path_b + // CHECK: bb2: + // CHECK: path_a +} + +#[no_mangle] +pub fn test3(x: i8) { + match likely(x < 7) { + true => path_a(), + _ => path_b(), + } + + // CHECK-LABEL: @test3( + // CHECK: br i1 %_2, label %bb2, label %bb3, !prof ![[NUM]] + // CHECK: bb3: + // CHECK: path_b + // CHECK: bb2: + // CHECK: path_a +} + +#[no_mangle] +pub fn test4(x: u64) { + match likely(x != 33) { + false => path_a(), + _ => path_b(), + } + + // CHECK-LABEL: @test4( + // CHECK: br i1 %0, label %bb3, label %bb2, !prof ![[NUM2:[0-9]+]] + // CHECK: bb3: + // CHECK: path_a + // CHECK: bb2: + // CHECK: path_b +} + +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} +// CHECK: ![[NUM2]] = !{!"branch_weights", {{(!"expected", )?}}i32 1, i32 2000} diff --git a/tests/codegen/hint/unlikely.rs b/tests/codegen/hint/unlikely.rs new file mode 100644 index 00000000000..328533f3081 --- /dev/null +++ b/tests/codegen/hint/unlikely.rs @@ -0,0 +1,80 @@ +//@ compile-flags: -O +#![crate_type = "lib"] +#![feature(likely_unlikely)] + +use std::hint::unlikely; + +#[inline(never)] +#[no_mangle] +pub fn path_a() { + println!("path a"); +} + +#[inline(never)] +#[no_mangle] +pub fn path_b() { + println!("path b"); +} + +#[no_mangle] +pub fn test1(x: bool) { + if unlikely(x) { + path_a(); + } else { + path_b(); + } + + // CHECK-LABEL: @test1( + // CHECK: br i1 %x, label %bb2, label %bb4, !prof ![[NUM:[0-9]+]] + // CHECK: bb4: + // CHECK: path_b + // CHECK: bb2: + // CHECK: path_a +} + +#[no_mangle] +pub fn test2(x: i32) { + match unlikely(x > 0) { + true => path_a(), + false => path_b(), + } + + // CHECK-LABEL: @test2( + // CHECK: br i1 %_2, label %bb2, label %bb4, !prof ![[NUM]] + // CHECK: bb4: + // CHECK: path_b + // CHECK: bb2: + // CHECK: path_a +} + +#[no_mangle] +pub fn test3(x: i8) { + match unlikely(x < 7) { + true => path_a(), + _ => path_b(), + } + + // CHECK-LABEL: @test3( + // CHECK: br i1 %_2, label %bb2, label %bb4, !prof ![[NUM]] + // CHECK: bb4: + // CHECK: path_b + // CHECK: bb2: + // CHECK: path_a +} + +#[no_mangle] +pub fn test4(x: u64) { + match unlikely(x != 33) { + false => path_a(), + _ => path_b(), + } + + // CHECK-LABEL: @test4( + // CHECK: br i1 %0, label %bb4, label %bb2, !prof ![[NUM2:[0-9]+]] + // CHECK: bb4: + // CHECK: path_a + // CHECK: bb2: + // CHECK: path_b +} + +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 1, i32 2000} diff --git a/tests/codegen/i128-x86-callconv.rs b/tests/codegen/i128-x86-callconv.rs new file mode 100644 index 00000000000..9a9c9002fc0 --- /dev/null +++ b/tests/codegen/i128-x86-callconv.rs @@ -0,0 +1,79 @@ +//! Verify that Rust implements the expected calling convention for `i128`/`u128`. + +// Eliminate intermediate instructions during `nop` tests +//@ compile-flags: -Copt-level=1 + +//@ add-core-stubs +//@ revisions: MSVC MINGW +//@ [MSVC] needs-llvm-components: x86 +//@ [MINGW] needs-llvm-components: x86 +//@ [MSVC] compile-flags: --target x86_64-pc-windows-msvc +//@ [MINGW] compile-flags: --target x86_64-pc-windows-gnu +//@ [MSVC] filecheck-flags: --check-prefix=WIN +//@ [MINGW] filecheck-flags: --check-prefix=WIN + +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![feature(no_core, lang_items)] + +extern crate minicore; + +extern "C" { + fn extern_call(arg0: i128); + fn extern_ret() -> i128; +} + +#[no_mangle] +pub extern "C" fn pass(_arg0: u32, arg1: i128) { + // CHECK-LABEL: @pass( + // i128 is passed indirectly on Windows. It should load the pointer to the stack and pass + // a pointer to that allocation. + // WIN-SAME: %_arg0, ptr{{.*}} %arg1) + // WIN: [[PASS:%[_0-9]+]] = alloca [16 x i8], align 16 + // WIN: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1 + // WIN: store i128 [[LOADED]], ptr [[PASS]] + // WIN: call void @extern_call + unsafe { extern_call(arg1) }; +} + +// Check that we produce the correct return ABI +#[no_mangle] +pub extern "C" fn ret(_arg0: u32, arg1: i128) -> i128 { + // CHECK-LABEL: @ret( + // i128 is returned in xmm0 on Windows + // FIXME(#134288): This may change for the `-msvc` targets in the future. + // WIN-SAME: i32{{.*}} %_arg0, ptr{{.*}} %arg1) + // WIN: [[LOADED:%[_0-9]+]] = load <16 x i8>, ptr %arg1 + // WIN-NEXT: ret <16 x i8> [[LOADED]] + arg1 +} + +// Check that we consume the correct return ABI +#[no_mangle] +pub extern "C" fn forward(dst: *mut i128) { + // CHECK-LABEL: @forward + // WIN-SAME: ptr{{.*}} %dst) + // WIN: [[RETURNED:%[_0-9]+]] = tail call <16 x i8> @extern_ret() + // WIN: store <16 x i8> [[RETURNED]], ptr %dst + // WIN: ret void + unsafe { *dst = extern_ret() }; +} + +#[repr(C)] +struct RetAggregate { + a: i32, + b: i128, +} + +#[no_mangle] +pub extern "C" fn ret_aggregate(_arg0: u32, arg1: i128) -> RetAggregate { + // CHECK-LABEL: @ret_aggregate( + // Aggregates should also be returned indirectly + // WIN-SAME: ptr{{.*}}sret([32 x i8]){{.*}}[[RET:%[_0-9]+]], i32{{.*}}%_arg0, ptr{{.*}}%arg1) + // WIN: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1 + // WIN: [[GEP:%[_0-9]+]] = getelementptr{{.*}}, ptr [[RET]] + // WIN: store i128 [[LOADED]], ptr [[GEP]] + // WIN: ret void + RetAggregate { a: 1, b: arg1 } +} diff --git a/tests/codegen/intrinsics/transmute-niched.rs b/tests/codegen/intrinsics/transmute-niched.rs index f5b7bd2efea..88119ccb8b2 100644 --- a/tests/codegen/intrinsics/transmute-niched.rs +++ b/tests/codegen/intrinsics/transmute-niched.rs @@ -17,12 +17,13 @@ pub enum SmallEnum { // CHECK-LABEL: @check_to_enum( #[no_mangle] pub unsafe fn check_to_enum(x: i8) -> SmallEnum { - // OPT: %0 = icmp uge i8 %x, 10 - // OPT: call void @llvm.assume(i1 %0) - // OPT: %1 = icmp ule i8 %x, 12 + // CHECK-NOT: icmp + // CHECK-NOT: assume + // OPT: %0 = sub i8 %x, 10 + // OPT: %1 = icmp ule i8 %0, 2 // OPT: call void @llvm.assume(i1 %1) - // DBG-NOT: icmp - // DBG-NOT: assume + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: ret i8 %x transmute(x) @@ -31,12 +32,13 @@ pub unsafe fn check_to_enum(x: i8) -> SmallEnum { // CHECK-LABEL: @check_from_enum( #[no_mangle] pub unsafe fn check_from_enum(x: SmallEnum) -> i8 { - // OPT: %0 = icmp uge i8 %x, 10 - // OPT: call void @llvm.assume(i1 %0) - // OPT: %1 = icmp ule i8 %x, 12 + // CHECK-NOT: icmp + // CHECK-NOT: assume + // OPT: %0 = sub i8 %x, 10 + // OPT: %1 = icmp ule i8 %0, 2 // OPT: call void @llvm.assume(i1 %1) - // DBG-NOT: icmp - // DBG-NOT: assume + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: ret i8 %x transmute(x) @@ -45,12 +47,13 @@ pub unsafe fn check_from_enum(x: SmallEnum) -> i8 { // CHECK-LABEL: @check_to_ordering( #[no_mangle] pub unsafe fn check_to_ordering(x: u8) -> std::cmp::Ordering { - // OPT: %0 = icmp uge i8 %x, -1 - // OPT: %1 = icmp ule i8 %x, 1 - // OPT: %2 = or i1 %0, %1 - // OPT: call void @llvm.assume(i1 %2) - // DBG-NOT: icmp - // DBG-NOT: assume + // CHECK-NOT: icmp + // CHECK-NOT: assume + // OPT: %0 = sub i8 %x, -1 + // OPT: %1 = icmp ule i8 %0, 2 + // OPT: call void @llvm.assume(i1 %1) + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: ret i8 %x transmute(x) @@ -59,12 +62,13 @@ pub unsafe fn check_to_ordering(x: u8) -> std::cmp::Ordering { // CHECK-LABEL: @check_from_ordering( #[no_mangle] pub unsafe fn check_from_ordering(x: std::cmp::Ordering) -> u8 { - // OPT: %0 = icmp uge i8 %x, -1 - // OPT: %1 = icmp ule i8 %x, 1 - // OPT: %2 = or i1 %0, %1 - // OPT: call void @llvm.assume(i1 %2) - // DBG-NOT: icmp - // DBG-NOT: assume + // CHECK-NOT: icmp + // CHECK-NOT: assume + // OPT: %0 = sub i8 %x, -1 + // OPT: %1 = icmp ule i8 %0, 2 + // OPT: call void @llvm.assume(i1 %1) + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: ret i8 %x transmute(x) @@ -98,14 +102,15 @@ pub enum Minus100ToPlus100 { // CHECK-LABEL: @check_enum_from_char( #[no_mangle] pub unsafe fn check_enum_from_char(x: char) -> Minus100ToPlus100 { + // CHECK-NOT: icmp + // CHECK-NOT: assume // OPT: %0 = icmp ule i32 %x, 1114111 // OPT: call void @llvm.assume(i1 %0) - // OPT: %1 = icmp uge i32 %x, -100 - // OPT: %2 = icmp ule i32 %x, 100 - // OPT: %3 = or i1 %1, %2 - // OPT: call void @llvm.assume(i1 %3) - // DBG-NOT: icmp - // DBG-NOT: assume + // OPT: %1 = sub i32 %x, -100 + // OPT: %2 = icmp ule i32 %1, 200 + // OPT: call void @llvm.assume(i1 %2) + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: ret i32 %x transmute(x) @@ -114,14 +119,15 @@ pub unsafe fn check_enum_from_char(x: char) -> Minus100ToPlus100 { // CHECK-LABEL: @check_enum_to_char( #[no_mangle] pub unsafe fn check_enum_to_char(x: Minus100ToPlus100) -> char { - // OPT: %0 = icmp uge i32 %x, -100 - // OPT: %1 = icmp ule i32 %x, 100 - // OPT: %2 = or i1 %0, %1 + // CHECK-NOT: icmp + // CHECK-NOT: assume + // OPT: %0 = sub i32 %x, -100 + // OPT: %1 = icmp ule i32 %0, 200 + // OPT: call void @llvm.assume(i1 %1) + // OPT: %2 = icmp ule i32 %x, 1114111 // OPT: call void @llvm.assume(i1 %2) - // OPT: %3 = icmp ule i32 %x, 1114111 - // OPT: call void @llvm.assume(i1 %3) - // DBG-NOT: icmp - // DBG-NOT: assume + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: ret i32 %x transmute(x) @@ -130,16 +136,20 @@ pub unsafe fn check_enum_to_char(x: Minus100ToPlus100) -> char { // CHECK-LABEL: @check_swap_pair( #[no_mangle] pub unsafe fn check_swap_pair(x: (char, NonZero<u32>)) -> (NonZero<u32>, char) { + // CHECK-NOT: icmp + // CHECK-NOT: assume // OPT: %0 = icmp ule i32 %x.0, 1114111 // OPT: call void @llvm.assume(i1 %0) - // OPT: %1 = icmp uge i32 %x.0, 1 - // OPT: call void @llvm.assume(i1 %1) - // OPT: %2 = icmp uge i32 %x.1, 1 + // OPT: %1 = sub i32 %x.0, 1 + // OPT: %2 = icmp ule i32 %1, -2 // OPT: call void @llvm.assume(i1 %2) - // OPT: %3 = icmp ule i32 %x.1, 1114111 - // OPT: call void @llvm.assume(i1 %3) - // DBG-NOT: icmp - // DBG-NOT: assume + // OPT: %3 = sub i32 %x.1, 1 + // OPT: %4 = icmp ule i32 %3, -2 + // OPT: call void @llvm.assume(i1 %4) + // OPT: %5 = icmp ule i32 %x.1, 1114111 + // OPT: call void @llvm.assume(i1 %5) + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: %[[P1:.+]] = insertvalue { i32, i32 } poison, i32 %x.0, 0 // CHECK: %[[P2:.+]] = insertvalue { i32, i32 } %[[P1]], i32 %x.1, 1 // CHECK: ret { i32, i32 } %[[P2]] @@ -150,14 +160,15 @@ pub unsafe fn check_swap_pair(x: (char, NonZero<u32>)) -> (NonZero<u32>, char) { // CHECK-LABEL: @check_bool_from_ordering( #[no_mangle] pub unsafe fn check_bool_from_ordering(x: std::cmp::Ordering) -> bool { - // OPT: %0 = icmp uge i8 %x, -1 - // OPT: %1 = icmp ule i8 %x, 1 - // OPT: %2 = or i1 %0, %1 + // CHECK-NOT: icmp + // CHECK-NOT: assume + // OPT: %0 = sub i8 %x, -1 + // OPT: %1 = icmp ule i8 %0, 2 + // OPT: call void @llvm.assume(i1 %1) + // OPT: %2 = icmp ule i8 %x, 1 // OPT: call void @llvm.assume(i1 %2) - // OPT: %3 = icmp ule i8 %x, 1 - // OPT: call void @llvm.assume(i1 %3) - // DBG-NOT: icmp - // DBG-NOT: assume + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: %[[R:.+]] = trunc i8 %x to i1 // CHECK: ret i1 %[[R]] @@ -168,14 +179,15 @@ pub unsafe fn check_bool_from_ordering(x: std::cmp::Ordering) -> bool { #[no_mangle] pub unsafe fn check_bool_to_ordering(x: bool) -> std::cmp::Ordering { // CHECK: %_0 = zext i1 %x to i8 + // CHECK-NOT: icmp + // CHECK-NOT: assume // OPT: %0 = icmp ule i8 %_0, 1 // OPT: call void @llvm.assume(i1 %0) - // OPT: %1 = icmp uge i8 %_0, -1 - // OPT: %2 = icmp ule i8 %_0, 1 - // OPT: %3 = or i1 %1, %2 - // OPT: call void @llvm.assume(i1 %3) - // DBG-NOT: icmp - // DBG-NOT: assume + // OPT: %1 = sub i8 %_0, -1 + // OPT: %2 = icmp ule i8 %1, 2 + // OPT: call void @llvm.assume(i1 %2) + // CHECK-NOT: icmp + // CHECK-NOT: assume // CHECK: ret i8 %_0 transmute(x) diff --git a/tests/codegen/mainsubprogramstart.rs b/tests/codegen/mainsubprogramstart.rs deleted file mode 100644 index 0bcb311644d..00000000000 --- a/tests/codegen/mainsubprogramstart.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ ignore-apple -//@ ignore-wasi wasi codegens the main symbol differently - -//@ compile-flags: -g -C no-prepopulate-passes - -#![feature(start)] - -// CHECK-LABEL: @main -// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DI{{(SP)?}}FlagMainSubprogram{{.*}} - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { - return 0; -} diff --git a/tests/codegen/optimize-attr-1.rs b/tests/codegen/optimize-attr-1.rs index 3aee44791e0..db6bdcf9a8b 100644 --- a/tests/codegen/optimize-attr-1.rs +++ b/tests/codegen/optimize-attr-1.rs @@ -37,11 +37,23 @@ pub fn speed() -> i32 { 4 + 4 } +// CHECK-LABEL: define{{.*}}i32 @none +// CHECK-SAME: [[NONE_ATTRS:#[0-9]+]] +// SIZE-OPT: alloca +// SPEED-OPT: alloca +#[no_mangle] +#[optimize(none)] +pub fn none() -> i32 { + let arr = [0, 1, 2, 3, 4]; + arr[4] +} + // NO-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}} // SPEED-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}} // SIZE-OPT-DAG: attributes [[NOTHING_ATTRS]] = {{.*}}optsize{{.*}} // SIZE-OPT-DAG: attributes [[SIZE_ATTRS]] = {{.*}}minsize{{.*}}optsize{{.*}} +// CHECK-DAG: attributes [[NONE_ATTRS]] = {{.*}}noinline{{.*}}optnone{{.*}} -// SIZE-OPT: attributes [[SPEED_ATTRS]] +// SIZE-OPT-DAG: attributes [[SPEED_ATTRS]] // SIZE-OPT-NOT: minsize // SIZE-OPT-NOT: optsize diff --git a/tests/codegen/overaligned-constant.rs b/tests/codegen/overaligned-constant.rs index 7cd8d19c211..e5540aca387 100644 --- a/tests/codegen/overaligned-constant.rs +++ b/tests/codegen/overaligned-constant.rs @@ -17,8 +17,6 @@ pub fn overaligned_constant() { // CHECK-LABEL: @overaligned_constant // CHECK: [[full:%_.*]] = alloca [32 x i8], align 8 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[full]], ptr align 8 @0, i64 32, i1 false) - // CHECK: %b.0 = load i32, ptr @0, align 4 - // CHECK: %b.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4 let mut s = S(1); s.0 = 3; diff --git a/tests/codegen/s390x-simd.rs b/tests/codegen/s390x-simd.rs new file mode 100644 index 00000000000..23181e6a103 --- /dev/null +++ b/tests/codegen/s390x-simd.rs @@ -0,0 +1,143 @@ +//! test that s390x vector types are passed using `PassMode::Direct` +//! see also https://github.com/rust-lang/rust/issues/135744 +//@ add-core-stubs +//@ compile-flags: --target s390x-unknown-linux-gnu -O +//@ needs-llvm-components: systemz + +#![crate_type = "rlib"] +#![feature(no_core, asm_experimental_arch)] +#![feature(s390x_target_feature, simd_ffi, link_llvm_intrinsics, repr_simd)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[repr(simd)] +struct i8x16([i8; 16]); + +#[repr(simd)] +struct i16x8([i16; 8]); + +#[repr(simd)] +struct i32x4([i32; 4]); + +#[repr(simd)] +struct i64x2([i64; 2]); + +#[repr(simd)] +struct f32x4([f32; 4]); + +#[repr(simd)] +struct f64x2([f64; 2]); + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.smax.v16i8"] + fn vmxb(a: i8x16, b: i8x16) -> i8x16; + #[link_name = "llvm.smax.v8i16"] + fn vmxh(a: i16x8, b: i16x8) -> i16x8; + #[link_name = "llvm.smax.v4i32"] + fn vmxf(a: i32x4, b: i32x4) -> i32x4; + #[link_name = "llvm.smax.v2i64"] + fn vmxg(a: i64x2, b: i64x2) -> i64x2; +} + +// CHECK-LABEL: define <16 x i8> @max_i8x16 +// CHECK-SAME: <16 x i8> %a, <16 x i8> %b +// CHECK: call <16 x i8> @llvm.smax.v16i8(<16 x i8> %a, <16 x i8> %b) +#[no_mangle] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn max_i8x16(a: i8x16, b: i8x16) -> i8x16 { + vmxb(a, b) +} + +// CHECK-LABEL: define <8 x i16> @max_i16x8 +// CHECK-SAME: <8 x i16> %a, <8 x i16> %b +// CHECK: call <8 x i16> @llvm.smax.v8i16(<8 x i16> %a, <8 x i16> %b) +#[no_mangle] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn max_i16x8(a: i16x8, b: i16x8) -> i16x8 { + vmxh(a, b) +} + +// CHECK-LABEL: define <4 x i32> @max_i32x4 +// CHECK-SAME: <4 x i32> %a, <4 x i32> %b +// CHECK: call <4 x i32> @llvm.smax.v4i32(<4 x i32> %a, <4 x i32> %b) +#[no_mangle] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn max_i32x4(a: i32x4, b: i32x4) -> i32x4 { + vmxf(a, b) +} + +// CHECK-LABEL: define <2 x i64> @max_i64x2 +// CHECK-SAME: <2 x i64> %a, <2 x i64> %b +// CHECK: call <2 x i64> @llvm.smax.v2i64(<2 x i64> %a, <2 x i64> %b) +#[no_mangle] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn max_i64x2(a: i64x2, b: i64x2) -> i64x2 { + vmxg(a, b) +} + +// CHECK-LABEL: define <4 x float> @choose_f32x4 +// CHECK-SAME: <4 x float> %a, <4 x float> %b +#[no_mangle] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn choose_f32x4(a: f32x4, b: f32x4, c: bool) -> f32x4 { + if c { a } else { b } +} + +// CHECK-LABEL: define <2 x double> @choose_f64x2 +// CHECK-SAME: <2 x double> %a, <2 x double> %b +#[no_mangle] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn choose_f64x2(a: f64x2, b: f64x2, c: bool) -> f64x2 { + if c { a } else { b } +} + +#[repr(C)] +struct Wrapper<T>(T); + +#[no_mangle] +#[inline(never)] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn max_wrapper_i8x16(a: Wrapper<i8x16>, b: Wrapper<i8x16>) -> Wrapper<i8x16> { + // CHECK-LABEL: max_wrapper_i8x16 + // CHECK-SAME: sret([16 x i8]) + // CHECK-SAME: <16 x i8> + // CHECK-SAME: <16 x i8> + // CHECK: call <16 x i8> @llvm.smax.v16i8 + // CHECK-SAME: <16 x i8> + // CHECK-SAME: <16 x i8> + Wrapper(vmxb(a.0, b.0)) +} + +#[no_mangle] +#[inline(never)] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn max_wrapper_i64x2(a: Wrapper<i64x2>, b: Wrapper<i64x2>) -> Wrapper<i64x2> { + // CHECK-LABEL: max_wrapper_i64x2 + // CHECK-SAME: sret([16 x i8]) + // CHECK-SAME: <16 x i8> + // CHECK-SAME: <16 x i8> + // CHECK: call <2 x i64> @llvm.smax.v2i64 + // CHECK-SAME: <2 x i64> + // CHECK-SAME: <2 x i64> + Wrapper(vmxg(a.0, b.0)) +} + +#[no_mangle] +#[inline(never)] +#[target_feature(enable = "vector")] +pub unsafe extern "C" fn choose_wrapper_f64x2( + a: Wrapper<f64x2>, + b: Wrapper<f64x2>, + c: bool, +) -> Wrapper<f64x2> { + // CHECK-LABEL: choose_wrapper_f64x2 + // CHECK-SAME: sret([16 x i8]) + // CHECK-SAME: <16 x i8> + // CHECK-SAME: <16 x i8> + Wrapper(choose_f64x2(a.0, b.0, c)) +} + +// CHECK: declare <2 x i64> @llvm.smax.v2i64(<2 x i64>, <2 x i64>) diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs index 10ceeecf900..605a0d520a7 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs @@ -23,7 +23,9 @@ extern "rust-intrinsic" { #[no_mangle] pub unsafe fn gather_f32x2(pointers: Vec2<*const f32>, mask: Vec2<i32>, values: Vec2<f32>) -> Vec2<f32> { - // CHECK: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}}) + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, <i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> + // CHECK: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) simd_gather(values, pointers, mask) } @@ -31,6 +33,8 @@ pub unsafe fn gather_f32x2(pointers: Vec2<*const f32>, mask: Vec2<i32>, #[no_mangle] pub unsafe fn gather_pf32x2(pointers: Vec2<*const *const f32>, mask: Vec2<i32>, values: Vec2<*const f32>) -> Vec2<*const f32> { - // CHECK: call <2 x ptr> @llvm.masked.gather.v2p0.v2p0(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x ptr> {{.*}}) + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, <i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> + // CHECK: call <2 x ptr> @llvm.masked.gather.v2p0.v2p0(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]], <2 x ptr> {{.*}}) simd_gather(values, pointers, mask) } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs index 073dc0ac94d..015f6fd9cef 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs @@ -21,7 +21,9 @@ extern "rust-intrinsic" { #[no_mangle] pub unsafe fn load_f32x2(mask: Vec2<i32>, pointer: *const f32, values: Vec2<f32>) -> Vec2<f32> { - // CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 4, <2 x i1> {{.*}}, <2 x float> {{.*}}) + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, <i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> + // CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 4, <2 x i1> [[B]], <2 x float> {{.*}}) simd_masked_load(mask, pointer, values) } @@ -29,6 +31,8 @@ pub unsafe fn load_f32x2(mask: Vec2<i32>, pointer: *const f32, #[no_mangle] pub unsafe fn load_pf32x4(mask: Vec4<i32>, pointer: *const *const f32, values: Vec4<*const f32>) -> Vec4<*const f32> { - // CHECK: call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr {{.*}}, i32 {{.*}}, <4 x i1> {{.*}}, <4 x ptr> {{.*}}) + // CHECK: [[A:%[0-9]+]] = lshr <4 x i32> {{.*}}, <i32 31, i32 31, i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <4 x i32> [[A]] to <4 x i1> + // CHECK: call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr {{.*}}, i32 {{.*}}, <4 x i1> [[B]], <4 x ptr> {{.*}}) simd_masked_load(mask, pointer, values) } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs index 7c3393e6f2e..471a4bea181 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs @@ -20,13 +20,17 @@ extern "rust-intrinsic" { // CHECK-LABEL: @store_f32x2 #[no_mangle] pub unsafe fn store_f32x2(mask: Vec2<i32>, pointer: *mut f32, values: Vec2<f32>) { - // CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 4, <2 x i1> {{.*}}) + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, <i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> + // CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 4, <2 x i1> [[B]]) simd_masked_store(mask, pointer, values) } // CHECK-LABEL: @store_pf32x4 #[no_mangle] pub unsafe fn store_pf32x4(mask: Vec4<i32>, pointer: *mut *const f32, values: Vec4<*const f32>) { - // CHECK: call void @llvm.masked.store.v4p0.p0(<4 x ptr> {{.*}}, ptr {{.*}}, i32 {{.*}}, <4 x i1> {{.*}}) + // CHECK: [[A:%[0-9]+]] = lshr <4 x i32> {{.*}}, <i32 31, i32 31, i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <4 x i32> [[A]] to <4 x i1> + // CHECK: call void @llvm.masked.store.v4p0.p0(<4 x ptr> {{.*}}, ptr {{.*}}, i32 {{.*}}, <4 x i1> [[B]]) simd_masked_store(mask, pointer, values) } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs index 3c75ef5be40..1c42b2534d8 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs @@ -23,7 +23,9 @@ extern "rust-intrinsic" { #[no_mangle] pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2<i32>, values: Vec2<f32>) { - // CHECK: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}) + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, <i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> + // CHECK: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]] simd_scatter(values, pointers, mask) } @@ -32,6 +34,8 @@ pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2<i32>, #[no_mangle] pub unsafe fn scatter_pf32x2(pointers: Vec2<*mut *const f32>, mask: Vec2<i32>, values: Vec2<*const f32>) { - // CHECK: call void @llvm.masked.scatter.v2p0.v2p0(<2 x ptr> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}) + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, <i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> + // CHECK: call void @llvm.masked.scatter.v2p0.v2p0(<2 x ptr> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]] simd_scatter(values, pointers, mask) } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs index c12fefa413b..a73593160f2 100644 --- a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-select.rs @@ -3,7 +3,7 @@ #![crate_type = "lib"] #![feature(repr_simd, intrinsics)] -#[allow(non_camel_case_types)] +#![allow(non_camel_case_types)] #[repr(simd)] #[derive(Copy, Clone, PartialEq, Debug)] @@ -17,21 +17,37 @@ pub struct f32x8([f32; 8]); #[derive(Copy, Clone, PartialEq, Debug)] pub struct b8x4(pub [i8; 4]); +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct i32x4([i32; 4]); + extern "rust-intrinsic" { fn simd_select<T, U>(x: T, a: U, b: U) -> U; fn simd_select_bitmask<T, U>(x: T, a: U, b: U) -> U; } -// CHECK-LABEL: @select +// CHECK-LABEL: @select_m8 +#[no_mangle] +pub unsafe fn select_m8(m: b8x4, a: f32x4, b: f32x4) -> f32x4 { + // CHECK: [[A:%[0-9]+]] = lshr <4 x i8> %{{.*}}, <i8 7, i8 7, i8 7, i8 7> + // CHECK: [[B:%[0-9]+]] = trunc <4 x i8> [[A]] to <4 x i1> + // CHECK: select <4 x i1> [[B]] + simd_select(m, a, b) +} + +// CHECK-LABEL: @select_m32 #[no_mangle] -pub unsafe fn select(m: b8x4, a: f32x4, b: f32x4) -> f32x4 { - // CHECK: select <4 x i1> +pub unsafe fn select_m32(m: i32x4, a: f32x4, b: f32x4) -> f32x4 { + // CHECK: [[A:%[0-9]+]] = lshr <4 x i32> %{{.*}}, <i32 31, i32 31, i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <4 x i32> [[A]] to <4 x i1> + // CHECK: select <4 x i1> [[B]] simd_select(m, a, b) } // CHECK-LABEL: @select_bitmask #[no_mangle] pub unsafe fn select_bitmask(m: i8, a: f32x8, b: f32x8) -> f32x8 { - // CHECK: select <8 x i1> + // CHECK: [[A:%[0-9]+]] = bitcast i8 {{.*}} to <8 x i1> + // CHECK: select <8 x i1> [[A]] simd_select_bitmask(m, a, b) } diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-mask-reduce.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-mask-reduce.rs new file mode 100644 index 00000000000..4df246c2f5c --- /dev/null +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-mask-reduce.rs @@ -0,0 +1,65 @@ +//@ compile-flags: -C no-prepopulate-passes +// + +#![crate_type = "lib"] +#![feature(repr_simd, intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct mask32x2([i32; 2]); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct mask8x16([i8; 16]); + +extern "rust-intrinsic" { + fn simd_reduce_all<T>(x: T) -> bool; + fn simd_reduce_any<T>(x: T) -> bool; +} + +// NOTE(eddyb) `%{{x|1}}` is used because on some targets (e.g. WASM) +// SIMD vectors are passed directly, resulting in `%x` being a vector, +// while on others they're passed indirectly, resulting in `%x` being +// a pointer to a vector, and `%1` a vector loaded from that pointer. +// This is controlled by the target spec option `simd_types_indirect`. + +// CHECK-LABEL: @reduce_any_32x2 +#[no_mangle] +pub unsafe fn reduce_any_32x2(x: mask32x2) -> bool { + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> + // CHECK: [[C:%[0-9]+]] = call i1 @llvm.vector.reduce.or.v2i1(<2 x i1> [[B]]) + // CHECK: %{{[0-9]+}} = zext i1 [[C]] to i8 + simd_reduce_any(x) +} + +// CHECK-LABEL: @reduce_all_32x2 +#[no_mangle] +pub unsafe fn reduce_all_32x2(x: mask32x2) -> bool { + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{x|1}}, <i32 31, i32 31> + // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> + // CHECK: [[C:%[0-9]+]] = call i1 @llvm.vector.reduce.and.v2i1(<2 x i1> [[B]]) + // CHECK: %{{[0-9]+}} = zext i1 [[C]] to i8 + simd_reduce_all(x) +} + +// CHECK-LABEL: @reduce_any_8x16 +#[no_mangle] +pub unsafe fn reduce_any_8x16(x: mask8x16) -> bool { + // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7> + // CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1> + // CHECK: [[C:%[0-9]+]] = call i1 @llvm.vector.reduce.or.v16i1(<16 x i1> [[B]]) + // CHECK: %{{[0-9]+}} = zext i1 [[C]] to i8 + simd_reduce_any(x) +} + +// CHECK-LABEL: @reduce_all_8x16 +#[no_mangle] +pub unsafe fn reduce_all_8x16(x: mask8x16) -> bool { + // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{x|1}}, <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7> + // CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1> + // CHECK: [[C:%[0-9]+]] = call i1 @llvm.vector.reduce.and.v16i1(<16 x i1> [[B]]) + // CHECK: %{{[0-9]+}} = zext i1 [[C]] to i8 + simd_reduce_all(x) +} diff --git a/tests/codegen/slice-init.rs b/tests/codegen/slice-init.rs index 1c2dd3e8875..b36a5b5de3d 100644 --- a/tests/codegen/slice-init.rs +++ b/tests/codegen/slice-init.rs @@ -2,6 +2,8 @@ #![crate_type = "lib"] +use std::mem::MaybeUninit; + // CHECK-LABEL: @zero_sized_elem #[no_mangle] pub fn zero_sized_elem() { @@ -76,17 +78,64 @@ pub fn u16_init_one_bytes() -> [u16; N] { [const { u16::from_be_bytes([1, 1]) }; N] } -// FIXME: undef bytes can just be initialized with the same value as the -// defined bytes, if the defines bytes are all the same. // CHECK-LABEL: @option_none_init #[no_mangle] pub fn option_none_init() -> [Option<u8>; N] { // CHECK-NOT: select + // CHECK-NOT: br + // CHECK-NOT: switch + // CHECK-NOT: icmp + // CHECK: call void @llvm.memset.p0 + [const { None }; N] +} + +// If there is partial provenance or some bytes are initialized and some are not, +// we can't really do better than initialize bytes or groups of bytes together. +// CHECK-LABEL: @option_maybe_uninit_init +#[no_mangle] +pub fn option_maybe_uninit_init() -> [MaybeUninit<u16>; N] { + // CHECK-NOT: select + // CHECK: br label %repeat_loop_header{{.*}} + // CHECK-NOT: switch + // CHECK: icmp + // CHECK-NOT: call void @llvm.memset.p0 + [const { + let mut val: MaybeUninit<u16> = MaybeUninit::uninit(); + let ptr = val.as_mut_ptr() as *mut u8; + unsafe { + ptr.write(0); + } + val + }; N] +} + +#[repr(packed)] +struct Packed { + start: u8, + ptr: &'static (), + rest: u16, + rest2: u8, +} + +// If there is partial provenance or some bytes are initialized and some are not, +// we can't really do better than initialize bytes or groups of bytes together. +// CHECK-LABEL: @option_maybe_uninit_provenance +#[no_mangle] +pub fn option_maybe_uninit_provenance() -> [MaybeUninit<Packed>; N] { + // CHECK-NOT: select // CHECK: br label %repeat_loop_header{{.*}} // CHECK-NOT: switch // CHECK: icmp // CHECK-NOT: call void @llvm.memset.p0 - [None; N] + [const { + let mut val: MaybeUninit<Packed> = MaybeUninit::uninit(); + unsafe { + let ptr = &raw mut (*val.as_mut_ptr()).ptr; + static HAS_ADDR: () = (); + ptr.write_unaligned(&HAS_ADDR); + } + val + }; N] } // Use an opaque function to prevent rustc from removing useless drops. diff --git a/tests/codegen/transmute-optimized.rs b/tests/codegen/transmute-optimized.rs index 11bd0523788..de54eecf0c0 100644 --- a/tests/codegen/transmute-optimized.rs +++ b/tests/codegen/transmute-optimized.rs @@ -110,3 +110,11 @@ pub fn char_is_negative(c: char) -> bool { let x: i32 = unsafe { std::mem::transmute(c) }; x < 0 } + +// CHECK-LABEL: i1 @transmute_to_char_is_negative(i32 +#[no_mangle] +pub fn transmute_to_char_is_negative(x: i32) -> bool { + // CHECK: ret i1 false + let _c: char = unsafe { std::mem::transmute(x) }; + x < 0 +} diff --git a/tests/crashes/108428.rs b/tests/crashes/108428.rs new file mode 100644 index 00000000000..b18123b6a7c --- /dev/null +++ b/tests/crashes/108428.rs @@ -0,0 +1,6 @@ +//@ known-bug: #108428 +//@ needs-rustc-debug-assertions +//@ compile-flags: -Wunused-lifetimes +fn main() { + let _: extern fn<'a: 'static>(); +} diff --git a/tests/crashes/128097.rs b/tests/crashes/128097.rs deleted file mode 100644 index 6ffca640cbd..00000000000 --- a/tests/crashes/128097.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #128097 -#![feature(explicit_tail_calls)] -fn f(x: &mut ()) { - let _y: String; - become f(x); -} diff --git a/tests/crashes/130779.rs b/tests/crashes/130779.rs deleted file mode 100644 index f0fd81fff44..00000000000 --- a/tests/crashes/130779.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #130779 -#![feature(never_patterns)] - -enum E { A } - -fn main() { - match E::A { - ! | - if true => {} - } -} diff --git a/tests/crashes/132826.rs b/tests/crashes/132826.rs new file mode 100644 index 00000000000..9889cecdac5 --- /dev/null +++ b/tests/crashes/132826.rs @@ -0,0 +1,10 @@ +//@ known-bug: #132826 +pub trait MyTrait { + type Item; +} + +impl<K> MyTrait for Vec<K> { + type Item = Vec<K>; +} + +impl<K> From<Vec<K>> for <Vec<K> as MyTrait>::Item {} diff --git a/tests/crashes/133063.rs b/tests/crashes/133063.rs deleted file mode 100644 index 132b5486170..00000000000 --- a/tests/crashes/133063.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #133063 - -fn foo(x: !) { - match x { - (! | !) if false => {} - _ => {} - } -} diff --git a/tests/crashes/133117.rs b/tests/crashes/133117.rs deleted file mode 100644 index 751c82626d5..00000000000 --- a/tests/crashes/133117.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #133117 - -fn main() { - match () { - (!|!) if true => {} - (!|!) if true => {} - } -} diff --git a/tests/crashes/135020.rs b/tests/crashes/135020.rs deleted file mode 100644 index b44056eb3af..00000000000 --- a/tests/crashes/135020.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ known-bug: #135020 - -pub fn problem_thingy(items: &mut impl Iterator<Item = str>) { - let mut peeker = items.peekable(); - match peeker.peek() { - Some(_) => (), - None => return (), - } -} - -pub fn main() {} diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff index 148ff86354b..a91d88984a8 100644 --- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff @@ -4,8 +4,8 @@ fn bar() -> bool { let mut _0: bool; -+ coverage body span: $DIR/instrument_coverage.rs:19:18: 21:2 (#0) -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:19:1: 21:2 (#0); ++ coverage body span: $DIR/instrument_coverage.rs:29:18: 31:2 (#0) ++ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:29:1: 31:2 (#0); + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff index fa09cf0b83f..d7ea442518e 100644 --- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff +++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff @@ -7,13 +7,13 @@ let mut _2: bool; let mut _3: !; -+ coverage body span: $DIR/instrument_coverage.rs:10:11: 16:2 (#0) ++ coverage body span: $DIR/instrument_coverage.rs:14:11: 20:2 (#0) + coverage ExpressionId(0) => Expression { lhs: Counter(1), op: Subtract, rhs: Counter(0) }; -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:10:1: 10:11 (#0); -+ coverage Code(Counter(1)) => $DIR/instrument_coverage.rs:12:12: 12:17 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:13:13: 13:18 (#0); -+ coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:14:10: 14:10 (#0); -+ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:16:2: 16:2 (#0); ++ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:14:1: 14:11 (#0); ++ coverage Code(Counter(1)) => $DIR/instrument_coverage.rs:16:12: 16:17 (#0); ++ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:17:13: 17:18 (#0); ++ coverage Code(Expression(0)) => $DIR/instrument_coverage.rs:18:10: 18:10 (#0); ++ coverage Code(Counter(0)) => $DIR/instrument_coverage.rs:20:2: 20:2 (#0); + bb0: { + Coverage::CounterIncrement(0); diff --git a/tests/mir-opt/coverage/instrument_coverage.rs b/tests/mir-opt/coverage/instrument_coverage.rs index beb88b607f9..c49786f9615 100644 --- a/tests/mir-opt/coverage/instrument_coverage.rs +++ b/tests/mir-opt/coverage/instrument_coverage.rs @@ -6,7 +6,11 @@ //@ compile-flags: -Cinstrument-coverage -Zno-profiler-runtime // EMIT_MIR instrument_coverage.main.InstrumentCoverage.diff -// EMIT_MIR instrument_coverage.bar.InstrumentCoverage.diff +// CHECK-LABEL: fn main() +// CHECK: coverage body span: +// CHECK: coverage Code(Counter({{[0-9]+}})) => +// CHECK: bb0: +// CHECK: Coverage::CounterIncrement fn main() { loop { if bar() { @@ -15,14 +19,13 @@ fn main() { } } +// EMIT_MIR instrument_coverage.bar.InstrumentCoverage.diff +// CHECK-LABEL: fn bar() +// CHECK: coverage body span: +// CHECK: coverage Code(Counter({{[0-9]+}})) => +// CHECK: bb0: +// CHECK: Coverage::CounterIncrement #[inline(never)] fn bar() -> bool { true } - -// CHECK: coverage ExpressionId({{[0-9]+}}) => -// CHECK-DAG: coverage Code(Counter({{[0-9]+}})) => -// CHECK-DAG: coverage Code(Expression({{[0-9]+}})) => -// CHECK: bb0: -// CHECK-DAG: Coverage::ExpressionUsed({{[0-9]+}}) -// CHECK-DAG: Coverage::CounterIncrement({{[0-9]+}}) diff --git a/tests/mir-opt/optimize_none.rs b/tests/mir-opt/optimize_none.rs new file mode 100644 index 00000000000..a5b541bd2b6 --- /dev/null +++ b/tests/mir-opt/optimize_none.rs @@ -0,0 +1,32 @@ +//@ revisions: NO-OPT SPEED-OPT +//@[NO-OPT] compile-flags: -Copt-level=0 +//@[SPEED-OPT] compile-flags: -Copt-level=3 -Coverflow-checks=y + +#![feature(optimize_attribute)] + +#[optimize(none)] +pub fn add_noopt() -> i32 { + // CHECK-LABEL: fn add_noopt( + // CHECK: AddWithOverflow(const 1_i32, const 2_i32); + // CHECK-NEXT: assert + 1 + 2 +} + +#[optimize(none)] +pub fn const_branch() -> i32 { + // CHECK-LABEL: fn const_branch( + // CHECK: switchInt(const true) -> [0: [[FALSE:bb[0-9]+]], otherwise: [[TRUE:bb[0-9]+]]]; + // CHECK-NEXT: } + // CHECK: [[FALSE]]: { + // CHECK-NEXT: _0 = const 0 + // CHECK-NEXT: goto + // CHECK-NEXT: } + // CHECK: [[TRUE]]: { + // CHECK-NEXT: _0 = const 1 + // CHECK-NEXT: goto + // CHECK-NEXT: } + + if true { 1 } else { 0 } +} + +fn main() {} diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir index cff5b4c7243..1a1c8b4b942 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir @@ -13,7 +13,7 @@ fn step_forward(_1: u16, _2: usize) -> u16 { scope 6 (inlined core::num::<impl u16>::checked_add) { let mut _5: (u16, bool); let mut _6: bool; - scope 7 (inlined unlikely) { + scope 7 (inlined std::intrinsics::unlikely) { let _7: (); } } @@ -55,7 +55,7 @@ fn step_forward(_1: u16, _2: usize) -> u16 { } bb3: { - _7 = cold_path() -> [return: bb4, unwind unreachable]; + _7 = std::intrinsics::cold_path() -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir index 6e0242a220d..e7e19af048a 100644 --- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir @@ -13,7 +13,7 @@ fn step_forward(_1: u16, _2: usize) -> u16 { scope 6 (inlined core::num::<impl u16>::checked_add) { let mut _5: (u16, bool); let mut _6: bool; - scope 7 (inlined unlikely) { + scope 7 (inlined std::intrinsics::unlikely) { let _7: (); } } @@ -55,7 +55,7 @@ fn step_forward(_1: u16, _2: usize) -> u16 { } bb3: { - _7 = cold_path() -> [return: bb4, unwind unreachable]; + _7 = std::intrinsics::cold_path() -> [return: bb4, unwind unreachable]; } bb4: { diff --git a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff index 17c64d4baf0..9a4f27a497d 100644 --- a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-abort.diff @@ -66,7 +66,6 @@ bb6: { + _8 = const false; StorageDead(_4); - StorageDead(_3); drop(_2) -> [return: bb7, unwind: bb12]; } diff --git a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff index 58d8a87986d..f13ee78aa36 100644 --- a/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/tail_call_drops.f.ElaborateDrops.panic-unwind.diff @@ -66,7 +66,6 @@ bb6: { + _8 = const false; StorageDead(_4); - StorageDead(_3); - drop(_2) -> [return: bb7, unwind continue]; + drop(_2) -> [return: bb7, unwind: bb12]; } diff --git a/tests/mir-opt/tail_call_drops.f.built.after.panic-abort.mir b/tests/mir-opt/tail_call_drops.f.built.after.panic-abort.mir index 2c3d62491d7..e017424a4cc 100644 --- a/tests/mir-opt/tail_call_drops.f.built.after.panic-abort.mir +++ b/tests/mir-opt/tail_call_drops.f.built.after.panic-abort.mir @@ -63,7 +63,6 @@ fn f() -> () { bb6: { StorageDead(_4); - StorageDead(_3); drop(_2) -> [return: bb7, unwind: bb17]; } diff --git a/tests/mir-opt/tail_call_drops.f.built.after.panic-unwind.mir b/tests/mir-opt/tail_call_drops.f.built.after.panic-unwind.mir index 2c3d62491d7..e017424a4cc 100644 --- a/tests/mir-opt/tail_call_drops.f.built.after.panic-unwind.mir +++ b/tests/mir-opt/tail_call_drops.f.built.after.panic-unwind.mir @@ -63,7 +63,6 @@ fn f() -> () { bb6: { StorageDead(_4); - StorageDead(_3); drop(_2) -> [return: bb7, unwind: bb17]; } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff index 1a51601bc56..a8c57d2cfe0 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff +++ b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-abort.diff @@ -80,7 +80,6 @@ bb8: { + _12 = const false; StorageDead(_6); - StorageDead(_5); drop(_4) -> [return: bb9, unwind: bb16]; } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff index 1a51601bc56..a8c57d2cfe0 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff +++ b/tests/mir-opt/tail_call_drops.f_with_arg.ElaborateDrops.panic-unwind.diff @@ -80,7 +80,6 @@ bb8: { + _12 = const false; StorageDead(_6); - StorageDead(_5); drop(_4) -> [return: bb9, unwind: bb16]; } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-abort.mir b/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-abort.mir index 744f1989acc..f89b98a3205 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-abort.mir +++ b/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-abort.mir @@ -77,7 +77,6 @@ fn f_with_arg(_1: String, _2: String) -> () { bb8: { StorageDead(_6); - StorageDead(_5); drop(_4) -> [return: bb9, unwind: bb23]; } diff --git a/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-unwind.mir b/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-unwind.mir index 744f1989acc..f89b98a3205 100644 --- a/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-unwind.mir +++ b/tests/mir-opt/tail_call_drops.f_with_arg.built.after.panic-unwind.mir @@ -77,7 +77,6 @@ fn f_with_arg(_1: String, _2: String) -> () { bb8: { StorageDead(_6); - StorageDead(_5); drop(_4) -> [return: bb9, unwind: bb23]; } diff --git a/tests/run-make/cat-and-grep-sanity-check/Makefile b/tests/run-make/cat-and-grep-sanity-check/Makefile deleted file mode 100644 index 8ee69c0a0de..00000000000 --- a/tests/run-make/cat-and-grep-sanity-check/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# grep in run-make tests was partially replaced with a custom script, CGREP. This tests that CGREP does its job correctly. -# See https://github.com/rust-lang/rust/commit/ab788a2ee175c7560f0ca58bbc183ecfd57d2f7a -# FIXME(Oneirical): Note that this test will likely become useless after the port to rmake.rs tests (see https://github.com/rust-lang/rust/issues/121876) - -include ../tools.mk - -all: - echo a | $(CGREP) a - ! echo b | $(CGREP) a - echo xyz | $(CGREP) x y z - ! echo abc | $(CGREP) b c d - printf "x\ny\nz" | $(CGREP) x y z - - echo AbCd | $(CGREP) -i a b C D - ! echo AbCd | $(CGREP) a b C D - - true | $(CGREP) -v nothing - ! echo nothing | $(CGREP) -v nothing - ! echo xyz | $(CGREP) -v w x y - ! echo xyz | $(CGREP) -v x y z - echo xyz | $(CGREP) -v a b c - - ! echo 'foo bar baz' | $(CGREP) 'foo baz' - echo 'foo bar baz' | $(CGREP) foo baz - echo 'x a `b` c y z' | $(CGREP) 'a `b` c' - - echo baaac | $(CGREP) -e 'ba*c' - echo bc | $(CGREP) -e 'ba*c' - ! echo aaac | $(CGREP) -e 'ba*c' - - echo aaa | $(CGREP) -e 'a+' - ! echo bbb | $(CGREP) -e 'a+' - - echo abc | $(CGREP) -e 'a|e|i|o|u' - ! echo fgh | $(CGREP) -e 'a|e|i|o|u' - echo abc | $(CGREP) -e '[aeiou]' - ! echo fgh | $(CGREP) -e '[aeiou]' - ! echo abc | $(CGREP) -e '[^aeiou]{3}' - echo fgh | $(CGREP) -e '[^aeiou]{3}' - echo ab cd ef gh | $(CGREP) -e '\bcd\b' - ! echo abcdefgh | $(CGREP) -e '\bcd\b' - echo xyz | $(CGREP) -e '...' - ! echo xy | $(CGREP) -e '...' - ! echo xyz | $(CGREP) -e '\.\.\.' - echo ... | $(CGREP) -e '\.\.\.' - - echo foo bar baz | $(CGREP) -e 'foo.*baz' - ! echo foo bar baz | $(CGREP) -ve 'foo.*baz' - ! echo foo bar baz | $(CGREP) -e 'baz.*foo' - echo foo bar baz | $(CGREP) -ve 'baz.*foo' diff --git a/tests/run-make/crate-circular-deps-link/c.rs b/tests/run-make/crate-circular-deps-link/c.rs index 9d72657aa59..cfe00a2a347 100644 --- a/tests/run-make/crate-circular-deps-link/c.rs +++ b/tests/run-make/crate-circular-deps-link/c.rs @@ -1,5 +1,5 @@ #![crate_type = "bin"] -#![feature(start)] +#![no_main] #![no_std] extern crate a; @@ -24,8 +24,8 @@ unsafe impl GlobalAlloc for Allocator { #[global_allocator] static ALLOCATOR: Allocator = Allocator; -#[start] -fn main(argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { let mut v = Vec::new(); for i in 0..argc { v.push(i); diff --git a/tests/run-make/fmt-write-bloat/main.rs b/tests/run-make/fmt-write-bloat/main.rs index 6f206d6515a..b50461c0a02 100644 --- a/tests/run-make/fmt-write-bloat/main.rs +++ b/tests/run-make/fmt-write-bloat/main.rs @@ -1,5 +1,5 @@ #![feature(lang_items)] -#![feature(start)] +#![no_main] #![no_std] use core::fmt; @@ -17,8 +17,8 @@ impl fmt::Write for Dummy { } } -#[start] -fn main(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { let _ = writeln!(Dummy, "Hello World"); 0 } diff --git a/tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu/rmake.rs b/tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu/rmake.rs new file mode 100644 index 00000000000..0134457c5c2 --- /dev/null +++ b/tests/run-make/glibc-symbols-x86_64-unknown-linux-gnu/rmake.rs @@ -0,0 +1,112 @@ +// Check that the compiler toolchain (rustc) that we distribute is not using newer glibc +// symbols than a specified minimum. +// This test should only be executed on an extracted dist archive or in a dist-* CI job. + +//@ only-dist +//@ only-x86_64-unknown-linux-gnu +//@ ignore-cross-compile + +use std::path::{Path, PathBuf}; + +use run_make_support::{cmd, llvm_objdump, regex, rustc_path}; + +fn main() { + // This is the maximum glibc version that we are *permitted* to use for the + // x86_64-unknown-linux-gnu target. + // All glibc symbols used in the compiler must be lower or equal than this version. + // So that if a given machine only has glibc 2.17, it is able to run the compiler. + let max_supported = (2, 17, 99); + + let rustc = PathBuf::from(rustc_path()); + // Check symbols directly in rustc + check_symbols(&rustc, max_supported); + + // Find dynamic libraries referenced by rustc that come from our lib directory + let lib_path = rustc.parent().unwrap().parent().unwrap().join("lib"); + let dynamic_libs = find_dynamic_libs(&rustc) + .into_iter() + .filter_map(|path| path.canonicalize().ok()) + .filter(|lib| lib.starts_with(&lib_path)) + .collect::<Vec<_>>(); + for lib in dynamic_libs { + check_symbols(&lib, max_supported); + } +} + +#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] +struct GlibcSymbol { + name: String, + version: (u32, u32, u32), +} + +fn find_dynamic_libs(path: &Path) -> Vec<PathBuf> { + cmd("ldd") + .arg(path) + .run() + .stdout_utf8() + .lines() + .filter_map(|line| { + let line = line.trim(); + let Some((_, line)) = line.split_once(" => ") else { + return None; + }; + line.split_ascii_whitespace().next().map(|path| PathBuf::from(path)) + }) + .collect() +} + +fn check_symbols(file: &Path, max_supported: (u32, u32, u32)) { + println!("Checking {}", file.display()); + let mut invalid: Vec<GlibcSymbol> = get_glibc_symbols(file) + .into_iter() + .filter(|symbol| symbol.version > max_supported) + .collect(); + if !invalid.is_empty() { + invalid.sort(); + panic!( + "Found invalid glibc symbols in {}:\n{}", + file.display(), + invalid + .into_iter() + .map(|symbol| format!( + "{} ({:?} higher than max allowed {:?})", + symbol.name, symbol.version, max_supported + )) + .collect::<Vec<_>>() + .join("\n") + ) + } +} + +fn get_glibc_symbols(file: &Path) -> Vec<GlibcSymbol> { + let regex = regex::Regex::new(r#"GLIBC_(\d)+\.(\d+)(:?\.(\d+))?"#).unwrap(); + + // FIXME(kobzol): llvm-objdump currently chokes on the BOLTed librustc_driver.so file. + // Use objdump instead, since it seems to work, and we only run this test in a specific + // CI environment anyway. + cmd("objdump") + .arg("--dynamic-syms") + .arg(file) + .run() + .stdout_utf8() + .lines() + .filter_map(|line| { + // Example line + // 0000000000000000 DF *UND* 0000000000000000 (GLIBC_2.2.5) sbrk + let mut parts = line.split(" ").collect::<Vec<_>>().into_iter().rev(); + let Some(name) = parts.next() else { + return None; + }; + let Some(lib) = parts.next() else { + return None; + }; + let Some(version) = regex.captures(lib) else { + return None; + }; + let major = version.get(1).and_then(|m| m.as_str().parse().ok()).unwrap_or(0); + let minor = version.get(2).and_then(|m| m.as_str().parse().ok()).unwrap_or(0); + let patch = version.get(3).and_then(|m| m.as_str().parse().ok()).unwrap_or(0); + Some(GlibcSymbol { version: (major, minor, patch), name: name.to_string() }) + }) + .collect() +} diff --git a/tests/run-make/jobserver-error/Makefile b/tests/run-make/jobserver-error/Makefile deleted file mode 100644 index 9f34970f96f..00000000000 --- a/tests/run-make/jobserver-error/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -include ../tools.mk - -# only-linux -# ignore-cross-compile - -# Test compiler behavior in case environment specifies wrong jobserver. -# Note that by default, the compiler uses file descriptors 0 (stdin), 1 (stdout), 2 (stderr), -# but also 3 and 4 for either end of the ctrl-c signal handler self-pipe. - -all: - bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=5,5" $(RUSTC)' 2>&1 | diff cannot_open_fd.stderr - - bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3</dev/null' 2>&1 | diff not_a_pipe.stderr - - -# This test randomly fails, see https://github.com/rust-lang/rust/issues/110321 -disabled: - bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3< <(cat /dev/null)' 2>&1 | diff poisoned_pipe.stderr - - diff --git a/tests/run-make/jobserver-error/cannot_open_fd.stderr b/tests/run-make/jobserver-error/cannot_open_fd.stderr index 9ac4c1c58f7..d075057b3d3 100644 --- a/tests/run-make/jobserver-error/cannot_open_fd.stderr +++ b/tests/run-make/jobserver-error/cannot_open_fd.stderr @@ -1,4 +1,4 @@ -warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=5,5"`: cannot open file descriptor 5 from the jobserver environment variable value: Bad file descriptor (os error 9) +warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--jobserver-auth=1000,1000"`: cannot open file descriptor 1000 from the jobserver environment variable value: Bad file descriptor (os error 9) | = note: the build environment is likely misconfigured diff --git a/tests/run-make/jobserver-error/rmake.rs b/tests/run-make/jobserver-error/rmake.rs new file mode 100644 index 00000000000..14ee24c7148 --- /dev/null +++ b/tests/run-make/jobserver-error/rmake.rs @@ -0,0 +1,47 @@ +// ignore-tidy-linelength +//! If the environment variables contain an invalid `jobserver-auth`, this used to cause an ICE +//! until this was fixed in [do not panic on failure to acquire jobserver token +//! #109694](https://github.com/rust-lang/rust/pull/109694). +//! +//! Proper handling has been added, and this test checks that helpful warnings and errors are +//! printed instead in case of a wrong jobserver. See +//! <https://github.com/rust-lang/rust/issues/46981>. + +//@ only-linux +//@ ignore-cross-compile + +#![deny(warnings)] + +use run_make_support::{diff, rustc}; + +fn main() { + let out = rustc() + .stdin_buf(("fn main() {}").as_bytes()) + .env("MAKEFLAGS", "--jobserver-auth=1000,1000") + .run_fail() + .stderr_utf8(); + diff().expected_file("cannot_open_fd.stderr").actual_text("actual", out).run(); + + let out = rustc() + .stdin_buf(("fn main() {}").as_bytes()) + .input("-") + .env("MAKEFLAGS", "--jobserver-auth=3,3") + .set_aux_fd(3, std::fs::File::open("/dev/null").unwrap()) + .run() + .stderr_utf8(); + diff().expected_file("not_a_pipe.stderr").actual_text("actual", out).run(); + + // FIXME(#110321): the Makefile version had a disabled check: + // + // ```makefile + // bash -c 'echo "fn main() {}" | MAKEFLAGS="--jobserver-auth=3,3" $(RUSTC) - 3< <(cat /dev/null)' 2>&1 | diff poisoned_pipe.stderr - + // ``` + // + // > the jobserver helper thread launched here gets starved out and doesn't run, while the + // > coordinator thread continually processes work using the implicit jobserver token, never + // > yielding long enough for the jobserver helper to do its work (and process the error). + // + // but is not necessarily worth fixing as it might require changing coordinator behavior that + // might regress performance. See discussion at + // <https://github.com/rust-lang/rust/issues/110321#issuecomment-1636914956>. +} diff --git a/tests/run-make/linker-warning/fake-linker.sh b/tests/run-make/linker-warning/fake-linker.sh new file mode 100755 index 00000000000..ed4d472c3bf --- /dev/null +++ b/tests/run-make/linker-warning/fake-linker.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +code=0 +while ! [ $# = 0 ]; do + case "$1" in + run_make_info) echo "foo" + ;; + run_make_warn) echo "warning: bar" >&2 + ;; + run_make_error) echo "error: baz" >&2; code=1 + ;; + *) ;; # rustc passes lots of args we don't care about + esac + shift +done + +exit $code diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index 4d21c5ea569..30387af428c 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -1,8 +1,20 @@ -use run_make_support::{Rustc, rustc}; +use run_make_support::{Rustc, diff, regex, rustc}; fn run_rustc() -> Rustc { let mut rustc = rustc(); - rustc.arg("main.rs").output("main").linker("./fake-linker"); + rustc + .arg("main.rs") + // NOTE: `link-self-contained` can vary depending on config.toml. + // Make sure we use a consistent value. + .arg("-Clink-self-contained=-linker") + .arg("-Zunstable-options") + .arg("-Wlinker-messages") + .output("main") + .linker("./fake-linker"); + if run_make_support::target() == "x86_64-unknown-linux-gnu" { + // The value of `rust.lld` is different between CI and locally. Override it explicitly. + rustc.arg("-Clinker-flavor=gnu-cc"); + } rustc } @@ -10,19 +22,73 @@ fn main() { // first, compile our linker rustc().arg("fake-linker.rs").output("fake-linker").run(); - // Make sure we don't show the linker args unless `--verbose` is passed + // Run rustc with our fake linker, and make sure it shows warnings + let warnings = run_rustc().link_arg("run_make_warn").run(); + warnings.assert_stderr_contains("warning: linker stderr: bar"); + + // Make sure it shows stdout run_rustc() - .link_arg("run_make_error") - .verbose() - .run_fail() - .assert_stderr_contains_regex("fake-linker.*run_make_error") + .link_arg("run_make_info") + .run() + .assert_stderr_contains("warning: linker stdout: foo"); + + // Make sure we short-circuit this new path if the linker exits with an error + // (so the diagnostic is less verbose) + run_rustc().link_arg("run_make_error").run_fail().assert_stderr_contains("note: error: baz"); + + // Make sure we don't show the linker args unless `--verbose` is passed + let out = run_rustc().link_arg("run_make_error").verbose().run_fail(); + out.assert_stderr_contains_regex("fake-linker.*run_make_error") .assert_stderr_not_contains("object files omitted") + .assert_stderr_contains(r".rcgu.o") .assert_stderr_contains_regex(r"lib(/|\\\\)libstd"); - run_rustc() - .link_arg("run_make_error") - .run_fail() - .assert_stderr_contains("fake-linker") + + let out = run_rustc().link_arg("run_make_error").run_fail(); + out.assert_stderr_contains("fake-linker") .assert_stderr_contains("object files omitted") .assert_stderr_contains_regex(r"\{") + .assert_stderr_not_contains(r".rcgu.o") .assert_stderr_not_contains_regex(r"lib(/|\\\\)libstd"); + + // FIXME: we should have a version of this for mac and windows + if run_make_support::target() == "x86_64-unknown-linux-gnu" { + diff() + .expected_file("short-error.txt") + .actual_text("(linker error)", out.stderr()) + .normalize(r#"/rustc[^/]*/"#, "/rustc/") + .normalize( + regex::escape(run_make_support::build_root().to_str().unwrap()), + "/build-root", + ) + .run(); + } + + // Make sure we show linker warnings even across `-Z no-link` + rustc() + .arg("-Zno-link") + .input("-") + .stdin_buf("#![deny(linker_messages)] \n fn main() {}") + .run() + .assert_stderr_equals(""); + rustc() + .arg("-Zlink-only") + .arg("rust_out.rlink") + .linker("./fake-linker") + .link_arg("run_make_warn") + .run_fail() + // NOTE: the error message here is quite bad (we don't have a source + // span, but still try to print the lint source). But `-Z link-only` is + // unstable and this still shows the linker warning itself so this is + // probably good enough. + .assert_stderr_contains("linker stderr: bar"); + + // Same thing, but with json output. + rustc() + .error_format("json") + .arg("-Zlink-only") + .arg("rust_out.rlink") + .linker("./fake-linker") + .link_arg("run_make_warn") + .run_fail() + .assert_stderr_contains(r#""$message_type":"diagnostic""#); } diff --git a/tests/run-make/linker-warning/short-error.txt b/tests/run-make/linker-warning/short-error.txt new file mode 100644 index 00000000000..dd3b742bbfd --- /dev/null +++ b/tests/run-make/linker-warning/short-error.txt @@ -0,0 +1,9 @@ +error: linking with `./fake-linker` failed: exit status: 1 + | + = note: "./fake-linker" "-m64" "/tmp/rustc/symbols.o" "<2 object files omitted>" "-Wl,--as-needed" "-Wl,-Bstatic" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib/{libstd-*,libpanic_unwind-*,libobject-*,libmemchr-*,libaddr2line-*,libgimli-*,librustc_demangle-*,libstd_detect-*,libhashbrown-*,librustc_std_workspace_alloc-*,libminiz_oxide-*,libadler2-*,libunwind-*,libcfg_if-*,liblibc-*,liballoc-*,librustc_std_workspace_core-*,libcore-*,libcompiler_builtins-*}.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/build-root/test/run-make/linker-warning/rmake_out" "-L" "<sysroot>/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" + = note: some arguments are omitted. use `--verbose` to show all linker arguments + = note: error: baz + + +error: aborting due to 1 previous error + diff --git a/tests/run-make/llvm-location-discriminator-limit-dummy-span/main.rs b/tests/run-make/llvm-location-discriminator-limit-dummy-span/main.rs new file mode 100644 index 00000000000..421eb4331b3 --- /dev/null +++ b/tests/run-make/llvm-location-discriminator-limit-dummy-span/main.rs @@ -0,0 +1,3 @@ +fn main() { + other::big_function(); +} diff --git a/tests/run-make/llvm-location-discriminator-limit-dummy-span/other.rs b/tests/run-make/llvm-location-discriminator-limit-dummy-span/other.rs new file mode 100644 index 00000000000..a3ff578ebe4 --- /dev/null +++ b/tests/run-make/llvm-location-discriminator-limit-dummy-span/other.rs @@ -0,0 +1 @@ +proc::declare_big_function!(); diff --git a/tests/run-make/llvm-location-discriminator-limit-dummy-span/proc.rs b/tests/run-make/llvm-location-discriminator-limit-dummy-span/proc.rs new file mode 100644 index 00000000000..59d17a9be59 --- /dev/null +++ b/tests/run-make/llvm-location-discriminator-limit-dummy-span/proc.rs @@ -0,0 +1,7 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn declare_big_function(_input: TokenStream) -> TokenStream { + include_str!("./generated.rs").parse().unwrap() +} diff --git a/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs b/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs new file mode 100644 index 00000000000..2727effe818 --- /dev/null +++ b/tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs @@ -0,0 +1,65 @@ +//! Regression test for <https://github.com/rust-lang/rust/issues/135332>. +//! +//! We can't simply drop debuginfo location spans when LLVM's location discriminator value limit is +//! reached. Otherwise, with `-Z verify-llvm-ir` and fat LTO, LLVM will report a broken module for +//! +//! ```text +//! inlinable function call in a function with debug info must have a !dbg location +//! ``` + +//@ ignore-cross-compile +//@ needs-dynamic-linking +//@ only-nightly (requires unstable rustc flag) + +#![deny(warnings)] + +use run_make_support::{dynamic_lib_name, rfs, rust_lib_name, rustc}; + +// Synthesize a function that will have a large (`n`) number of functions +// MIR-inlined into it. When combined with a proc-macro, all of these inline +// callsites will have the same span, forcing rustc to use the DWARF +// discriminator to distinguish between them. LLVM's capacity to store that +// discriminator is not infinite (currently it allocates 12 bits for a +// maximum value of 4096) so if this function gets big enough rustc's error +// handling path will be exercised. +fn generate_program(n: u32) -> String { + let mut program = String::from("pub type BigType = Vec<Vec<String>>;\n\n"); + program.push_str("pub fn big_function() -> BigType {\n"); + program.push_str(" vec![\n"); + for i in 1..=n { + program.push_str(&format!("vec![\"string{}\".to_owned()],\n", i)); + } + program.push_str(" ]\n"); + program.push_str("}\n"); + program +} + +fn main() { + // The reported threshold is around 1366 (4096/3), but let's bump it to + // around 1500 to be less sensitive. + rfs::write("generated.rs", generate_program(1500)); + + rustc() + .input("proc.rs") + .crate_type("proc-macro") + .edition("2021") + .arg("-Cdebuginfo=line-tables-only") + .run(); + rustc() + .extern_("proc", dynamic_lib_name("proc")) + .input("other.rs") + .crate_type("rlib") + .edition("2021") + .opt_level("3") + .arg("-Cdebuginfo=line-tables-only") + .run(); + rustc() + .extern_("other", rust_lib_name("other")) + .input("main.rs") + .edition("2021") + .opt_level("3") + .arg("-Cdebuginfo=line-tables-only") + .arg("-Clto=fat") + .arg("-Zverify-llvm-ir") + .run(); +} diff --git a/tests/run-make/no-alloc-shim/foo.rs b/tests/run-make/no-alloc-shim/foo.rs index a3daec3db39..42606961f8b 100644 --- a/tests/run-make/no-alloc-shim/foo.rs +++ b/tests/run-make/no-alloc-shim/foo.rs @@ -35,7 +35,7 @@ unsafe impl GlobalAlloc for Alloc { static __rust_no_alloc_shim_is_unstable: u8 = 0; #[no_mangle] -extern "C" fn main(_argc: usize, _argv: *const *const i8) -> i32 { +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const i8) -> i32 { unsafe { assert_eq!(alloc::alloc::alloc(Layout::new::<()>()), core::ptr::null_mut()); } diff --git a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs index 2417a4274e4..263bb9b2e20 100644 --- a/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs +++ b/tests/run-make/rust-lld-by-default-beta-stable/rmake.rs @@ -12,11 +12,7 @@ use run_make_support::rustc; fn main() { // A regular compilation should not use rust-lld by default. We'll check that by asking the // linker to display its version number with a link-arg. - let output = rustc() - .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") - .link_arg("-Wl,-v") - .input("main.rs") - .run(); + let output = rustc().arg("-Wlinker-messages").link_arg("-Wl,-v").input("main.rs").run(); assert!( !find_lld_version_in_logs(output.stderr_utf8()), "the LLD version string should not be present in the output logs:\n{}", @@ -25,6 +21,7 @@ fn main() { } fn find_lld_version_in_logs(stderr: String) -> bool { - let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); + let lld_version_re = + Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); stderr.lines().any(|line| lld_version_re.is_match(line.trim())) } diff --git a/tests/run-make/rust-lld-by-default-nightly/rmake.rs b/tests/run-make/rust-lld-by-default-nightly/rmake.rs index 02bbe8227f0..7a0a08863dd 100644 --- a/tests/run-make/rust-lld-by-default-nightly/rmake.rs +++ b/tests/run-make/rust-lld-by-default-nightly/rmake.rs @@ -12,11 +12,7 @@ use run_make_support::rustc; fn main() { // A regular compilation should use rust-lld by default. We'll check that by asking the linker // to display its version number with a link-arg. - let output = rustc() - .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") - .link_arg("-Wl,-v") - .input("main.rs") - .run(); + let output = rustc().arg("-Wlinker-messages").link_arg("-Wl,-v").input("main.rs").run(); assert!( find_lld_version_in_logs(output.stderr_utf8()), "the LLD version string should be present in the output logs:\n{}", @@ -25,7 +21,7 @@ fn main() { // But it can still be disabled by turning the linker feature off. let output = rustc() - .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") + .arg("-Wlinker-messages") .link_arg("-Wl,-v") .arg("-Zlinker-features=-lld") .input("main.rs") @@ -38,6 +34,7 @@ fn main() { } fn find_lld_version_in_logs(stderr: String) -> bool { - let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); + let lld_version_re = + Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); stderr.lines().any(|line| lld_version_re.is_match(line.trim())) } diff --git a/tests/run-make/rust-lld-custom-target/rmake.rs b/tests/run-make/rust-lld-custom-target/rmake.rs index a6f7c33793a..993a248ad00 100644 --- a/tests/run-make/rust-lld-custom-target/rmake.rs +++ b/tests/run-make/rust-lld-custom-target/rmake.rs @@ -15,8 +15,8 @@ fn main() { // Compile to a custom target spec with rust-lld enabled by default. We'll check that by asking // the linker to display its version number with a link-arg. let output = rustc() - .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") .crate_type("cdylib") + .arg("-Wlinker-messages") .target("custom-target.json") .link_arg("-Wl,-v") .input("lib.rs") @@ -29,8 +29,8 @@ fn main() { // But it can also be disabled via linker features. let output = rustc() - .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") .crate_type("cdylib") + .arg("-Wlinker-messages") .target("custom-target.json") .arg("-Zlinker-features=-lld") .link_arg("-Wl,-v") @@ -44,6 +44,7 @@ fn main() { } fn find_lld_version_in_logs(stderr: String) -> bool { - let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); + let lld_version_re = + Regex::new(r"^warning: linker stdout: LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); stderr.lines().any(|line| lld_version_re.is_match(line.trim())) } diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs index 1f311af1ed5..e5ae9435388 100644 --- a/tests/run-make/rust-lld/rmake.rs +++ b/tests/run-make/rust-lld/rmake.rs @@ -14,10 +14,10 @@ fn main() { // Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by // asking the linker to display its version number with a link-arg. let output = rustc() - .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") .arg("-Zlinker-features=+lld") .arg("-Clink-self-contained=+linker") .arg("-Zunstable-options") + .arg("-Wlinker-messages") .link_arg(linker_version_flag) .input("main.rs") .run(); @@ -29,9 +29,9 @@ fn main() { // It should not be used when we explicitly opt-out of lld. let output = rustc() - .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") .link_arg(linker_version_flag) .arg("-Zlinker-features=-lld") + .arg("-Wlinker-messages") .input("main.rs") .run(); assert!( @@ -43,13 +43,13 @@ fn main() { // While we're here, also check that the last linker feature flag "wins" when passed multiple // times to rustc. let output = rustc() - .env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info") .link_arg(linker_version_flag) .arg("-Clink-self-contained=+linker") .arg("-Zunstable-options") .arg("-Zlinker-features=-lld") .arg("-Zlinker-features=+lld") .arg("-Zlinker-features=-lld,+lld") + .arg("-Wlinker-messages") .input("main.rs") .run(); assert!( @@ -60,6 +60,7 @@ fn main() { } fn find_lld_version_in_logs(stderr: String) -> bool { - let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); + let lld_version_re = + Regex::new(r"^warning: linker std(out|err): LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap(); stderr.lines().any(|line| lld_version_re.is_match(line.trim())) } diff --git a/tests/run-make/sepcomp-inlining/foo.rs b/tests/run-make/sepcomp-inlining/foo.rs index 2fe5f9cb726..9101ee691a4 100644 --- a/tests/run-make/sepcomp-inlining/foo.rs +++ b/tests/run-make/sepcomp-inlining/foo.rs @@ -1,4 +1,4 @@ -#![feature(start)] +#![crate_type = "lib"] #[inline] fn inlined() -> u32 { @@ -21,8 +21,7 @@ mod b { } } -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +pub fn start(_: isize, _: *const *const u8) -> isize { a::f(); b::f(); diff --git a/tests/rustdoc-gui/search-tab.goml b/tests/rustdoc-gui/search-tab.goml index eea561e0c67..826e272e508 100644 --- a/tests/rustdoc-gui/search-tab.goml +++ b/tests/rustdoc-gui/search-tab.goml @@ -78,7 +78,7 @@ call-function: ("check-colors", { set-window-size: (851, 600) // Check the size and count in tabs -assert-text: ("#search-tabs > button:nth-child(1) > .count", " (26) ") +assert-text: ("#search-tabs > button:nth-child(1) > .count", " (27) ") assert-text: ("#search-tabs > button:nth-child(2) > .count", " (7) ") assert-text: ("#search-tabs > button:nth-child(3) > .count", " (0) ") store-property: ("#search-tabs > button:nth-child(1)", {"offsetWidth": buttonWidth}) diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs index dae13d9ac18..1a9ffbe8898 100644 --- a/tests/rustdoc-gui/src/test_docs/lib.rs +++ b/tests/rustdoc-gui/src/test_docs/lib.rs @@ -691,3 +691,25 @@ impl ImplDoc { impl ImplDoc { pub fn bar5() {} } + +pub trait ItemsTrait { + /// You want doc, here is doc! + /// + /// blablala + type F; + + /// You want doc, here is doc! + /// + /// blablala + const X: u32; + + /// You want doc, here is doc! + /// + /// blablala + fn foo() {} + + /// You want doc, here is doc! + /// + /// blablala + fn bar(); +} diff --git a/tests/rustdoc-gui/toggle-docs-mobile.goml b/tests/rustdoc-gui/toggle-docs-mobile.goml index be12e4c19b3..6a40ba83b84 100644 --- a/tests/rustdoc-gui/toggle-docs-mobile.goml +++ b/tests/rustdoc-gui/toggle-docs-mobile.goml @@ -31,3 +31,29 @@ assert-attribute: (".top-doc", {"open": ""}) // To ensure that the toggle isn't over the text, we check that the toggle isn't clicked. click: (3, 270) assert-attribute: (".top-doc", {"open": ""}) + +// Same check on trait items. +fail-on-request-error: false // To prevent downloads errors on "trait.impl/test_docs/trait.ItemsTrait.js" +go-to: "file://" + |DOC_PATH| + "/test_docs/trait.ItemsTrait.html" + +define-function: ( + "check-trait-item", + [nth, text], + block { + store-value: (selector, ".methods:nth-of-type(" + |nth| + ") > details summary") + assert-text: (|selector| + " h4", |text|) + assert-position: ( + |selector| + "::before", + {"x": 6}, + ) + }, +) + +// Assert the position of the toggle on an associated const. +call-function: ("check-trait-item", {"nth": 2, "text": "const X: u32"}) +// Assert the position of the toggle on an associated type. +call-function: ("check-trait-item", {"nth": 3, "text": "type F"}) +// Assert the position of the toggle on an associated required method. +call-function: ("check-trait-item", {"nth": 4, "text": "fn bar()"}) +// Assert the position of the toggle on an associated provided method. +call-function: ("check-trait-item", {"nth": 5, "text": "fn foo()"}) diff --git a/tests/rustdoc-json/auxiliary/defines_and_reexports.rs b/tests/rustdoc-json/auxiliary/defines_and_reexports.rs new file mode 100644 index 00000000000..72434ef152f --- /dev/null +++ b/tests/rustdoc-json/auxiliary/defines_and_reexports.rs @@ -0,0 +1,10 @@ +pub mod m1 { + pub struct InPubMod; +} + +mod m2 { + pub struct InPrivMod; +} + +pub use m1::{InPubMod, InPubMod as InPubMod2}; +pub use m2::{InPrivMod, InPrivMod as InPrivMod2}; diff --git a/tests/rustdoc-json/blanket_impls.rs b/tests/rustdoc-json/blanket_impls.rs index f2acabbe372..bf0983e66a1 100644 --- a/tests/rustdoc-json/blanket_impls.rs +++ b/tests/rustdoc-json/blanket_impls.rs @@ -4,5 +4,5 @@ //@ has "$.index[*][?(@.name=='Error')].inner.assoc_type" //@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path" -//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.name" \"Infallible\" +//@ has "$.index[*][?(@.name=='Error')].inner.assoc_type.type.resolved_path.path" \"Infallible\" pub struct ForBlanketTryFromImpl; diff --git a/tests/rustdoc-json/fns/async_return.rs b/tests/rustdoc-json/fns/async_return.rs index 18a8a586e76..ff88fa99c61 100644 --- a/tests/rustdoc-json/fns/async_return.rs +++ b/tests/rustdoc-json/fns/async_return.rs @@ -17,7 +17,7 @@ pub async fn get_int_async() -> i32 { 42 } -//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"' +//@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"' //@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' //@ is "$.index[*][?(@.name=='get_int_future')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" //@ is "$.index[*][?(@.name=='get_int_future')].inner.function.header.is_async" false @@ -25,7 +25,7 @@ pub fn get_int_future() -> impl Future<Output = i32> { async { 42 } } -//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.name" '"Future"' +//@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.path" '"Future"' //@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name" '"Output"' //@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.sig.output.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive" \"i32\" //@ is "$.index[*][?(@.name=='get_int_future_async')].inner.function.header.is_async" true diff --git a/tests/rustdoc-json/impl-trait-in-assoc-type.rs b/tests/rustdoc-json/impl-trait-in-assoc-type.rs index 907a0f6c603..14ea2950769 100644 --- a/tests/rustdoc-json/impl-trait-in-assoc-type.rs +++ b/tests/rustdoc-json/impl-trait-in-assoc-type.rs @@ -10,7 +10,7 @@ impl IntoIterator for AlwaysTrue { type Item = bool; //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[*]' 1 - //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.name' '"Iterator"' + //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.path' '"Iterator"' //@ count '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[*]' 1 //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].name' '"Item"' //@ is '$.index[*][?(@.docs=="type IntoIter")].inner.assoc_type.type.impl_trait[0].trait_bound.trait.args.angle_bracketed.constraints[0].binding.equality.type.primitive' '"bool"' diff --git a/tests/rustdoc-json/path_name.rs b/tests/rustdoc-json/path_name.rs new file mode 100644 index 00000000000..67843dfc8ff --- /dev/null +++ b/tests/rustdoc-json/path_name.rs @@ -0,0 +1,83 @@ +// Test for the Path::name field within a single crate. +// +// See https://github.com/rust-lang/rust/issues/135600 +// and https://github.com/rust-lang/rust/pull/134880#issuecomment-2596386111 +// +// ignore-tidy-linelength +//@ aux-build: defines_and_reexports.rs +extern crate defines_and_reexports; + +mod priv_mod { + pub struct InPrivMod; +} + +pub mod pub_mod { + pub struct InPubMod; +} + +use priv_mod::InPrivMod as InPrivMod3; +pub use priv_mod::{InPrivMod, InPrivMod as InPrivMod2}; +use pub_mod::InPubMod as InPubMod3; +pub use pub_mod::{InPubMod, InPubMod as InPubMod2}; + +//@ is "$.index[*][?(@.name=='T0')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"' +pub type T0 = priv_mod::InPrivMod; +//@ is "$.index[*][?(@.name=='T1')].inner.type_alias.type.resolved_path.path" '"InPrivMod"' +pub type T1 = InPrivMod; +//@ is "$.index[*][?(@.name=='T2')].inner.type_alias.type.resolved_path.path" '"InPrivMod2"' +pub type T2 = InPrivMod2; +//@ is "$.index[*][?(@.name=='T3')].inner.type_alias.type.resolved_path.path" '"priv_mod::InPrivMod"' +pub type T3 = InPrivMod3; + +//@ is "$.index[*][?(@.name=='U0')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"' +pub type U0 = pub_mod::InPubMod; +//@ is "$.index[*][?(@.name=='U1')].inner.type_alias.type.resolved_path.path" '"InPubMod"' +pub type U1 = InPubMod; +//@ is "$.index[*][?(@.name=='U2')].inner.type_alias.type.resolved_path.path" '"InPubMod2"' +pub type U2 = InPubMod2; +//@ is "$.index[*][?(@.name=='U3')].inner.type_alias.type.resolved_path.path" '"pub_mod::InPubMod"' +pub type U3 = InPubMod3; + +// Check we only have paths for structs at their original path +//@ ismany "$.paths[*][?(@.crate_id==0 && @.kind=='struct')].path" '["path_name", "priv_mod", "InPrivMod"]' '["path_name", "pub_mod", "InPubMod"]' + +pub use defines_and_reexports::{InPrivMod as XPrivMod, InPubMod as XPubMod}; +use defines_and_reexports::{InPrivMod as XPrivMod2, InPubMod as XPubMod2}; + +//@ is "$.index[*][?(@.name=='X0')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::m1::InPubMod"' +pub type X0 = defines_and_reexports::m1::InPubMod; +//@ is "$.index[*][?(@.name=='X1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"' +pub type X1 = defines_and_reexports::InPubMod; +//@ is "$.index[*][?(@.name=='X2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod2"' +pub type X2 = defines_and_reexports::InPubMod2; +//@ is "$.index[*][?(@.name=='X3')].inner.type_alias.type.resolved_path.path" '"XPubMod"' +pub type X3 = XPubMod; +// N.B. This isn't the path as used *or* the original path! +//@ is "$.index[*][?(@.name=='X4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPubMod"' +pub type X4 = XPubMod2; + +//@ is "$.index[*][?(@.name=='Y1')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"' +pub type Y1 = defines_and_reexports::InPrivMod; +//@ is "$.index[*][?(@.name=='Y2')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod2"' +pub type Y2 = defines_and_reexports::InPrivMod2; +//@ is "$.index[*][?(@.name=='Y3')].inner.type_alias.type.resolved_path.path" '"XPrivMod"' +pub type Y3 = XPrivMod; +//@ is "$.index[*][?(@.name=='Y4')].inner.type_alias.type.resolved_path.path" '"defines_and_reexports::InPrivMod"' +pub type Y4 = XPrivMod2; + +// For foreign items, $.paths contains the *origional* path, even if it's not publicly +// assessable. This should probably be changed. + +//@ has "$.paths[*].path" '["defines_and_reexports", "m1", "InPubMod"]' +//@ has "$.paths[*].path" '["defines_and_reexports", "m2", "InPrivMod"]' +//@ !has "$.paths[*].path" '["defines_and_reexports", "InPubMod"]' +//@ !has "$.paths[*].path" '["defines_and_reexports", "InPrivMod"]' + +// Tests for the example in the docs of Path::name. +// If these change, chage the docs. +//@ is "$.index[*][?(@.name=='Vec1')].inner.type_alias.type.resolved_path.path" '"std::vec::Vec"' +pub type Vec1 = std::vec::Vec<i32>; +//@ is "$.index[*][?(@.name=='Vec2')].inner.type_alias.type.resolved_path.path" '"Vec"' +pub type Vec2 = Vec<i32>; +//@ is "$.index[*][?(@.name=='Vec3')].inner.type_alias.type.resolved_path.path" '"std::prelude::v1::Vec"' +pub type Vec3 = std::prelude::v1::Vec<i32>; diff --git a/tests/rustdoc-json/return_private.rs b/tests/rustdoc-json/return_private.rs index c238a536e0d..bfcbed89040 100644 --- a/tests/rustdoc-json/return_private.rs +++ b/tests/rustdoc-json/return_private.rs @@ -2,11 +2,13 @@ // ignore-tidy-linelength mod secret { + //@ set struct_secret = "$.index[*][?(@.name == 'Secret' && @.inner.struct)].id" pub struct Secret; } //@ has "$.index[*][?(@.name=='get_secret')].inner.function" -//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.name" \"Secret\" +//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.path" '"secret::Secret"' +//@ is "$.index[*][?(@.name=='get_secret')].inner.function.sig.output.resolved_path.id" $struct_secret pub fn get_secret() -> secret::Secret { secret::Secret } diff --git a/tests/rustdoc-json/type/dyn.rs b/tests/rustdoc-json/type/dyn.rs index 97c8689a7c8..f990a2cb53a 100644 --- a/tests/rustdoc-json/type/dyn.rs +++ b/tests/rustdoc-json/type/dyn.rs @@ -10,7 +10,7 @@ use std::fmt::Debug; //@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias" //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.generics" '{"params": [], "where_predicates": []}' //@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path" -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.name" \"Box\" +//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.path" \"Box\" //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] //@ count "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args" 1 //@ has "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait" @@ -19,9 +19,9 @@ use std::fmt::Debug; //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].generic_params" [] //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].generic_params" [] //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].generic_params" [] -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Fn"' -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Send"' -//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.name" '"Sync"' +//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Fn"' +//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Send"' +//@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[2].trait.path" '"Sync"' //@ is "$.index[*][?(@.name=='SyncIntGen')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.args" '{"parenthesized": {"inputs": [],"output": {"primitive": "i32"}}}' pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>; @@ -34,13 +34,13 @@ pub type SyncIntGen = Box<dyn Fn() -> i32 + Send + Sync + 'static>; //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.lifetime" null //@ count "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[*]" 1 //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"' +//@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"' //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref" //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.inputs[0].borrowed_ref.lifetime" "\"'b\"" //@ has "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref" //@ is "$.index[*][?(@.name=='RefFn')].inner.type_alias.type.borrowed_ref.type.dyn_trait.traits[0].trait.args.parenthesized.output.borrowed_ref.lifetime" "\"'b\"" pub type RefFn<'a> = &'a dyn for<'b> Fn(&'b i32) -> &'b i32; -//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.name" '"Send"' -//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.name" '"Debug"' +//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[0].trait.path" '"Send"' +//@ is "$.index[*][?(@.name=='WeirdOrder')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.dyn_trait.traits[1].trait.path" '"Debug"' pub type WeirdOrder = Box<dyn Send + Debug>; diff --git a/tests/rustdoc-json/type/generic_default.rs b/tests/rustdoc-json/type/generic_default.rs index c1a05805014..7eaa299af5c 100644 --- a/tests/rustdoc-json/type/generic_default.rs +++ b/tests/rustdoc-json/type/generic_default.rs @@ -21,10 +21,10 @@ pub struct MyError {} //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[0].kind.type.default" null //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path" //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.id" $my_error -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.name" \"MyError\" +//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.generics.params[1].kind.type.default.resolved_path.path" \"MyError\" //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path" //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.id" $result -//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.name" \"Result\" +//@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.path" \"Result\" //@ is "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.constraints" [] //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[0].type.generic" //@ has "$.index[*][?(@.name=='MyResult')].inner.type_alias.type.resolved_path.args.angle_bracketed.args[1].type.generic" diff --git a/tests/rustdoc-json/type/hrtb.rs b/tests/rustdoc-json/type/hrtb.rs index 825720e9198..e71d9fc1e1e 100644 --- a/tests/rustdoc-json/type/hrtb.rs +++ b/tests/rustdoc-json/type/hrtb.rs @@ -15,7 +15,7 @@ where //@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.lifetime" null //@ count "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[*]" 1 //@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].generic_params" '[{"kind": {"lifetime": {"outlives": []}},"name": "'\''a"},{"kind": {"lifetime": {"outlives": []}},"name": "'\''b"}]' -//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.name" '"Fn"' +//@ is "$.index[*][?(@.name=='dynfn')].inner.function.sig.inputs[0][1].borrowed_ref.type.dyn_trait.traits[0].trait.path" '"Fn"' pub fn dynfn(f: &dyn for<'a, 'b> Fn(&'a i32, &'b i32)) { let zero = 0; f(&zero, &zero); diff --git a/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs index 571bc94e30f..db2ccefb0fb 100644 --- a/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs +++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.rs @@ -1,4 +1,5 @@ //@ compile-flags:--test +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ check-pass #![allow(rustdoc::invalid_codeblock_attributes)] diff --git a/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout index e5c27bebbdb..7326c0a25a0 100644 --- a/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout +++ b/tests/rustdoc-ui/doctest/doctest-no-run-invalid-langstring-124577.stdout @@ -1,5 +1,5 @@ running 0 tests -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/ice-unresolved-import-100241.stderr b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr index 2eebedba9a5..a82847d381c 100644 --- a/tests/rustdoc-ui/ice-unresolved-import-100241.stderr +++ b/tests/rustdoc-ui/ice-unresolved-import-100241.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `inner` --> $DIR/ice-unresolved-import-100241.rs:9:13 | LL | pub use inner::S; - | ^^^^^ you might be missing crate `inner` + | ^^^^^ use of unresolved module or unlinked crate `inner` | -help: consider importing the `inner` crate +help: you might be missing a crate named `inner`, add it to your project and import it in your code | LL + extern crate inner; | diff --git a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr index e6894319213..dcdd230c25a 100644 --- a/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr +++ b/tests/rustdoc-ui/intra-doc/unresolved-import-recovery.stderr @@ -1,10 +1,10 @@ -error[E0433]: failed to resolve: you might be missing crate `unresolved_crate` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `unresolved_crate` --> $DIR/unresolved-import-recovery.rs:3:5 | LL | use unresolved_crate::module::Name; - | ^^^^^^^^^^^^^^^^ you might be missing crate `unresolved_crate` + | ^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `unresolved_crate` | -help: consider importing the `unresolved_crate` crate +help: you might be missing a crate named `unresolved_crate`, add it to your project and import it in your code | LL + extern crate unresolved_crate; | diff --git a/tests/rustdoc-ui/invalid_const_in_lifetime_position.rs b/tests/rustdoc-ui/invalid_const_in_lifetime_position.rs index 07fc239a8f8..427c84679ba 100644 --- a/tests/rustdoc-ui/invalid_const_in_lifetime_position.rs +++ b/tests/rustdoc-ui/invalid_const_in_lifetime_position.rs @@ -8,4 +8,4 @@ fn f<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} //~| ERROR associated type takes 0 generic arguments but 1 generic argument //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments //~| ERROR associated type takes 0 generic arguments but 1 generic argument -//~| ERROR trait `X` cannot be made into an object +//~| ERROR trait `X` is not dyn compatible diff --git a/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr b/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr index 0c3826c5665..180ba63927b 100644 --- a/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr +++ b/tests/rustdoc-ui/invalid_const_in_lifetime_position.stderr @@ -92,17 +92,18 @@ LL | type Y<'a>; | ^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/invalid_const_in_lifetime_position.rs:4:20 | LL | fn f<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/invalid_const_in_lifetime_position.rs:2:10 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait diff --git a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.rs b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.rs index 027574923c7..89b55beaea1 100644 --- a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.rs +++ b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.rs @@ -5,8 +5,8 @@ use std::ops::Index; pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { //~^ expected 1 lifetime argument //~| expected 1 generic argument - //~| the trait `SVec` cannot be made into an object - //~| `SVec` cannot be made into an object + //~| the trait `SVec` is not dyn compatible + //~| `SVec` is not dyn compatible //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` let _ = s; diff --git a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr index f9080bf0785..72d1a52f710 100644 --- a/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr +++ b/tests/rustdoc-ui/issues/ice-generic-type-alias-105742.stderr @@ -294,19 +294,20 @@ help: add missing generic argument LL | Output = <Self as SVec>::Item> as SVec>::Item<T>, | +++ -error[E0038]: the trait `SVec` cannot be made into an object - --> $DIR/ice-generic-type-alias-105742.rs:5:31 +error[E0038]: the trait `SVec` is not dyn compatible + --> $DIR/ice-generic-type-alias-105742.rs:5:35 | LL | pub fn next<'a, T>(s: &'a mut dyn SVec<Item = T, Output = T>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SVec` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `SVec` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/ice-generic-type-alias-105742.rs:15:17 | LL | pub trait SVec: Index< | ____________----__^ | | | - | | this trait cannot be made into an object... + | | this trait is not dyn compatible... LL | | <Self as SVec>::Item, ... | LL | |/ Output = <Index<<Self as SVec>::Item, diff --git a/tests/rustdoc-ui/issues/issue-61732.rs b/tests/rustdoc-ui/issues/issue-61732.rs index 3969ab92c32..d5d9ad5e463 100644 --- a/tests/rustdoc-ui/issues/issue-61732.rs +++ b/tests/rustdoc-ui/issues/issue-61732.rs @@ -1,4 +1,4 @@ // This previously triggered an ICE. pub(in crate::r#mod) fn main() {} -//~^ ERROR failed to resolve: you might be missing crate `r#mod` +//~^ ERROR failed to resolve: use of unresolved module or unlinked crate `r#mod` diff --git a/tests/rustdoc-ui/issues/issue-61732.stderr b/tests/rustdoc-ui/issues/issue-61732.stderr index 0aa7d558c30..c4e6997ab74 100644 --- a/tests/rustdoc-ui/issues/issue-61732.stderr +++ b/tests/rustdoc-ui/issues/issue-61732.stderr @@ -1,10 +1,10 @@ -error[E0433]: failed to resolve: you might be missing crate `r#mod` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `r#mod` --> $DIR/issue-61732.rs:3:15 | LL | pub(in crate::r#mod) fn main() {} - | ^^^^^ you might be missing crate `r#mod` + | ^^^^^ use of unresolved module or unlinked crate `r#mod` | -help: consider importing the `r#mod` crate +help: you might be missing a crate named `r#mod`, add it to your project and import it in your code | LL + extern crate r#mod; | diff --git a/tests/rustdoc/sidebar/sidebar-items.rs b/tests/rustdoc/sidebar/sidebar-items.rs index 57c2eee91a9..6e13457796e 100644 --- a/tests/rustdoc/sidebar/sidebar-items.rs +++ b/tests/rustdoc/sidebar/sidebar-items.rs @@ -26,7 +26,7 @@ pub trait Foo { } //@ has foo/trait.DynCompatible.html -//@ !has - '//div[@class="sidebar-elems"]//h3/a[@href="#object-safety"]' '' +//@ !has - '//div[@class="sidebar-elems"]//h3/a[@href="#dyn-compatibility"]' '' pub trait DynCompatible { fn access(&self); } diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs index 1e462210cba..5f34c8b99e0 100644 --- a/tests/rustdoc/type-layout.rs +++ b/tests/rustdoc/type-layout.rs @@ -37,7 +37,8 @@ pub struct Y(u8); pub struct Z; // We can't compute layout for generic types. -//@ hasraw type_layout/struct.Generic.html 'Unable to compute type layout, possibly due to this type having generic parameters' +//@ hasraw type_layout/struct.Generic.html 'Unable to compute type layout, possibly due to this type having generic parameters.' +//@ hasraw type_layout/struct.Generic.html 'Layout can only be computed for concrete, fully-instantiated types.' //@ !hasraw - 'Size: ' pub struct Generic<T>(T); @@ -91,3 +92,9 @@ pub enum Uninhabited {} //@ hasraw type_layout/struct.Uninhabited2.html 'Size: ' //@ hasraw - '8 bytes (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)' pub struct Uninhabited2(std::convert::Infallible, u64); + +pub trait Project { type Assoc; } +// We can't compute layout. A `LayoutError::Unknown` is returned. +//@ hasraw type_layout/struct.Unknown.html 'Unable to compute type layout.' +//@ !hasraw - 'Size: ' +pub struct Unknown(<() as Project>::Assoc) where for<'a> (): Project; diff --git a/tests/ui-fulldeps/compiler-calls.rs b/tests/ui-fulldeps/compiler-calls.rs index 5fb47c87e50..d6148dfec43 100644 --- a/tests/ui-fulldeps/compiler-calls.rs +++ b/tests/ui-fulldeps/compiler-calls.rs @@ -25,7 +25,7 @@ fn main() { let mut count = 1; let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; rustc_driver::catch_fatal_errors(|| -> interface::Result<()> { - rustc_driver::RunCompiler::new(&args, &mut TestCalls { count: &mut count }).run(); + rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count }); Ok(()) }) .ok(); diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs index 8ea2ac61971..f8064c245a8 100644 --- a/tests/ui-fulldeps/obtain-borrowck.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -47,7 +47,7 @@ fn main() { rustc_args.push("-Zpolonius".to_owned()); let mut callbacks = CompilerCalls::default(); // Call the Rust compiler with our callbacks. - rustc_driver::RunCompiler::new(&rustc_args, &mut callbacks).run(); + rustc_driver::run_compiler(&rustc_args, &mut callbacks); Ok(()) }); std::process::exit(exit_code); diff --git a/tests/ui-fulldeps/run-compiler-twice.rs b/tests/ui-fulldeps/run-compiler-twice.rs index bcc235e58ed..f414c961627 100644 --- a/tests/ui-fulldeps/run-compiler-twice.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -72,7 +72,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path override_queries: None, make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), - using_internal_features: std::sync::Arc::default(), + using_internal_features: &rustc_driver::USING_INTERNAL_FEATURES, expanded_args: Default::default(), }; diff --git a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs index 4afb710b193..22b9b029a40 100644 --- a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs +++ b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs @@ -5,8 +5,7 @@ // without #[repr(simd)] //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess #![feature(avx512_target_feature)] diff --git a/tests/ui/abi/segfault-no-out-of-stack.rs b/tests/ui/abi/segfault-no-out-of-stack.rs index 113c82c30e9..b5af13ebfb5 100644 --- a/tests/ui/abi/segfault-no-out-of-stack.rs +++ b/tests/ui/abi/segfault-no-out-of-stack.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 can't run commands -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia must translate zircon signal to SIGSEGV/SIGBUS, FIXME (#58590) #![feature(rustc_private)] diff --git a/tests/ui/abi/sparcv8plus-llvm19.rs b/tests/ui/abi/sparcv8plus-llvm19.rs new file mode 100644 index 00000000000..a884e5ca06f --- /dev/null +++ b/tests/ui/abi/sparcv8plus-llvm19.rs @@ -0,0 +1,43 @@ +//@ revisions: sparc sparcv8plus sparc_cpu_v9 sparc_feature_v8plus sparc_cpu_v9_feature_v8plus +//@[sparc] compile-flags: --target sparc-unknown-none-elf +//@[sparc] needs-llvm-components: sparc +//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu +//@[sparcv8plus] needs-llvm-components: sparc +//@[sparc_cpu_v9] compile-flags: --target sparc-unknown-none-elf -C target-cpu=v9 +//@[sparc_cpu_v9] needs-llvm-components: sparc +//@[sparc_feature_v8plus] compile-flags: --target sparc-unknown-none-elf -C target-feature=+v8plus +//@[sparc_feature_v8plus] needs-llvm-components: sparc +//@[sparc_cpu_v9_feature_v8plus] compile-flags: --target sparc-unknown-none-elf -C target-cpu=v9 -C target-feature=+v8plus +//@[sparc_cpu_v9_feature_v8plus] needs-llvm-components: sparc +//@ exact-llvm-major-version: 19 + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[rustc_builtin_macro] +macro_rules! compile_error { + () => {}; +} + +#[cfg(all(not(target_feature = "v8plus"), not(target_feature = "v9")))] +compile_error!("-v8plus,-v9"); +//[sparc]~^ ERROR -v8plus,-v9 + +// FIXME: sparc_cpu_v9 should be in "-v8plus,+v9" group (fixed in LLVM 20) +#[cfg(all(target_feature = "v8plus", target_feature = "v9"))] +compile_error!("+v8plus,+v9"); +//[sparcv8plus,sparc_cpu_v9_feature_v8plus,sparc_cpu_v9]~^ ERROR +v8plus,+v9 + +// FIXME: should be rejected +#[cfg(all(target_feature = "v8plus", not(target_feature = "v9")))] +compile_error!("+v8plus,-v9 (FIXME)"); +//[sparc_feature_v8plus]~^ ERROR +v8plus,-v9 (FIXME) + +#[cfg(all(not(target_feature = "v8plus"), target_feature = "v9"))] +compile_error!("-v8plus,+v9"); diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparc.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparc.stderr new file mode 100644 index 00000000000..7eedf26135f --- /dev/null +++ b/tests/ui/abi/sparcv8plus-llvm19.sparc.stderr @@ -0,0 +1,8 @@ +error: -v8plus,-v9 + --> $DIR/sparcv8plus-llvm19.rs:29:1 + | +LL | compile_error!("-v8plus,-v9"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9.stderr new file mode 100644 index 00000000000..ac61df35678 --- /dev/null +++ b/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9.stderr @@ -0,0 +1,8 @@ +error: +v8plus,+v9 + --> $DIR/sparcv8plus-llvm19.rs:34:1 + | +LL | compile_error!("+v8plus,+v9"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9_feature_v8plus.stderr new file mode 100644 index 00000000000..ac61df35678 --- /dev/null +++ b/tests/ui/abi/sparcv8plus-llvm19.sparc_cpu_v9_feature_v8plus.stderr @@ -0,0 +1,8 @@ +error: +v8plus,+v9 + --> $DIR/sparcv8plus-llvm19.rs:34:1 + | +LL | compile_error!("+v8plus,+v9"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparc_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparc_feature_v8plus.stderr new file mode 100644 index 00000000000..1bf7a3ad76a --- /dev/null +++ b/tests/ui/abi/sparcv8plus-llvm19.sparc_feature_v8plus.stderr @@ -0,0 +1,8 @@ +error: +v8plus,-v9 (FIXME) + --> $DIR/sparcv8plus-llvm19.rs:39:1 + | +LL | compile_error!("+v8plus,-v9 (FIXME)"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus-llvm19.sparcv8plus.stderr b/tests/ui/abi/sparcv8plus-llvm19.sparcv8plus.stderr new file mode 100644 index 00000000000..ac61df35678 --- /dev/null +++ b/tests/ui/abi/sparcv8plus-llvm19.sparcv8plus.stderr @@ -0,0 +1,8 @@ +error: +v8plus,+v9 + --> $DIR/sparcv8plus-llvm19.rs:34:1 + | +LL | compile_error!("+v8plus,+v9"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus.rs b/tests/ui/abi/sparcv8plus.rs index 108279b3494..a78ae0cd328 100644 --- a/tests/ui/abi/sparcv8plus.rs +++ b/tests/ui/abi/sparcv8plus.rs @@ -9,7 +9,7 @@ //@[sparc_feature_v8plus] needs-llvm-components: sparc //@[sparc_cpu_v9_feature_v8plus] compile-flags: --target sparc-unknown-none-elf -C target-cpu=v9 -C target-feature=+v8plus //@[sparc_cpu_v9_feature_v8plus] needs-llvm-components: sparc -//@ min-llvm-version: 19 +//@ min-llvm-version: 20 #![crate_type = "rlib"] #![feature(no_core, rustc_attrs, lang_items)] @@ -29,10 +29,9 @@ macro_rules! compile_error { compile_error!("-v8plus,-v9"); //[sparc]~^ ERROR -v8plus,-v9 -// FIXME: sparc_cpu_v9 should be in "-v8plus,+v9" group (fixed in LLVM 20) #[cfg(all(target_feature = "v8plus", target_feature = "v9"))] compile_error!("+v8plus,+v9"); -//[sparcv8plus,sparc_cpu_v9_feature_v8plus,sparc_cpu_v9]~^ ERROR +v8plus,+v9 +//[sparcv8plus,sparc_cpu_v9_feature_v8plus]~^ ERROR +v8plus,+v9 // FIXME: should be rejected #[cfg(all(target_feature = "v8plus", not(target_feature = "v9")))] @@ -41,3 +40,4 @@ compile_error!("+v8plus,-v9 (FIXME)"); #[cfg(all(not(target_feature = "v8plus"), target_feature = "v9"))] compile_error!("-v8plus,+v9"); +//[sparc_cpu_v9]~^ ERROR -v8plus,+v9 diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr index 5e1e1fa5c79..00fd7ef4ea8 100644 --- a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr @@ -1,7 +1,7 @@ -error: +v8plus,+v9 - --> $DIR/sparcv8plus.rs:34:1 +error: -v8plus,+v9 + --> $DIR/sparcv8plus.rs:42:1 | -LL | compile_error!("+v8plus,+v9"); +LL | compile_error!("-v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr index 5e1e1fa5c79..a3c74e67f8f 100644 --- a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr @@ -1,5 +1,5 @@ error: +v8plus,+v9 - --> $DIR/sparcv8plus.rs:34:1 + --> $DIR/sparcv8plus.rs:33:1 | LL | compile_error!("+v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr index 8a5375a46bc..84f560d158c 100644 --- a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr @@ -1,5 +1,5 @@ error: +v8plus,-v9 (FIXME) - --> $DIR/sparcv8plus.rs:39:1 + --> $DIR/sparcv8plus.rs:38:1 | LL | compile_error!("+v8plus,-v9 (FIXME)"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr index 5e1e1fa5c79..a3c74e67f8f 100644 --- a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr @@ -1,5 +1,5 @@ error: +v8plus,+v9 - --> $DIR/sparcv8plus.rs:34:1 + --> $DIR/sparcv8plus.rs:33:1 | LL | compile_error!("+v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/stack-probes-lto.rs b/tests/ui/abi/stack-probes-lto.rs index e6c26c5c4de..c6e5bea5f42 100644 --- a/tests/ui/abi/stack-probes-lto.rs +++ b/tests/ui/abi/stack-probes-lto.rs @@ -3,7 +3,7 @@ //@[aarch64] only-aarch64 //@[x32] only-x86 //@[x64] only-x86_64 -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-musl FIXME #31506 //@ ignore-fuchsia no exception handler registered for segfault //@ compile-flags: -C lto diff --git a/tests/ui/abi/stack-probes.rs b/tests/ui/abi/stack-probes.rs index 1c0e50250d7..f0fbd80d2e7 100644 --- a/tests/ui/abi/stack-probes.rs +++ b/tests/ui/abi/stack-probes.rs @@ -3,8 +3,7 @@ //@[aarch64] only-aarch64 //@[x32] only-x86 //@[x64] only-x86_64 -//@ ignore-emscripten no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia no exception handler registered for segfault //@ ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino //@ ignore-ios Stack probes are enabled, but the SIGSEGV handler isn't diff --git a/tests/ui/alloc-error/default-alloc-error-hook.rs b/tests/ui/alloc-error/default-alloc-error-hook.rs index 5f977460b8c..7fbc66ca5f4 100644 --- a/tests/ui/alloc-error/default-alloc-error-hook.rs +++ b/tests/ui/alloc-error/default-alloc-error-hook.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::alloc::{Layout, handle_alloc_error}; use std::env; diff --git a/tests/ui/array-slice-vec/bounds-check-no-overflow.rs b/tests/ui/array-slice-vec/bounds-check-no-overflow.rs index 4614df44084..c5ff805a853 100644 --- a/tests/ui/array-slice-vec/bounds-check-no-overflow.rs +++ b/tests/ui/array-slice-vec/bounds-check-no-overflow.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:index out of bounds -//@ ignore-emscripten no processes +//@ needs-subprocess use std::mem::size_of; diff --git a/tests/ui/array-slice-vec/box-of-array-of-drop-1.rs b/tests/ui/array-slice-vec/box-of-array-of-drop-1.rs index d64df4f7e4d..c7c05946c4c 100644 --- a/tests/ui/array-slice-vec/box-of-array-of-drop-1.rs +++ b/tests/ui/array-slice-vec/box-of-array-of-drop-1.rs @@ -1,12 +1,12 @@ //@ run-pass //@ needs-unwind +//@ needs-threads + #![allow(overflowing_literals)] // Test that we cleanup a fixed size Box<[D; k]> properly when D has a // destructor. -//@ ignore-emscripten no threads support - use std::thread; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/tests/ui/array-slice-vec/box-of-array-of-drop-2.rs b/tests/ui/array-slice-vec/box-of-array-of-drop-2.rs index 5ca3d60ad1d..98175a26ec0 100644 --- a/tests/ui/array-slice-vec/box-of-array-of-drop-2.rs +++ b/tests/ui/array-slice-vec/box-of-array-of-drop-2.rs @@ -1,12 +1,12 @@ //@ run-pass //@ needs-unwind +//@ needs-threads + #![allow(overflowing_literals)] // Test that we cleanup dynamic sized Box<[D]> properly when D has a // destructor. -//@ ignore-emscripten no threads support - use std::thread; use std::sync::atomic::{AtomicUsize, Ordering}; diff --git a/tests/ui/array-slice-vec/dst-raw-slice.rs b/tests/ui/array-slice-vec/dst-raw-slice.rs index f1281f4e302..ab9dedc139d 100644 --- a/tests/ui/array-slice-vec/dst-raw-slice.rs +++ b/tests/ui/array-slice-vec/dst-raw-slice.rs @@ -2,7 +2,7 @@ //@ run-fail //@ error-pattern:index out of bounds -//@ ignore-emscripten no processes +//@ needs-subprocess #[allow(unconditional_panic)] fn main() { diff --git a/tests/ui/array-slice-vec/nested-vec-3.rs b/tests/ui/array-slice-vec/nested-vec-3.rs index ce61401aab4..51975743742 100644 --- a/tests/ui/array-slice-vec/nested-vec-3.rs +++ b/tests/ui/array-slice-vec/nested-vec-3.rs @@ -1,8 +1,8 @@ //@ run-pass //@ needs-unwind -#![allow(overflowing_literals)] +//@ needs-threads -//@ ignore-emscripten no threads support +#![allow(overflowing_literals)] // Test that using the `vec!` macro nested within itself works when // the contents implement Drop and we hit a panic in the middle of diff --git a/tests/ui/array-slice-vec/slice-panic-1.rs b/tests/ui/array-slice-vec/slice-panic-1.rs index d4f584c1632..a745dff96af 100644 --- a/tests/ui/array-slice-vec/slice-panic-1.rs +++ b/tests/ui/array-slice-vec/slice-panic-1.rs @@ -1,7 +1,6 @@ //@ run-pass //@ needs-unwind - -//@ ignore-emscripten no threads support +//@ needs-threads // Test that if a slicing expr[..] fails, the correct cleanups happen. diff --git a/tests/ui/array-slice-vec/slice-panic-2.rs b/tests/ui/array-slice-vec/slice-panic-2.rs index b3d1dc45573..483a4cbe245 100644 --- a/tests/ui/array-slice-vec/slice-panic-2.rs +++ b/tests/ui/array-slice-vec/slice-panic-2.rs @@ -1,7 +1,6 @@ //@ run-pass //@ needs-unwind - -//@ ignore-emscripten no threads support +//@ needs-threads // Test that if a slicing expr[..] fails, the correct cleanups happen. diff --git a/tests/ui/array-slice-vec/vec-macro-no-std.rs b/tests/ui/array-slice-vec/vec-macro-no-std.rs index 1b5ab536dcb..ea0df0bea71 100644 --- a/tests/ui/array-slice-vec/vec-macro-no-std.rs +++ b/tests/ui/array-slice-vec/vec-macro-no-std.rs @@ -1,21 +1,21 @@ //@ run-pass - //@ ignore-emscripten no no_std executables +//@ ignore-wasm different `main` convention -#![feature(lang_items, start, rustc_private)] #![no_std] +#![no_main] +// Import global allocator and panic handler. extern crate std as other; -#[macro_use] -extern crate alloc; +#[macro_use] extern crate alloc; use alloc::vec::Vec; // Issue #16806 -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { let x: Vec<u8> = vec![0, 1, 2]; match x.last() { Some(&2) => (), diff --git a/tests/ui/array-slice-vec/vec-overrun.rs b/tests/ui/array-slice-vec/vec-overrun.rs index 10f8350869f..3b3e9215279 100644 --- a/tests/ui/array-slice-vec/vec-overrun.rs +++ b/tests/ui/array-slice-vec/vec-overrun.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:index out of bounds: the len is 1 but the index is 2 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let v: Vec<isize> = vec![10]; diff --git a/tests/ui/associated-consts/associated-const-in-trait.rs b/tests/ui/associated-consts/associated-const-in-trait.rs index 4e8143d5795..90ad596b23e 100644 --- a/tests/ui/associated-consts/associated-const-in-trait.rs +++ b/tests/ui/associated-consts/associated-const-in-trait.rs @@ -5,9 +5,9 @@ trait Trait { } impl dyn Trait { - //~^ ERROR the trait `Trait` cannot be made into an object [E0038] + //~^ ERROR the trait `Trait` is not dyn compatible [E0038] const fn n() -> usize { Self::N } - //~^ ERROR the trait `Trait` cannot be made into an object [E0038] + //~^ ERROR the trait `Trait` is not dyn compatible [E0038] } fn main() {} diff --git a/tests/ui/associated-consts/associated-const-in-trait.stderr b/tests/ui/associated-consts/associated-const-in-trait.stderr index b40c1005797..107ceeaf113 100644 --- a/tests/ui/associated-consts/associated-const-in-trait.stderr +++ b/tests/ui/associated-consts/associated-const-in-trait.stderr @@ -1,29 +1,31 @@ -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/associated-const-in-trait.rs:7:6 | LL | impl dyn Trait { - | ^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/associated-const-in-trait.rs:4:11 | LL | trait Trait { - | ----- this trait cannot be made into an object... + | ----- this trait is not dyn compatible... LL | const N: usize; | ^ ...because it contains this associated `const` = help: consider moving `N` to another trait -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/associated-const-in-trait.rs:9:29 | LL | const fn n() -> usize { Self::N } - | ^^^^ `Trait` cannot be made into an object + | ^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/associated-const-in-trait.rs:4:11 | LL | trait Trait { - | ----- this trait cannot be made into an object... + | ----- this trait is not dyn compatible... LL | const N: usize; | ^ ...because it contains this associated `const` = help: consider moving `N` to another trait diff --git a/tests/ui/associated-item/issue-48027.rs b/tests/ui/associated-item/issue-48027.rs index d2b51184c99..715f3935107 100644 --- a/tests/ui/associated-item/issue-48027.rs +++ b/tests/ui/associated-item/issue-48027.rs @@ -3,6 +3,6 @@ trait Bar { fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: E0790 } -impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object +impl dyn Bar {} //~ ERROR: the trait `Bar` is not dyn compatible fn main() {} diff --git a/tests/ui/associated-item/issue-48027.stderr b/tests/ui/associated-item/issue-48027.stderr index 2883259ce2f..1baaefd7720 100644 --- a/tests/ui/associated-item/issue-48027.stderr +++ b/tests/ui/associated-item/issue-48027.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/issue-48027.rs:6:6 | LL | impl dyn Bar {} - | ^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-48027.rs:2:11 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr deleted file mode 100644 index 26b4d935ac7..00000000000 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.current.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/equality.rs:5:12 - | -LL | #![feature(return_type_notation)] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: return type notation is not allowed to use type equality - --> $DIR/equality.rs:14:18 - | -LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error; 1 warning emitted - diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr deleted file mode 100644 index 26b4d935ac7..00000000000 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.next.stderr +++ /dev/null @@ -1,17 +0,0 @@ -warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/equality.rs:5:12 - | -LL | #![feature(return_type_notation)] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information - = note: `#[warn(incomplete_features)]` on by default - -error: return type notation is not allowed to use type equality - --> $DIR/equality.rs:14:18 - | -LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error; 1 warning emitted - diff --git a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr index c5260adbed4..88db3611719 100644 --- a/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr +++ b/tests/ui/associated-types/associated-types-in-ambiguous-context.stderr @@ -40,14 +40,14 @@ LL | type X = std::ops::Deref::Target; | help: use fully-qualified syntax | +LL | type X = <ByteStr as Deref>::Target; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL | type X = <ByteString as Deref>::Target; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | type X = <CString as Deref>::Target; | ~~~~~~~~~~~~~~~~~~~~~~~~~~ LL | type X = <IoSlice<'_> as Deref>::Target; | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LL | type X = <IoSliceMut<'_> as Deref>::Target; - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LL | type X = <OsString as Deref>::Target; - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ and N other candidates error: aborting due to 5 previous errors diff --git a/tests/ui/async-await/async-closures/is-not-fn.stderr b/tests/ui/async-await/async-closures/is-not-fn.current.stderr index bc1d5e6e9d1..e7be1d5b10e 100644 --- a/tests/ui/async-await/async-closures/is-not-fn.stderr +++ b/tests/ui/async-await/async-closures/is-not-fn.current.stderr @@ -1,5 +1,5 @@ -error[E0271]: expected `{async closure@is-not-fn.rs:5:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:5:23: 5:25}` - --> $DIR/is-not-fn.rs:5:14 +error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}` + --> $DIR/is-not-fn.rs:8:14 | LL | needs_fn(async || {}); | -------- ^^^^^^^^^^^ expected `()`, found `async` closure body @@ -7,9 +7,9 @@ LL | needs_fn(async || {}); | required by a bound introduced by this call | = note: expected unit type `()` - found `async` closure body `{async closure body@$DIR/is-not-fn.rs:5:23: 5:25}` + found `async` closure body `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}` note: required by a bound in `needs_fn` - --> $DIR/is-not-fn.rs:4:25 + --> $DIR/is-not-fn.rs:7:25 | LL | fn needs_fn(x: impl FnOnce()) {} | ^^^^^^^^ required by this bound in `needs_fn` diff --git a/tests/ui/async-await/async-closures/is-not-fn.next.stderr b/tests/ui/async-await/async-closures/is-not-fn.next.stderr new file mode 100644 index 00000000000..e7be1d5b10e --- /dev/null +++ b/tests/ui/async-await/async-closures/is-not-fn.next.stderr @@ -0,0 +1,19 @@ +error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}` + --> $DIR/is-not-fn.rs:8:14 + | +LL | needs_fn(async || {}); + | -------- ^^^^^^^^^^^ expected `()`, found `async` closure body + | | + | required by a bound introduced by this call + | + = note: expected unit type `()` + found `async` closure body `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}` +note: required by a bound in `needs_fn` + --> $DIR/is-not-fn.rs:7:25 + | +LL | fn needs_fn(x: impl FnOnce()) {} + | ^^^^^^^^ required by this bound in `needs_fn` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/async-await/async-closures/is-not-fn.rs b/tests/ui/async-await/async-closures/is-not-fn.rs index 4acaa5d9809..eacd07b7cdd 100644 --- a/tests/ui/async-await/async-closures/is-not-fn.rs +++ b/tests/ui/async-await/async-closures/is-not-fn.rs @@ -1,7 +1,10 @@ //@ edition:2021 +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver fn main() { fn needs_fn(x: impl FnOnce()) {} needs_fn(async || {}); - //~^ ERROR expected `{async closure@is-not-fn.rs:5:14}` to be a closure that returns `()` + //~^ ERROR expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()` } diff --git a/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang-2.rs b/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang-2.rs new file mode 100644 index 00000000000..4cdf4bf8def --- /dev/null +++ b/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang-2.rs @@ -0,0 +1,23 @@ +//@ edition: 2021 +//@ build-fail + +// Regression test for <https://github.com/rust-lang/rust/issues/135780>. + +use std::future::Future; +use std::ops::AsyncFn; +use std::pin::Pin; + +fn recur<'l>(closure: &'l impl AsyncFn()) -> Pin<Box<dyn Future<Output = ()> + 'l>> { + Box::pin(async move { + let _ = closure(); + let _ = recur(&async || { + //~^ ERROR reached the recursion limit + let _ = closure(); + }); + }) +} + +fn main() { + let closure = async || {}; + let _ = recur(&closure); +} diff --git a/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang-2.stderr b/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang-2.stderr new file mode 100644 index 00000000000..64f4665225f --- /dev/null +++ b/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang-2.stderr @@ -0,0 +1,18 @@ +error: reached the recursion limit while instantiating `recur::<{async closure@$DIR/post-mono-higher-ranked-hang-2.rs:13:24: 13:32}>` + --> $DIR/post-mono-higher-ranked-hang-2.rs:13:17 + | +LL | let _ = recur(&async || { + | _________________^ +LL | | +LL | | let _ = closure(); +LL | | }); + | |__________^ + | +note: `recur` defined here + --> $DIR/post-mono-higher-ranked-hang-2.rs:10:1 + | +LL | fn recur<'l>(closure: &'l impl AsyncFn()) -> Pin<Box<dyn Future<Output = ()> + 'l>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang.rs b/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang.rs new file mode 100644 index 00000000000..f6ebf787f81 --- /dev/null +++ b/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang.rs @@ -0,0 +1,63 @@ +//@ build-fail +//@ aux-build:block-on.rs +//@ edition:2021 + +// Regression test for <https://github.com/rust-lang/rust/issues/135780>. + +extern crate block_on; + +use std::future::Future; +use std::ops::AsyncFnMut; +use std::pin::{Pin, pin}; +use std::task::*; + +trait Db {} + +impl Db for () {} + +struct Env<'db> { + db: &'db (), +} + +#[derive(Debug)] +enum SymPerm<'db> { + Dummy(&'db ()), + Apply(Box<SymPerm<'db>>, Box<SymPerm<'db>>), +} + +pub struct ToChain<'env, 'db> { + db: &'db dyn crate::Db, + env: &'env Env<'db>, +} + +impl<'env, 'db> ToChain<'env, 'db> { + fn perm_pairs<'l>( + &'l self, + perm: &'l SymPerm<'db>, + yield_chain: &'l mut impl AsyncFnMut(&SymPerm<'db>), + ) -> Pin<Box<dyn std::future::Future<Output = ()> + 'l>> { + Box::pin(async move { + match perm { + SymPerm::Dummy(_) => yield_chain(perm).await, + SymPerm::Apply(l, r) => { + self.perm_pairs(l, &mut async move |left_pair| { + //~^ ERROR reached the recursion limit while instantiating + self.perm_pairs(r, yield_chain).await + }) + .await + } + } + }) + } +} + +fn main() { + block_on::block_on(async { + let pair = SymPerm::Apply(Box::new(SymPerm::Dummy(&())), Box::new(SymPerm::Dummy(&()))); + ToChain { db: &(), env: &Env { db: &() } } + .perm_pairs(&pair, &mut async |p| { + eprintln!("{p:?}"); + }) + .await; + }); +} diff --git a/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang.stderr b/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang.stderr new file mode 100644 index 00000000000..486e5f94165 --- /dev/null +++ b/tests/ui/async-await/async-closures/post-mono-higher-ranked-hang.stderr @@ -0,0 +1,21 @@ +error: reached the recursion limit while instantiating `ToChain::<'_, '_>::perm_pairs::<{async closure@$DIR/post-mono-higher-ranked-hang.rs:43:45: 43:67}>` + --> $DIR/post-mono-higher-ranked-hang.rs:43:21 + | +LL | / self.perm_pairs(l, &mut async move |left_pair| { +LL | | +LL | | self.perm_pairs(r, yield_chain).await +LL | | }) + | |______________________^ + | +note: `ToChain::<'env, 'db>::perm_pairs` defined here + --> $DIR/post-mono-higher-ranked-hang.rs:34:5 + | +LL | / fn perm_pairs<'l>( +LL | | &'l self, +LL | | perm: &'l SymPerm<'db>, +LL | | yield_chain: &'l mut impl AsyncFnMut(&SymPerm<'db>), +LL | | ) -> Pin<Box<dyn std::future::Future<Output = ()> + 'l>> { + | |____________________________________________________________^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/async-fn/dyn-pos.rs b/tests/ui/async-await/async-fn/dyn-pos.rs index d71af1bd53e..ab4685b07bb 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.rs +++ b/tests/ui/async-await/async-fn/dyn-pos.rs @@ -1,6 +1,6 @@ //@ edition:2018 fn foo(x: &dyn AsyncFn()) {} -//~^ ERROR the trait `AsyncFnMut` cannot be made into an object +//~^ ERROR the trait `AsyncFnMut` is not dyn compatible fn main() {} diff --git a/tests/ui/async-await/async-fn/dyn-pos.stderr b/tests/ui/async-await/async-fn/dyn-pos.stderr index 0c901846671..f9d2a669477 100644 --- a/tests/ui/async-await/async-fn/dyn-pos.stderr +++ b/tests/ui/async-await/async-fn/dyn-pos.stderr @@ -1,17 +1,14 @@ -error[E0038]: the trait `AsyncFnMut` cannot be made into an object +error[E0038]: the trait `AsyncFnMut` is not dyn compatible --> $DIR/dyn-pos.rs:3:16 | LL | fn foo(x: &dyn AsyncFn()) {} - | ^^^^^^^^^ `AsyncFnMut` cannot be made into an object + | ^^^^^^^^^ `AsyncFnMut` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $SRC_DIR/core/src/ops/async_function.rs:LL:COL | - = note: the trait cannot be made into an object because it contains the generic associated type `CallRefFuture` - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `AsyncFnMut` for this new enum and using it instead: - &F - &mut F - std::boxed::Box<F, A> + = note: the trait is not dyn compatible because it contains the generic associated type `CallRefFuture` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/coroutine-desc.stderr b/tests/ui/async-await/coroutine-desc.stderr index 01482a9cb1f..84a1a3166ad 100644 --- a/tests/ui/async-await/coroutine-desc.stderr +++ b/tests/ui/async-await/coroutine-desc.stderr @@ -30,7 +30,6 @@ LL | fun(one(), two()); | | expected all arguments to be this future type because they need to match the type of this parameter | arguments to this function are incorrect | - = help: consider `await`ing on both `Future`s = note: distinct uses of `impl Trait` result in different opaque types note: function defined here --> $DIR/coroutine-desc.rs:7:4 diff --git a/tests/ui/async-await/dont-suggest-missing-await.stderr b/tests/ui/async-await/dont-suggest-missing-await.stderr index 45a226c31f8..2ca52b2d5f5 100644 --- a/tests/ui/async-await/dont-suggest-missing-await.stderr +++ b/tests/ui/async-await/dont-suggest-missing-await.stderr @@ -6,20 +6,11 @@ LL | take_u32(x) | | | arguments to this function are incorrect | -note: calling an async function returns a future - --> $DIR/dont-suggest-missing-await.rs:14:18 - | -LL | take_u32(x) - | ^ note: function defined here --> $DIR/dont-suggest-missing-await.rs:5:4 | LL | fn take_u32(x: u32) {} | ^^^^^^^^ ------ -help: consider `await`ing on the `Future` - | -LL | take_u32(x.await) - | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/async-await/in-trait/dyn-compatibility.rs b/tests/ui/async-await/in-trait/dyn-compatibility.rs index 8174a803e79..c1b1ec79784 100644 --- a/tests/ui/async-await/in-trait/dyn-compatibility.rs +++ b/tests/ui/async-await/in-trait/dyn-compatibility.rs @@ -7,5 +7,5 @@ trait Foo { fn main() { let x: &dyn Foo = todo!(); - //~^ ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/async-await/in-trait/dyn-compatibility.stderr b/tests/ui/async-await/in-trait/dyn-compatibility.stderr index 5cc3b6800dd..c6c406902f6 100644 --- a/tests/ui/async-await/in-trait/dyn-compatibility.stderr +++ b/tests/ui/async-await/in-trait/dyn-compatibility.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility.rs:9:12 | LL | let x: &dyn Foo = todo!(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility.rs:5:14 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | async fn foo(&self); | ^^^ ...because method `foo` is `async` = help: consider moving `foo` to another trait diff --git a/tests/ui/async-await/inference_var_self_argument.rs b/tests/ui/async-await/inference_var_self_argument.rs index 4d5ac4abb19..d03f2b5c50b 100644 --- a/tests/ui/async-await/inference_var_self_argument.rs +++ b/tests/ui/async-await/inference_var_self_argument.rs @@ -3,7 +3,7 @@ trait Foo { async fn foo(self: &dyn Foo) { - //~^ ERROR: `Foo` cannot be made into an object + //~^ ERROR: `Foo` is not dyn compatible //~| ERROR invalid `self` parameter type: `&dyn Foo` todo!() } diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr index 7b7b3dbc757..a674fc0f3a5 100644 --- a/tests/ui/async-await/inference_var_self_argument.stderr +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -7,17 +7,18 @@ LL | async fn foo(self: &dyn Foo) { = note: type of `self` must be `Self` or a type that dereferences to it = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`) -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/inference_var_self_argument.rs:5:5 | LL | async fn foo(self: &dyn Foo) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/inference_var_self_argument.rs:5:14 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | async fn foo(self: &dyn Foo) { | ^^^ ...because method `foo` is `async` = help: consider moving `foo` to another trait diff --git a/tests/ui/async-await/issue-68523-start.rs b/tests/ui/async-await/issue-68523-start.rs deleted file mode 100644 index ee3baf4990c..00000000000 --- a/tests/ui/async-await/issue-68523-start.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ edition:2018 - -#![feature(start)] - -#[start] -pub async fn start(_: isize, _: *const *const u8) -> isize { -//~^ ERROR `#[start]` function is not allowed to be `async` - 0 -} diff --git a/tests/ui/async-await/issue-68523-start.stderr b/tests/ui/async-await/issue-68523-start.stderr deleted file mode 100644 index 5b76ab56e24..00000000000 --- a/tests/ui/async-await/issue-68523-start.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0752]: `#[start]` function is not allowed to be `async` - --> $DIR/issue-68523-start.rs:6:1 - | -LL | pub async fn start(_: isize, _: *const *const u8) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `#[start]` is not allowed to be `async` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0752`. diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr deleted file mode 100644 index 018f4f2207a..00000000000 --- a/tests/ui/async-await/return-type-notation/issue-110963-late.next.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-110963-late.rs:6:12 - | -LL | #![feature(return_type_notation)] - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr b/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr deleted file mode 100644 index 5f482b60878..00000000000 --- a/tests/ui/async-await/return-type-notation/super-method-bound.next.stderr +++ /dev/null @@ -1,10 +0,0 @@ -warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/super-method-bound.rs:6:31 - | -LL | #![feature(return_type_notation)] | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/attr-start.rs b/tests/ui/attr-start.rs deleted file mode 100644 index 232f50955b2..00000000000 --- a/tests/ui/attr-start.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ run-pass - -#![feature(start)] - -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { - return 0; -} diff --git a/tests/ui/attributes/check-builtin-attr-ice.stderr b/tests/ui/attributes/check-builtin-attr-ice.stderr index 5a27da565a8..06a4769b2b4 100644 --- a/tests/ui/attributes/check-builtin-attr-ice.stderr +++ b/tests/ui/attributes/check-builtin-attr-ice.stderr @@ -1,20 +1,20 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `should_panic` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic` --> $DIR/check-builtin-attr-ice.rs:43:7 | LL | #[should_panic::skip] - | ^^^^^^^^^^^^ use of undeclared crate or module `should_panic` + | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic` -error[E0433]: failed to resolve: use of undeclared crate or module `should_panic` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `should_panic` --> $DIR/check-builtin-attr-ice.rs:47:7 | LL | #[should_panic::a::b::c] - | ^^^^^^^^^^^^ use of undeclared crate or module `should_panic` + | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `should_panic` -error[E0433]: failed to resolve: use of undeclared crate or module `deny` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `deny` --> $DIR/check-builtin-attr-ice.rs:55:7 | LL | #[deny::skip] - | ^^^^ use of undeclared crate or module `deny` + | ^^^^ use of unresolved module or unlinked crate `deny` error: aborting due to 3 previous errors diff --git a/tests/ui/attributes/check-cfg_attr-ice.stderr b/tests/ui/attributes/check-cfg_attr-ice.stderr index dbdf32597f7..bed3150bdc2 100644 --- a/tests/ui/attributes/check-cfg_attr-ice.stderr +++ b/tests/ui/attributes/check-cfg_attr-ice.stderr @@ -17,83 +17,83 @@ LL | #[cfg_attr::no_such_thing] = help: add `#![feature(stmt_expr_attributes)]` 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[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:52:3 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:55:7 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:57:17 | LL | GiveYouUp(#[cfg_attr::no_such_thing] u8), - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:64:11 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:41:7 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:43:15 | LL | fn from(#[cfg_attr::no_such_thing] any_other_guy: AnyOtherGuy) -> This { - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:45:11 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:32:3 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:24:3 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:27:7 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:16:3 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:19:7 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` -error[E0433]: failed to resolve: use of undeclared crate or module `cfg_attr` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `cfg_attr` --> $DIR/check-cfg_attr-ice.rs:12:3 | LL | #[cfg_attr::no_such_thing] - | ^^^^^^^^ use of undeclared crate or module `cfg_attr` + | ^^^^^^^^ use of unresolved module or unlinked crate `cfg_attr` error: aborting due to 15 previous errors diff --git a/tests/ui/attributes/field-attributes-vis-unresolved.stderr b/tests/ui/attributes/field-attributes-vis-unresolved.stderr index f8610c08b02..d689b76eaf8 100644 --- a/tests/ui/attributes/field-attributes-vis-unresolved.stderr +++ b/tests/ui/attributes/field-attributes-vis-unresolved.stderr @@ -1,21 +1,21 @@ -error[E0433]: failed to resolve: you might be missing crate `nonexistent` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `nonexistent` --> $DIR/field-attributes-vis-unresolved.rs:17:12 | LL | pub(in nonexistent) field: u8 - | ^^^^^^^^^^^ you might be missing crate `nonexistent` + | ^^^^^^^^^^^ use of unresolved module or unlinked crate `nonexistent` | -help: consider importing the `nonexistent` crate +help: you might be missing a crate named `nonexistent`, add it to your project and import it in your code | LL + extern crate nonexistent; | -error[E0433]: failed to resolve: you might be missing crate `nonexistent` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `nonexistent` --> $DIR/field-attributes-vis-unresolved.rs:22:12 | LL | pub(in nonexistent) u8 - | ^^^^^^^^^^^ you might be missing crate `nonexistent` + | ^^^^^^^^^^^ use of unresolved module or unlinked crate `nonexistent` | -help: consider importing the `nonexistent` crate +help: you might be missing a crate named `nonexistent`, add it to your project and import it in your code | LL + extern crate nonexistent; | diff --git a/tests/ui/backtrace/backtrace.rs b/tests/ui/backtrace/backtrace.rs index 2579ff5203b..487473f4393 100644 --- a/tests/ui/backtrace/backtrace.rs +++ b/tests/ui/backtrace/backtrace.rs @@ -1,8 +1,7 @@ //@ run-pass //@ ignore-android FIXME #17520 -//@ ignore-wasm32 spawning processes is not supported +//@ needs-subprocess //@ ignore-openbsd no support for libbacktrace without filename -//@ ignore-sgx no processes //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test //@ ignore-fuchsia Backtraces not symbolized //@ compile-flags:-g diff --git a/tests/ui/backtrace/std-backtrace.rs b/tests/ui/backtrace/std-backtrace.rs index 57d953a8640..7ccbd46152b 100644 --- a/tests/ui/backtrace/std-backtrace.rs +++ b/tests/ui/backtrace/std-backtrace.rs @@ -1,8 +1,7 @@ //@ run-pass //@ ignore-android FIXME #17520 -//@ ignore-wasm32 spawning processes is not supported +//@ needs-subprocess //@ ignore-openbsd no support for libbacktrace without filename -//@ ignore-sgx no processes //@ ignore-fuchsia Backtraces not symbolized //@ compile-flags:-g //@ compile-flags:-Cstrip=none diff --git a/tests/ui/binop/binop-fail-3.rs b/tests/ui/binop/binop-fail-3.rs index b1e70a1c596..4e8d7e92ab6 100644 --- a/tests/ui/binop/binop-fail-3.rs +++ b/tests/ui/binop/binop-fail-3.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:quux -//@ ignore-emscripten no processes +//@ needs-subprocess fn foo() -> ! { panic!("quux"); diff --git a/tests/ui/binop/binop-panic.rs b/tests/ui/binop/binop-panic.rs index 8dbf62a922e..8173eb0d689 100644 --- a/tests/ui/binop/binop-panic.rs +++ b/tests/ui/binop/binop-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:quux -//@ ignore-emscripten no processes +//@ needs-subprocess fn my_err(s: String) -> ! { println!("{}", s); diff --git a/tests/ui/borrowck/borrowck-local-borrow.rs b/tests/ui/borrowck/borrowck-local-borrow.rs index de6ee5983c8..4d22503e37b 100644 --- a/tests/ui/borrowck/borrowck-local-borrow.rs +++ b/tests/ui/borrowck/borrowck-local-borrow.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:panic 1 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let x = 2; diff --git a/tests/ui/borrowck/issue-28934.rs b/tests/ui/borrowck/issue-28934.rs index a3ac663c5b5..64559d4cf1d 100644 --- a/tests/ui/borrowck/issue-28934.rs +++ b/tests/ui/borrowck/issue-28934.rs @@ -3,7 +3,7 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess struct Parser<'i: 't, 't>(&'i u8, &'t u8); diff --git a/tests/ui/box/unit/unwind-unique.rs b/tests/ui/box/unit/unwind-unique.rs index 512327c9af4..1da55c45ee9 100644 --- a/tests/ui/box/unit/unwind-unique.rs +++ b/tests/ui/box/unit/unwind-unique.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/cfg/disallowed-cli-cfgs.test_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.test_.stderr deleted file mode 100644 index 96b5beb0210..00000000000 --- a/tests/ui/cfg/disallowed-cli-cfgs.test_.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: unexpected `--cfg test` flag - | - = note: config `test` is only supposed to be controlled by `--test` - = note: see <https://github.com/rust-lang/rust/issues/xxxxx> for more information - = note: `#[deny(unexpected_builtin_cfgs)]` on by default - -error: aborting due to 1 previous error - diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs index ff724174cea..5eef50e08e2 100644 --- a/tests/ui/check-cfg/allow-same-level.rs +++ b/tests/ui/check-cfg/allow-same-level.rs @@ -1,12 +1,24 @@ -// This test check that #[allow(unexpected_cfgs)] doesn't work if put on the same level +// This test check that #[allow(unexpected_cfgs)] **doesn't work** +// when put on the same level as the #[cfg] attribute. +// +// It should work, but due to interactions between how #[cfg]s are +// expanded, the lint machinery and the check-cfg impl, we +// miss the #[allow], althrough we probably shoudln't. +// +// cf. https://github.com/rust-lang/rust/issues/124735 // //@ check-pass //@ no-auto-check-cfg -//@ compile-flags: --check-cfg=cfg() +//@ compile-flags: --check-cfg=cfg() --cfg=unknown_but_active_cfg #[allow(unexpected_cfgs)] #[cfg(FALSE)] //~^ WARNING unexpected `cfg` condition name fn bar() {} +#[allow(unexpected_cfgs)] +#[cfg(unknown_but_active_cfg)] +//~^ WARNING unexpected `cfg` condition name +fn bar() {} + fn main() {} diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr index 5d74b211654..a705cd4e5f0 100644 --- a/tests/ui/check-cfg/allow-same-level.stderr +++ b/tests/ui/check-cfg/allow-same-level.stderr @@ -1,13 +1,21 @@ warning: unexpected `cfg` condition name: `FALSE` - --> $DIR/allow-same-level.rs:8:7 + --> $DIR/allow-same-level.rs:15:7 | LL | #[cfg(FALSE)] | ^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(FALSE)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default -warning: 1 warning emitted +warning: unexpected `cfg` condition name: `unknown_but_active_cfg` + --> $DIR/allow-same-level.rs:20:7 + | +LL | #[cfg(unknown_but_active_cfg)] + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = help: to expect this configuration use `--check-cfg=cfg(unknown_but_active_cfg)` + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration + +warning: 2 warnings emitted diff --git a/tests/ui/check-cfg/cargo-build-script.stderr b/tests/ui/check-cfg/cargo-build-script.stderr index fb48751bc1d..df0bc47571c 100644 --- a/tests/ui/check-cfg/cargo-build-script.stderr +++ b/tests/ui/check-cfg/cargo-build-script.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `has_foo` LL | #[cfg(has_foo)] | ^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `has_bar`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `has_bar` and 30 more = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr index aa2a1ab8fb2..58813a1f677 100644 --- a/tests/ui/check-cfg/cargo-feature.none.stderr +++ b/tests/ui/check-cfg/cargo-feature.none.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `serde` - --> $DIR/cargo-feature.rs:14:7 + --> $DIR/cargo-feature.rs:15:7 | LL | #[cfg(feature = "serde")] | ^^^^^^^^^^^^^^^^^ help: remove the condition @@ -10,7 +10,7 @@ LL | #[cfg(feature = "serde")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/cargo-feature.rs:18:7 + --> $DIR/cargo-feature.rs:19:7 | LL | #[cfg(feature)] | ^^^^^^^ help: remove the condition @@ -20,12 +20,12 @@ LL | #[cfg(feature)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` - --> $DIR/cargo-feature.rs:22:7 + --> $DIR/cargo-feature.rs:23:7 | LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `docsrs`, `feature`, and `test` and 30 more = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] @@ -34,7 +34,7 @@ LL | #[cfg(tokio_unstable)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `CONFIG_NVME` - --> $DIR/cargo-feature.rs:26:7 + --> $DIR/cargo-feature.rs:27:7 | LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/check-cfg/cargo-feature.rs b/tests/ui/check-cfg/cargo-feature.rs index 13faf7f2820..a9380ddae1a 100644 --- a/tests/ui/check-cfg/cargo-feature.rs +++ b/tests/ui/check-cfg/cargo-feature.rs @@ -6,6 +6,7 @@ //@ no-auto-check-cfg //@ revisions: some none //@ rustc-env:CARGO_CRATE_NAME=foo +//@ compile-flags: --check-cfg=cfg(docsrs,test) //@ [none]compile-flags: --check-cfg=cfg(feature,values()) //@ [some]compile-flags: --check-cfg=cfg(feature,values("bitcode")) //@ [some]compile-flags: --check-cfg=cfg(CONFIG_NVME,values("y")) diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr index c3ba123985b..5a12be81338 100644 --- a/tests/ui/check-cfg/cargo-feature.some.stderr +++ b/tests/ui/check-cfg/cargo-feature.some.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `serde` - --> $DIR/cargo-feature.rs:14:7 + --> $DIR/cargo-feature.rs:15:7 | LL | #[cfg(feature = "serde")] | ^^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | #[cfg(feature = "serde")] = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: (none) - --> $DIR/cargo-feature.rs:18:7 + --> $DIR/cargo-feature.rs:19:7 | LL | #[cfg(feature)] | ^^^^^^^- help: specify a config value: `= "bitcode"` @@ -20,12 +20,12 @@ LL | #[cfg(feature)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `tokio_unstable` - --> $DIR/cargo-feature.rs:22:7 + --> $DIR/cargo-feature.rs:23:7 | LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `CONFIG_NVME`, `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `CONFIG_NVME`, `docsrs`, `feature`, and `test` and 30 more = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] @@ -34,7 +34,7 @@ LL | #[cfg(tokio_unstable)] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `m` - --> $DIR/cargo-feature.rs:26:7 + --> $DIR/cargo-feature.rs:27:7 | LL | #[cfg(CONFIG_NVME = "m")] | ^^^^^^^^^^^^^^--- diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr index b7dc27f9ba9..7c276c58170 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value` LL | #[cfg(value)] | ^^^^^ | - = help: expected names are: `bar`, `bee`, `clippy`, `cow`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `bar`, `bee`, `cow`, and `foo` and 30 more = help: to expect this configuration use `--check-cfg=cfg(value)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr index d2af81d7787..9687a043e83 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_value` LL | #[cfg(my_value)] | ^^^^^^^^ | - = help: expected names are: `bar`, `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `bar` and `foo` and 30 more = help: to expect this configuration use `--check-cfg=cfg(my_value)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr index 85bf66eb10c..883679ddf9c 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr @@ -4,7 +4,6 @@ warning: unexpected `cfg` condition name: `linux` LL | #[cfg(linux)] | ^^^^^ help: found config with similar value: `target_os = "linux"` | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(linux)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr index ef0a413bd0d..74ed0337e3b 100644 --- a/tests/ui/check-cfg/compact-names.stderr +++ b/tests/ui/check-cfg/compact-names.stderr @@ -4,7 +4,6 @@ warning: unexpected `cfg` condition name: `target_architecture` LL | #[cfg(target(os = "linux", architecture = "arm"))] | ^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(target_architecture, values("arm"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr index 23b6edacce7..7e77ba63a12 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr @@ -4,7 +4,6 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index 804d7fb9163..10302f0a7e4 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `feature` and 30 more = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index 804d7fb9163..10302f0a7e4 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `feature` and 30 more = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr index d134cfcfd29..4d56d24acaf 100644 --- a/tests/ui/check-cfg/exhaustive-names.stderr +++ b/tests/ui/check-cfg/exhaustive-names.stderr @@ -4,7 +4,6 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 76c7befd6d3..033aaef848f 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -44,7 +44,7 @@ warning: unexpected `cfg` condition name: `uu` LL | #[cfg_attr(uu, unix)] | ^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `feature` and 30 more = help: to expect this configuration use `--check-cfg=cfg(uu)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/raw-keywords.edition2015.stderr b/tests/ui/check-cfg/raw-keywords.edition2015.stderr index 3ad8ebac959..f19ded9cb67 100644 --- a/tests/ui/check-cfg/raw-keywords.edition2015.stderr +++ b/tests/ui/check-cfg/raw-keywords.edition2015.stderr @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `r#false` LL | #[cfg(r#false)] | ^^^^^^^ | - = help: expected names are: `async`, `clippy`, `debug_assertions`, `doc`, `doctest`, `edition2015`, `edition2021`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `r#true`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `async`, `edition2015`, `edition2021`, and `r#true` and 30 more = help: to expect this configuration use `--check-cfg=cfg(r#false)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/raw-keywords.edition2021.stderr b/tests/ui/check-cfg/raw-keywords.edition2021.stderr index ff43a332697..6096148a259 100644 --- a/tests/ui/check-cfg/raw-keywords.edition2021.stderr +++ b/tests/ui/check-cfg/raw-keywords.edition2021.stderr @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `r#false` LL | #[cfg(r#false)] | ^^^^^^^ | - = help: expected names are: `r#async`, `clippy`, `debug_assertions`, `doc`, `doctest`, `edition2015`, `edition2021`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `r#true`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `r#async`, `edition2015`, `edition2021`, and `r#true` and 30 more = help: to expect this configuration use `--check-cfg=cfg(r#false)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr index b82a09917f4..a6584d777a3 100644 --- a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr +++ b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_lib_cfg` LL | cfg_macro::my_lib_macro!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `feature` and 30 more = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try referring to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg = help: the macro `cfg_macro::my_lib_macro` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro` diff --git a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr index 85d84a1e1ee..914b5a0efe3 100644 --- a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr +++ b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_lib_cfg` LL | cfg_macro::my_lib_macro!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `feature`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` + = help: expected names are: `feature` and 30 more = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try referring to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg = help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)` diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr index d8c6b0f3cec..3cf43c6aece 100644 --- a/tests/ui/check-cfg/stmt-no-ice.stderr +++ b/tests/ui/check-cfg/stmt-no-ice.stderr @@ -4,7 +4,6 @@ warning: unexpected `cfg` condition name: `crossbeam_loom` LL | #[cfg(crossbeam_loom)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(crossbeam_loom)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/unexpected-cfg-name.stderr b/tests/ui/check-cfg/unexpected-cfg-name.stderr index 4ca7209cc07..7708d9e3cd4 100644 --- a/tests/ui/check-cfg/unexpected-cfg-name.stderr +++ b/tests/ui/check-cfg/unexpected-cfg-name.stderr @@ -14,7 +14,6 @@ warning: unexpected `cfg` condition name: `test` LL | #[cfg(test)] | ^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(test)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/well-known-names.rs b/tests/ui/check-cfg/well-known-names.rs index b84710ca839..39fa3a37d1a 100644 --- a/tests/ui/check-cfg/well-known-names.rs +++ b/tests/ui/check-cfg/well-known-names.rs @@ -2,7 +2,12 @@ // //@ check-pass //@ no-auto-check-cfg -//@ compile-flags: --check-cfg=cfg() +//@ compile-flags: --check-cfg=cfg() -Zcheck-cfg-all-expected +//@ normalize-stderr: "`, `" -> "`\n`" + +#[cfg(list_all_well_known_cfgs)] +//~^ WARNING unexpected `cfg` condition name +fn in_diagnostics() {} #[cfg(target_oz = "linux")] //~^ WARNING unexpected `cfg` condition name diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index 61d518627ba..4ff90261158 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -1,29 +1,66 @@ +warning: unexpected `cfg` condition name: `list_all_well_known_cfgs` + --> $DIR/well-known-names.rs:8:7 + | +LL | #[cfg(list_all_well_known_cfgs)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `clippy` +`debug_assertions` +`doc` +`doctest` +`fmt_debug` +`miri` +`overflow_checks` +`panic` +`proc_macro` +`relocation_model` +`rustfmt` +`sanitize` +`sanitizer_cfi_generalize_pointers` +`sanitizer_cfi_normalize_integers` +`target_abi` +`target_arch` +`target_endian` +`target_env` +`target_family` +`target_feature` +`target_has_atomic` +`target_has_atomic_equal_alignment` +`target_has_atomic_load_store` +`target_os` +`target_pointer_width` +`target_thread_local` +`target_vendor` +`ub_checks` +`unix`, and `windows` + = help: to expect this configuration use `--check-cfg=cfg(list_all_well_known_cfgs)` + = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + warning: unexpected `cfg` condition name: `target_oz` - --> $DIR/well-known-names.rs:7:7 + --> $DIR/well-known-names.rs:12:7 | LL | #[cfg(target_oz = "linux")] | ^^^^^^^^^^^^^^^^^^^ | = help: to expect this configuration use `--check-cfg=cfg(target_oz, values("linux"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration - = note: `#[warn(unexpected_cfgs)]` on by default help: there is a config with a similar name and value | LL | #[cfg(target_os = "linux")] | ~~~~~~~~~ warning: unexpected `cfg` condition name: `features` - --> $DIR/well-known-names.rs:14:7 + --> $DIR/well-known-names.rs:19:7 | LL | #[cfg(features = "foo")] | ^^^^^^^^^^^^^^^^ | - = help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `ub_checks`, `unix`, and `windows` = help: to expect this configuration use `--check-cfg=cfg(features, values("foo"))` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `feature` - --> $DIR/well-known-names.rs:18:7 + --> $DIR/well-known-names.rs:23:7 | LL | #[cfg(feature = "foo")] | ^^^^^^^^^^^^^^^ @@ -32,7 +69,7 @@ LL | #[cfg(feature = "foo")] = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition name: `uniw` - --> $DIR/well-known-names.rs:22:7 + --> $DIR/well-known-names.rs:27:7 | LL | #[cfg(uniw)] | ^^^^ help: there is a config with a similar name: `unix` @@ -40,5 +77,5 @@ LL | #[cfg(uniw)] = help: to expect this configuration use `--check-cfg=cfg(uniw)` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration -warning: 4 warnings emitted +warning: 5 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 5c1898a0ae3..ffebd7e5531 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -129,7 +129,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, and `x32` + = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `fortanix`, `ilp32`, `ilp32e`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, and `x32` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -156,7 +156,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, and `uclibc` + = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `nto80`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, and `uclibc` = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs b/tests/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs index 80c5a8fe099..4c59df24e4b 100644 --- a/tests/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs +++ b/tests/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs @@ -20,7 +20,7 @@ // It's unclear how likely such a bug is to recur, but it seems like a // scenario worth testing. -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/closures/2229_closure_analysis/issue-87987.rs b/tests/ui/closures/2229_closure_analysis/issue-87987.rs deleted file mode 100644 index f79a8f1b571..00000000000 --- a/tests/ui/closures/2229_closure_analysis/issue-87987.rs +++ /dev/null @@ -1,27 +0,0 @@ -//@ run-pass -//@ edition:2021 - -struct Props { - field_1: u32, //~ WARNING: fields `field_1` and `field_2` are never read - field_2: u32, -} - -fn main() { - // Test 1 - let props_2 = Props { field_1: 1, field_2: 1 }; - - let _ = || { - let _: Props = props_2; - }; - - // Test 2 - let mut arr = [1, 3, 4, 5]; - - let mref = &mut arr; - - let _c = || match arr { - [_, _, _, _] => println!("A"), - }; - - println!("{:#?}", mref); -} diff --git a/tests/ui/closures/2229_closure_analysis/issue-87987.stderr b/tests/ui/closures/2229_closure_analysis/issue-87987.stderr deleted file mode 100644 index 5696a010c3f..00000000000 --- a/tests/ui/closures/2229_closure_analysis/issue-87987.stderr +++ /dev/null @@ -1,14 +0,0 @@ -warning: fields `field_1` and `field_2` are never read - --> $DIR/issue-87987.rs:5:5 - | -LL | struct Props { - | ----- fields in this struct -LL | field_1: u32, - | ^^^^^^^ -LL | field_2: u32, - | ^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs b/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs new file mode 100644 index 00000000000..c501e034c97 --- /dev/null +++ b/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs @@ -0,0 +1,46 @@ +//! When a closure syntactically captures a place, but doesn't actually capture +//! it, make sure MIR building doesn't ICE when handling that place. +//! +//! Under the Rust 2021 disjoint capture rules, this sort of non-capture can +//! occur when a place is only inspected by infallible non-binding patterns. + +// FIXME(#135985): On its own, this test should probably just be check-pass. +// But there are few/no other tests that use non-binding array patterns and +// invoke the later parts of the compiler, so building/running has some value. + +//@ run-pass +//@ edition:2021 + +#[expect(dead_code)] +struct Props { + field_1: u32, + field_2: u32, +} + +fn main() { + // Test 1 + let props_2 = Props { field_1: 1, field_2: 1 }; + + let _ = || { + let _: Props = props_2; + }; + + // Test 2 + let mut arr = [1, 3, 4, 5]; + + let mref = &mut arr; + + // These array patterns don't need to inspect the array, so the array + // isn't captured. + let _c = || match arr { + [_, _, _, _] => println!("C"), + }; + let _d = || match arr { + [_, .., _] => println!("D"), + }; + let _e = || match arr { + [_, ..] => println!("E"), + }; + + println!("{:#?}", mref); +} diff --git a/tests/ui/closures/binder/forbid_ambig_const_infers.rs b/tests/ui/closures/binder/forbid_ambig_const_infers.rs new file mode 100644 index 00000000000..e9d783711ee --- /dev/null +++ b/tests/ui/closures/binder/forbid_ambig_const_infers.rs @@ -0,0 +1,9 @@ +#![feature(generic_arg_infer, closure_lifetime_binder)] + +struct Foo<const N: usize>([u32; N]); + +fn main() { + let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0[0] }; + //~^ ERROR: implicit types in closure signatures are forbidden when `for<...>` is present + c(&Foo([1_u32; 1])); +} diff --git a/tests/ui/closures/binder/forbid_ambig_const_infers.stderr b/tests/ui/closures/binder/forbid_ambig_const_infers.stderr new file mode 100644 index 00000000000..396c9e8c916 --- /dev/null +++ b/tests/ui/closures/binder/forbid_ambig_const_infers.stderr @@ -0,0 +1,10 @@ +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/forbid_ambig_const_infers.rs:6:33 + | +LL | let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0[0] }; + | ------- ^ + | | + | `for<...>` is here + +error: aborting due to 1 previous error + diff --git a/tests/ui/closures/binder/forbid_ambig_type_infers.rs b/tests/ui/closures/binder/forbid_ambig_type_infers.rs new file mode 100644 index 00000000000..4e717ef3a17 --- /dev/null +++ b/tests/ui/closures/binder/forbid_ambig_type_infers.rs @@ -0,0 +1,9 @@ +#![feature(generic_arg_infer, closure_lifetime_binder)] + +struct Foo<T>(T); + +fn main() { + let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0 }; + //~^ ERROR: implicit types in closure signatures are forbidden when `for<...>` is present + c(&Foo(1_u32)); +} diff --git a/tests/ui/closures/binder/forbid_ambig_type_infers.stderr b/tests/ui/closures/binder/forbid_ambig_type_infers.stderr new file mode 100644 index 00000000000..8f19d710073 --- /dev/null +++ b/tests/ui/closures/binder/forbid_ambig_type_infers.stderr @@ -0,0 +1,10 @@ +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/forbid_ambig_type_infers.rs:6:33 + | +LL | let c = for<'a> |b: &'a Foo<_>| -> u32 { b.0 }; + | ------- ^ + | | + | `for<...>` is here + +error: aborting due to 1 previous error + diff --git a/tests/ui/closures/binder/forbid_const_infer.rs b/tests/ui/closures/binder/forbid_const_infer.rs new file mode 100644 index 00000000000..f5b8bf188df --- /dev/null +++ b/tests/ui/closures/binder/forbid_const_infer.rs @@ -0,0 +1,7 @@ +#![feature(generic_arg_infer, closure_lifetime_binder)] + +fn main() { + let c = for<'a> |b: &'a [u32; _]| -> u32 { b[0] }; + //~^ ERROR: implicit types in closure signatures are forbidden when `for<...>` is present + c(&[1_u32; 2]); +} diff --git a/tests/ui/closures/binder/forbid_const_infer.stderr b/tests/ui/closures/binder/forbid_const_infer.stderr new file mode 100644 index 00000000000..e93685d400e --- /dev/null +++ b/tests/ui/closures/binder/forbid_const_infer.stderr @@ -0,0 +1,10 @@ +error: implicit types in closure signatures are forbidden when `for<...>` is present + --> $DIR/forbid_const_infer.rs:4:35 + | +LL | let c = for<'a> |b: &'a [u32; _]| -> u32 { b[0] }; + | ------- ^ + | | + | `for<...>` is here + +error: aborting due to 1 previous error + diff --git a/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.polonius.stderr b/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.polonius.stderr deleted file mode 100644 index 8846ccef34e..00000000000 --- a/tests/ui/closures/closure-expected-type/expect-region-supply-region-2.polonius.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/expect-region-supply-region-2.rs:14:30 - | -LL | fn expect_bound_supply_named<'x>() { - | -- lifetime `'x` defined here -... -LL | closure_expecting_bound(|x: &'x u32| { - | ^ - let's call the lifetime of this reference `'1` - | | - | requires that `'1` must outlive `'x` - -error[E0521]: borrowed data escapes outside of closure - --> $DIR/expect-region-supply-region-2.rs:20:9 - | -LL | let mut f: Option<&u32> = None; - | ----- `f` declared here, outside of the closure body -... -LL | closure_expecting_bound(|x: &'x u32| { - | - `x` is a reference that is only valid in the closure body -... -LL | f = Some(x); - | ^^^^^^^^^^^ `x` escapes the closure body here - -error: lifetime may not live long enough - --> $DIR/expect-region-supply-region-2.rs:14:30 - | -LL | fn expect_bound_supply_named<'x>() { - | -- lifetime `'x` defined here -... -LL | closure_expecting_bound(|x: &'x u32| { - | ^ requires that `'x` must outlive `'static` - | - = help: consider replacing `'x` with `'static` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/closures/diverging-closure.rs b/tests/ui/closures/diverging-closure.rs index dda829d8af4..2c86f55cf25 100644 --- a/tests/ui/closures/diverging-closure.rs +++ b/tests/ui/closures/diverging-closure.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:oops -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let func = || -> ! { diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr deleted file mode 100644 index 77379f7049d..00000000000 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target - --> $DIR/trustzone-only.rs:5:1 - | -LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr index 542be2dbc30..20257bbaf28 100644 --- a/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr +++ b/tests/ui/coherence/coherence-impl-trait-for-trait-dyn-compatible.stderr @@ -1,16 +1,17 @@ -error[E0038]: the trait `DynIncompatible` cannot be made into an object +error[E0038]: the trait `DynIncompatible` is not dyn compatible --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:7:26 | LL | impl DynIncompatible for dyn DynIncompatible { } - | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/coherence-impl-trait-for-trait-dyn-compatible.rs:6:45 | LL | trait DynIncompatible { fn eq(&self, other: Self); } | --------------- ^^^^ ...because method `eq` references the `Self` type in this parameter | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... = help: consider moving `eq` to another trait error[E0046]: not all trait items implemented, missing: `eq` diff --git a/tests/ui/coherence/conflicting-impl-with-err.stderr b/tests/ui/coherence/conflicting-impl-with-err.stderr index 3009b452dc7..75a201797b5 100644 --- a/tests/ui/coherence/conflicting-impl-with-err.stderr +++ b/tests/ui/coherence/conflicting-impl-with-err.stderr @@ -1,14 +1,18 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `nope` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `nope` --> $DIR/conflicting-impl-with-err.rs:4:11 | LL | impl From<nope::Thing> for Error { - | ^^^^ use of undeclared crate or module `nope` + | ^^^^ use of unresolved module or unlinked crate `nope` + | + = help: you might be missing a crate named `nope` -error[E0433]: failed to resolve: use of undeclared crate or module `nope` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `nope` --> $DIR/conflicting-impl-with-err.rs:5:16 | LL | fn from(_: nope::Thing) -> Self { - | ^^^^ use of undeclared crate or module `nope` + | ^^^^ use of unresolved module or unlinked crate `nope` + | + = help: you might be missing a crate named `nope` error: aborting due to 2 previous errors diff --git a/tests/ui/command/command-argv0.rs b/tests/ui/command/command-argv0.rs index 35625c0b334..0907e18b30c 100644 --- a/tests/ui/command/command-argv0.rs +++ b/tests/ui/command/command-argv0.rs @@ -1,8 +1,7 @@ //@ run-pass -//@ ignore-windows - this is a unix-specific test -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ only-unix (this is a unix-specific test) +//@ needs-subprocess use std::env; use std::os::unix::process::CommandExt; use std::process::Command; diff --git a/tests/ui/command/command-current-dir.rs b/tests/ui/command/command-current-dir.rs index 23269e41231..e264cbe4d70 100644 --- a/tests/ui/command/command-current-dir.rs +++ b/tests/ui/command/command-current-dir.rs @@ -1,7 +1,6 @@ //@ run-pass //@ no-prefer-dynamic We move the binary around, so do not depend dynamically on libstd -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia Needs directory creation privilege use std::env; diff --git a/tests/ui/command/command-exec.rs b/tests/ui/command/command-exec.rs index d2545b0b472..77336377e88 100644 --- a/tests/ui/command/command-exec.rs +++ b/tests/ui/command/command-exec.rs @@ -1,13 +1,9 @@ //@ run-pass -#![allow(stable_features)] -//@ ignore-windows - this is a unix-specific test -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ only-unix (this is a unix-specific test) +//@ needs-subprocess //@ ignore-fuchsia no execvp syscall provided -#![feature(process_exec)] - use std::env; use std::os::unix::process::CommandExt; use std::process::Command; diff --git a/tests/ui/command/command-pre-exec.rs b/tests/ui/command/command-pre-exec.rs index 7242dea2775..7299f357bd0 100644 --- a/tests/ui/command/command-pre-exec.rs +++ b/tests/ui/command/command-pre-exec.rs @@ -1,11 +1,9 @@ //@ run-pass - -#![allow(stable_features)] -//@ ignore-windows - this is a unix-specific test -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ only-unix (this is a unix-specific test) +//@ needs-subprocess //@ ignore-fuchsia no execvp syscall -#![feature(process_exec, rustc_private)] + +#![feature(rustc_private)] extern crate libc; diff --git a/tests/ui/command/command-setgroups.rs b/tests/ui/command/command-setgroups.rs index c940135d844..047f06729af 100644 --- a/tests/ui/command/command-setgroups.rs +++ b/tests/ui/command/command-setgroups.rs @@ -1,9 +1,8 @@ //@ run-pass -//@ ignore-windows - this is a unix-specific test -//@ ignore-wasm32 -//@ ignore-sgx +//@ only-unix (this is a unix-specific test) //@ ignore-musl - returns dummy result for _SC_NGROUPS_MAX //@ ignore-nto - does not have `/bin/id`, expects groups to be i32 (not u32) +//@ needs-subprocess #![feature(rustc_private)] #![feature(setgroups)] diff --git a/tests/ui/command/command-uid-gid.rs b/tests/ui/command/command-uid-gid.rs index 7a70a0fbd76..f54a0f50708 100644 --- a/tests/ui/command/command-uid-gid.rs +++ b/tests/ui/command/command-uid-gid.rs @@ -1,8 +1,7 @@ //@ run-pass //@ ignore-android -//@ ignore-emscripten -//@ ignore-sgx //@ ignore-fuchsia no '/bin/sh', '/bin/ls' +//@ needs-subprocess #![feature(rustc_private)] diff --git a/tests/ui/command/issue-10626.rs b/tests/ui/command/issue-10626.rs index f8dbb011513..d2679ec9e29 100644 --- a/tests/ui/command/issue-10626.rs +++ b/tests/ui/command/issue-10626.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess // Make sure that if a process doesn't have its stdio/stderr descriptors set up // that we don't die in a large ball of fire diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr index 84281eb53c9..cd7f3a3c21d 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_dyn_compatibility.stderr @@ -1,28 +1,30 @@ -error[E0038]: the trait `ConstParamTy_` cannot be made into an object - --> $DIR/const_param_ty_dyn_compatibility.rs:6:12 +error[E0038]: the trait `ConstParamTy_` is not dyn compatible + --> $DIR/const_param_ty_dyn_compatibility.rs:6:16 | LL | fn foo(a: &dyn ConstParamTy_) {} - | ^^^^^^^^^^^^^^^^^ `ConstParamTy_` cannot be made into an object + | ^^^^^^^^^^^^^ `ConstParamTy_` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $SRC_DIR/core/src/cmp.rs:LL:COL | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter + = note: the trait is not dyn compatible because it uses `Self` as a type parameter help: consider using an opaque type instead | LL | fn foo(a: &impl ConstParamTy_) {} | ~~~~ -error[E0038]: the trait `UnsizedConstParamTy` cannot be made into an object - --> $DIR/const_param_ty_dyn_compatibility.rs:9:12 +error[E0038]: the trait `UnsizedConstParamTy` is not dyn compatible + --> $DIR/const_param_ty_dyn_compatibility.rs:9:16 | LL | fn bar(a: &dyn UnsizedConstParamTy) {} - | ^^^^^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `UnsizedConstParamTy` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $SRC_DIR/core/src/cmp.rs:LL:COL | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter + = note: the trait is not dyn compatible because it uses `Self` as a type parameter help: consider using an opaque type instead | LL | fn bar(a: &impl UnsizedConstParamTy) {} diff --git a/tests/ui/const-generics/generic_arg_infer/parend_infer.rs b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs new file mode 100644 index 00000000000..81c42183b38 --- /dev/null +++ b/tests/ui/const-generics/generic_arg_infer/parend_infer.rs @@ -0,0 +1,12 @@ +//@ check-pass +//@ revisions: gate nogate +#![cfg_attr(gate, feature(generic_arg_infer))] + +fn main() { + // AST Types preserve parens for pretty printing reasons. This means + // that this is parsed as a `TyKind::Paren(TyKind::Infer)`. Generic + // arg lowering therefore needs to take into account not just `TyKind::Infer` + // but `TyKind::Infer` wrapped in arbitrarily many `TyKind::Paren`. + let a: Vec<(_)> = vec![1_u8]; + let a: Vec<(((((_)))))> = vec![1_u8]; +} diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs index 1620e257667..9ab715d01f7 100644 --- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.rs @@ -14,8 +14,8 @@ impl Foo for () { } } -fn use_dyn(v: &dyn Foo) { //~ERROR the trait `Foo` cannot be made into an object - v.test(); //~ERROR the trait `Foo` cannot be made into an object +fn use_dyn(v: &dyn Foo) { //~ERROR the trait `Foo` is not dyn compatible + v.test(); //~ERROR the trait `Foo` is not dyn compatible } fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr index d2017615e67..763bc626c9d 100644 --- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-ret.stderr @@ -1,38 +1,40 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility-err-ret.rs:17:16 | LL | fn use_dyn(v: &dyn Foo) { - | ^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility-err-ret.rs:8:8 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn test(&self) -> [u8; bar::<Self>()]; | ^^^^ ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type | | | ...because method `test` references the `Self` type in its `where` clause = help: consider moving `test` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility-err-ret.rs:18:5 | LL | v.test(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility-err-ret.rs:8:8 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn test(&self) -> [u8; bar::<Self>()]; | ^^^^ ^^^^^^^^^^^^^^^^^^^ ...because method `test` references the `Self` type in its return type | | | ...because method `test` references the `Self` type in its `where` clause = help: consider moving `test` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `Foo`; consider using it directly instead. error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs index b3bbb842638..a7b771cd4f8 100644 --- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.rs @@ -13,9 +13,9 @@ impl Foo for () { } fn use_dyn(v: &dyn Foo) { - //~^ ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible v.test(); - //~^ ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible } fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr index 26ca2d4df5f..56678e4e9af 100644 --- a/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dyn-compatibility-err-where-bounds.stderr @@ -1,34 +1,36 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility-err-where-bounds.rs:15:16 | LL | fn use_dyn(v: &dyn Foo) { - | ^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn test(&self) where [u8; bar::<Self>()]: Sized; | ^^^^ ...because method `test` references the `Self` type in its `where` clause = help: consider moving `test` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility-err-where-bounds.rs:17:5 | LL | v.test(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility-err-where-bounds.rs:8:8 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn test(&self) where [u8; bar::<Self>()]: Sized; | ^^^^ ...because method `test` references the `Self` type in its `where` clause = help: consider moving `test` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `Foo`; consider using it directly instead. error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.rs b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs index f2ad7d7ce8b..882b27a418e 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-102768.rs +++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.rs @@ -13,7 +13,7 @@ const _: () = { //~| ERROR associated type takes 0 generic arguments but 1 generic argument //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments //~| ERROR associated type takes 0 generic arguments but 1 generic argument - //~| ERROR `X` cannot be made into an object + //~| ERROR `X` is not dyn compatible }; fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr index 9a75f372879..bd1811bd2cc 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-102768.stderr @@ -92,17 +92,18 @@ LL | type Y<'a>; | ^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/issue-102768.rs:9:24 | LL | fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-102768.rs:5:10 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr index c851a8380f2..d90380396c1 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -6,6 +6,6 @@ Box<dyn Any> query stack during panic: #0 [eval_to_allocation_raw] const-evaluating + checking `<impl at $DIR/issue-80742.rs:26:1: 28:32>::{constant#0}` #1 [eval_to_valtree] evaluating type-level constant -end of query stack +... and 2 other queries... use `env RUST_BACKTRACE=1` to see the full query stack error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-62878.min.stderr b/tests/ui/const-generics/issues/issue-62878.min.stderr index bd17d70a50b..1bb111b188d 100644 --- a/tests/ui/const-generics/issues/issue-62878.min.stderr +++ b/tests/ui/const-generics/issues/issue-62878.min.stderr @@ -18,19 +18,17 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | -error[E0747]: type provided when a constant was expected +error[E0658]: const arguments cannot yet be inferred with `_` --> $DIR/issue-62878.rs:10:11 | LL | foo::<_, { [1] }>(); | ^ | - = help: const arguments cannot yet be inferred with `_` -help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable - | -LL + #![feature(generic_arg_infer)] - | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` 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 -Some errors have detailed explanations: E0747, E0770. -For more information about an error, try `rustc --explain E0747`. +Some errors have detailed explanations: E0658, E0770. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/issues/issue-62878.rs b/tests/ui/const-generics/issues/issue-62878.rs index 0b5269df85e..c80b46ddbc4 100644 --- a/tests/ui/const-generics/issues/issue-62878.rs +++ b/tests/ui/const-generics/issues/issue-62878.rs @@ -8,5 +8,5 @@ fn foo<const N: usize, const A: [u8; N]>() {} fn main() { foo::<_, { [1] }>(); - //[min]~^ ERROR: type provided when a constant was expected + //[min]~^ ERROR: const arguments cannot yet be inferred with `_` } diff --git a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr index 1de1c78faf6..a506f2a282b 100644 --- a/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr +++ b/tests/ui/consts/const-eval/dont_promote_unstable_const_fn.stderr @@ -4,7 +4,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const fn bar() -> u32 { foo() } | ^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] diff --git a/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr b/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr deleted file mode 100644 index fef6c92af98..00000000000 --- a/tests/ui/consts/const-eval/ub-nonnull.chalk.64bit.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0284]: type annotations needed: cannot satisfy `<usize as SliceIndex<[u8]>>::Output == _` - --> $DIR/ub-nonnull.rs:19:30 - | -LL | let out_of_bounds_ptr = &ptr[255]; - | ^^^^^^^^ cannot satisfy `<usize as SliceIndex<[u8]>>::Output == _` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr b/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr deleted file mode 100644 index 533db90ce6c..00000000000 --- a/tests/ui/consts/const-eval/ub-wide-ptr.chalk.64bit.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0282]: type annotations needed - --> $DIR/ub-wide-ptr.rs:90:67 - | -LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); - | ^^^^^^^^^^^^^^ cannot infer type for type parameter `U` declared on the function `transmute` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/consts/issue-29798.rs b/tests/ui/consts/issue-29798.rs index bdabbad6491..f7470d7aac9 100644 --- a/tests/ui/consts/issue-29798.rs +++ b/tests/ui/consts/issue-29798.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:index out of bounds: the len is 5 but the index is 5 -//@ ignore-emscripten no processes +//@ needs-subprocess const fn test(x: usize) -> i32 { [42;5][x] diff --git a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index 899cec07ac7..26dedc49a39 100644 --- a/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -4,7 +4,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const fn bar() -> u32 { foo() } | ^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -22,7 +22,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const fn bar2() -> u32 { foo2() } | ^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -57,7 +57,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | foo() | ^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -75,7 +75,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -93,7 +93,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | pub(crate) const fn bar2_gated_stable_indirect() -> u32 { super::foo2_gated() } | ^^^^^^^^^^^^^^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -111,7 +111,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const fn stable_indirect() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr index 442a079020f..b61f7db6f43 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -4,7 +4,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const unsafe fn bar() -> u32 { unsafe { foo() } } | ^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -22,7 +22,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } | ^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -40,7 +40,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } | ^^^^^^^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] diff --git a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr index ff37cba7b9a..fad8e396e9a 100644 --- a/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr +++ b/tests/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr @@ -4,7 +4,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const unsafe fn bar() -> u32 { foo() } | ^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -22,7 +22,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const unsafe fn bar2() -> u32 { foo2() } | ^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] @@ -40,7 +40,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } | ^^^^^^^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr index a655c0faab6..bbe749f5958 100644 --- a/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr +++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unmarked_crate_imports.stderr @@ -4,7 +4,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | unstable_if_unmarked_const_fn_crate::not_stably_const(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] diff --git a/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr index d4ba0f9df2d..9d7b81c822b 100644 --- a/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr +++ b/tests/ui/consts/min_const_fn/recursive_const_stab_unstable_if_unmarked.stderr @@ -4,7 +4,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | not_stably_const(); | ^^^^^^^^^^^^^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] diff --git a/tests/ui/consts/too_generic_eval_ice.stderr b/tests/ui/consts/too_generic_eval_ice.stderr index b48be16a24c..3cc4377514a 100644 --- a/tests/ui/consts/too_generic_eval_ice.stderr +++ b/tests/ui/consts/too_generic_eval_ice.stderr @@ -32,13 +32,13 @@ LL | [5; Self::HOST_SIZE] == [6; 0] = help: the following other types implement trait `PartialEq<Rhs>`: `&[T]` implements `PartialEq<Vec<U, A>>` `&[T]` implements `PartialEq<[U; N]>` + `&[u8; N]` implements `PartialEq<ByteStr>` + `&[u8; N]` implements `PartialEq<ByteString>` + `&[u8]` implements `PartialEq<ByteStr>` + `&[u8]` implements `PartialEq<ByteString>` `&mut [T]` implements `PartialEq<Vec<U, A>>` `&mut [T]` implements `PartialEq<[U; N]>` - `[T; N]` implements `PartialEq<&[U]>` - `[T; N]` implements `PartialEq<&mut [U]>` - `[T; N]` implements `PartialEq<[U; N]>` - `[T; N]` implements `PartialEq<[U]>` - and 3 others + and 11 others error: aborting due to 4 previous errors diff --git a/tests/ui/consts/write_to_mut_ref_dest.stock.stderr b/tests/ui/consts/write_to_mut_ref_dest.stock.stderr deleted file mode 100644 index 688d48ec707..00000000000 --- a/tests/ui/consts/write_to_mut_ref_dest.stock.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: mutable references are not allowed in constants - --> $DIR/write_to_mut_ref_dest.rs:11:27 - | -LL | let b: *mut u32 = &mut a; - | ^^^^^^ - | - = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information - = help: add `#![feature(const_mut_refs)]` 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]: dereferencing raw mutable pointers in constants is unstable - --> $DIR/write_to_mut_ref_dest.rs:12:18 - | -LL | unsafe { *b = 5; } - | ^^^^^^ - | - = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information - = help: add `#![feature(const_mut_refs)]` 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 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr b/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr deleted file mode 100644 index cfee8fc44fe..00000000000 --- a/tests/ui/coroutine/coroutine-region-requirements.migrate.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/generator-region-requirements.rs:16:51 - | -LL | fn dangle(x: &mut i32) -> &'static mut i32 { - | -------- help: add explicit lifetime `'static` to the type of `x`: `&'static mut i32` -... -LL | GeneratorState::Complete(c) => return c, - | ^ lifetime `'static` required - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/coroutine/coroutine-resume-after-panic.rs b/tests/ui/coroutine/coroutine-resume-after-panic.rs index 2745ebc6132..1aa547c2a7b 100644 --- a/tests/ui/coroutine/coroutine-resume-after-panic.rs +++ b/tests/ui/coroutine/coroutine-resume-after-panic.rs @@ -1,7 +1,7 @@ //@ run-fail //@ needs-unwind //@ error-pattern:coroutine resumed after panicking -//@ ignore-emscripten no processes +//@ needs-subprocess // Test that we get the correct message for resuming a panicked coroutine. diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs new file mode 100644 index 00000000000..3a8d9c998cf --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_off.rs @@ -0,0 +1,29 @@ +//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g +//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=off +//@ check-pass + +//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm +//@[aarch64_gl] needs-llvm-components: aarch64 + +//@[i686_g] compile-flags: --target i686-pc-windows-gnu +//@[i686_g] needs-llvm-components: x86 + +//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm +//@[i686_gl] needs-llvm-components: x86 + +//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu +//@[i686_uwp_g] needs-llvm-components: x86 + +//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu +//@[x86_64_g] needs-llvm-components: x86 + +//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm +//@[x86_64_gl] needs-llvm-components: x86 + +//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu +//@[x86_64_uwp_g] needs-llvm-components: x86 + +#![feature(no_core)] + +#![no_core] +#![no_std] diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr new file mode 100644 index 00000000000..f3465e64976 --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.aarch64_gl.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=packed` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr new file mode 100644 index 00000000000..f3465e64976 --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_g.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=packed` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr new file mode 100644 index 00000000000..f3465e64976 --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_gl.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=packed` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr new file mode 100644 index 00000000000..f3465e64976 --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.i686_uwp_g.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=packed` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs new file mode 100644 index 00000000000..896bbac7d8e --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.rs @@ -0,0 +1,29 @@ +//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g +//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=packed +//@ error-pattern: error: `-Csplit-debuginfo=packed` is unstable on this platform + +//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm +//@[aarch64_gl] needs-llvm-components: aarch64 + +//@[i686_g] compile-flags: --target i686-pc-windows-gnu +//@[i686_g] needs-llvm-components: x86 + +//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm +//@[i686_gl] needs-llvm-components: x86 + +//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu +//@[i686_uwp_g] needs-llvm-components: x86 + +//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu +//@[x86_64_g] needs-llvm-components: x86 + +//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm +//@[x86_64_gl] needs-llvm-components: x86 + +//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu +//@[x86_64_uwp_g] needs-llvm-components: x86 + +#![feature(no_core)] + +#![no_core] +#![no_std] diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr new file mode 100644 index 00000000000..f3465e64976 --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_g.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=packed` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr new file mode 100644 index 00000000000..f3465e64976 --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_gl.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=packed` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr new file mode 100644 index 00000000000..f3465e64976 --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_packed.x86_64_uwp_g.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=packed` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr new file mode 100644 index 00000000000..0964e21b13b --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.aarch64_gl.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=unpacked` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr new file mode 100644 index 00000000000..0964e21b13b --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_g.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=unpacked` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr new file mode 100644 index 00000000000..0964e21b13b --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_gl.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=unpacked` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr new file mode 100644 index 00000000000..0964e21b13b --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.i686_uwp_g.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=unpacked` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs new file mode 100644 index 00000000000..54a88c91217 --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.rs @@ -0,0 +1,29 @@ +//@ revisions: aarch64_gl i686_g i686_gl i686_uwp_g x86_64_g x86_64_gl x86_64_uwp_g +//@ compile-flags: --crate-type cdylib -Csplit-debuginfo=unpacked +//@ error-pattern: error: `-Csplit-debuginfo=unpacked` is unstable on this platform + +//@[aarch64_gl] compile-flags: --target aarch64-pc-windows-gnullvm +//@[aarch64_gl] needs-llvm-components: aarch64 + +//@[i686_g] compile-flags: --target i686-pc-windows-gnu +//@[i686_g] needs-llvm-components: x86 + +//@[i686_gl] compile-flags: --target i686-pc-windows-gnullvm +//@[i686_gl] needs-llvm-components: x86 + +//@[i686_uwp_g] compile-flags: --target i686-uwp-windows-gnu +//@[i686_uwp_g] needs-llvm-components: x86 + +//@[x86_64_g] compile-flags: --target x86_64-pc-windows-gnu +//@[x86_64_g] needs-llvm-components: x86 + +//@[x86_64_gl] compile-flags: --target x86_64-pc-windows-gnullvm +//@[x86_64_gl] needs-llvm-components: x86 + +//@[x86_64_uwp_g] compile-flags: --target x86_64-uwp-windows-gnu +//@[x86_64_uwp_g] needs-llvm-components: x86 + +#![feature(no_core)] + +#![no_core] +#![no_std] diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr new file mode 100644 index 00000000000..0964e21b13b --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_g.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=unpacked` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr new file mode 100644 index 00000000000..0964e21b13b --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_gl.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=unpacked` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr new file mode 100644 index 00000000000..0964e21b13b --- /dev/null +++ b/tests/ui/debuginfo/windows_gnu_split_debuginfo_unpacked.x86_64_uwp_g.stderr @@ -0,0 +1,4 @@ +error: `-Csplit-debuginfo=unpacked` is unstable on this platform + +error: aborting due to 1 previous error + diff --git a/tests/ui/delegation/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs index f15e6aa81af..861f2b15da2 100644 --- a/tests/ui/delegation/bad-resolve.rs +++ b/tests/ui/delegation/bad-resolve.rs @@ -40,7 +40,7 @@ impl Trait for S { } mod prefix {} -reuse unresolved_prefix::{a, b, c}; //~ ERROR use of undeclared crate or module `unresolved_prefix` +reuse unresolved_prefix::{a, b, c}; //~ ERROR use of unresolved module or unlinked crate reuse prefix::{self, super, crate}; //~ ERROR `crate` in paths can only be used in start position fn main() {} diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index 32d2f3b26cb..966387e1d61 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -81,11 +81,13 @@ LL | type Type; LL | impl Trait for S { | ^^^^^^^^^^^^^^^^ missing `Type` in implementation -error[E0433]: failed to resolve: use of undeclared crate or module `unresolved_prefix` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `unresolved_prefix` --> $DIR/bad-resolve.rs:43:7 | LL | reuse unresolved_prefix::{a, b, c}; - | ^^^^^^^^^^^^^^^^^ use of undeclared crate or module `unresolved_prefix` + | ^^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `unresolved_prefix` + | + = help: you might be missing a crate named `unresolved_prefix` error[E0433]: failed to resolve: `crate` in paths can only be used in start position --> $DIR/bad-resolve.rs:44:29 diff --git a/tests/ui/delegation/glob-bad-path.rs b/tests/ui/delegation/glob-bad-path.rs index 7bc4f0153a3..4ac9d68e8dd 100644 --- a/tests/ui/delegation/glob-bad-path.rs +++ b/tests/ui/delegation/glob-bad-path.rs @@ -5,7 +5,7 @@ trait Trait {} struct S; impl Trait for u8 { - reuse unresolved::*; //~ ERROR failed to resolve: use of undeclared crate or module `unresolved` + reuse unresolved::*; //~ ERROR failed to resolve: use of unresolved module or unlinked crate `unresolved` reuse S::*; //~ ERROR expected trait, found struct `S` } diff --git a/tests/ui/delegation/glob-bad-path.stderr b/tests/ui/delegation/glob-bad-path.stderr index 0c06364b3f0..15d9ca41203 100644 --- a/tests/ui/delegation/glob-bad-path.stderr +++ b/tests/ui/delegation/glob-bad-path.stderr @@ -4,11 +4,11 @@ error: expected trait, found struct `S` LL | reuse S::*; | ^ not a trait -error[E0433]: failed to resolve: use of undeclared crate or module `unresolved` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `unresolved` --> $DIR/glob-bad-path.rs:8:11 | LL | reuse unresolved::*; - | ^^^^^^^^^^ use of undeclared crate or module `unresolved` + | ^^^^^^^^^^ use of unresolved module or unlinked crate `unresolved` error: aborting due to 2 previous errors diff --git a/tests/ui/deprecation/deprecation-lint.stderr b/tests/ui/deprecation/deprecation-lint.stderr index 2098073409d..95ae1b04d86 100644 --- a/tests/ui/deprecation/deprecation-lint.stderr +++ b/tests/ui/deprecation/deprecation-lint.stderr @@ -739,8 +739,11 @@ LL | _) error[E0451]: field `i` of struct `this_crate::nested::DeprecatedStruct` is private --> $DIR/deprecation-lint.rs:280:13 | +LL | let _ = nested::DeprecatedStruct { + | ------------------------ in this type +LL | LL | i: 0 - | ^^^^ private field + | ^ private field error: aborting due to 123 previous errors diff --git a/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.rs b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.rs new file mode 100644 index 00000000000..76b93c0c947 --- /dev/null +++ b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.rs @@ -0,0 +1,8 @@ +use std::rc::Rc; + +#[derive(PartialEq)] //~ NOTE in this expansion +pub struct Function { + callback: Rc<dyn Fn()>, //~ ERROR binary operation `==` cannot be applied to type `Rc<dyn Fn()>` +} + +fn main() {} diff --git a/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr new file mode 100644 index 00000000000..40464a49c34 --- /dev/null +++ b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr @@ -0,0 +1,14 @@ +error[E0369]: binary operation `==` cannot be applied to type `Rc<dyn Fn()>` + --> $DIR/do-not-suggest-calling-fn-in-derive-macro.rs:5:5 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | pub struct Function { +LL | callback: Rc<dyn Fn()>, + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.rs b/tests/ui/diagnostic-width/non-copy-type-moved.rs new file mode 100644 index 00000000000..a5593ad7b2a --- /dev/null +++ b/tests/ui/diagnostic-width/non-copy-type-moved.rs @@ -0,0 +1,17 @@ +//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +//@ normalize-stderr: "long-type-\d+" -> "long-type-hash" +type A = (String, String, String, String); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +trait Trait {} + +fn require_trait<T: Trait>() {} + +fn foo(x: D) { + let _a = x; + let _b = x; //~ ERROR use of moved value +} + +fn main() {} diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.stderr b/tests/ui/diagnostic-width/non-copy-type-moved.stderr new file mode 100644 index 00000000000..da9385a5b4d --- /dev/null +++ b/tests/ui/diagnostic-width/non-copy-type-moved.stderr @@ -0,0 +1,20 @@ +error[E0382]: use of moved value: `x` + --> $DIR/non-copy-type-moved.rs:14:14 + | +LL | fn foo(x: D) { + | - move occurs because `x` has type `((..., ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait +LL | let _a = x; + | - value moved here +LL | let _b = x; + | ^ value used here after move + | + = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/non-copy-type-moved/non-copy-type-moved.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console +help: consider cloning the value if the performance cost is acceptable + | +LL | let _a = x.clone(); + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/diagnostic-width/secondary-label-with-long-type.rs b/tests/ui/diagnostic-width/secondary-label-with-long-type.rs new file mode 100644 index 00000000000..6ed600c48ac --- /dev/null +++ b/tests/ui/diagnostic-width/secondary-label-with-long-type.rs @@ -0,0 +1,17 @@ +//@ compile-flags: --diagnostic-width=100 -Zwrite-long-types-to-disk=yes +//@ normalize-stderr: "long-type-\d+" -> "long-type-hash" +type A = (i32, i32, i32, i32); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +fn foo(x: D) { + let () = x; //~ ERROR mismatched types + //~^ NOTE this expression has type `((..., + //~| NOTE expected `((..., + //~| NOTE expected tuple + //~| NOTE the full type name has been written to + //~| NOTE consider using `--verbose` to print the full type name to the console +} + +fn main() {} diff --git a/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr b/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr new file mode 100644 index 00000000000..1e890455156 --- /dev/null +++ b/tests/ui/diagnostic-width/secondary-label-with-long-type.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/secondary-label-with-long-type.rs:9:9 + | +LL | let () = x; + | ^^ - this expression has type `((..., ..., ..., ...), ..., ..., ...)` + | | + | expected `((..., ..., ..., ...), ..., ..., ...)`, found `()` + | + = note: expected tuple `((..., ..., ..., ...), ..., ..., ...)` + found unit type `()` + = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/secondary-label-with-long-type/secondary-label-with-long-type.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/bad-assoc-ty.stderr b/tests/ui/did_you_mean/bad-assoc-ty.stderr index 41039ae82a6..5fc2f7c1fe6 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.stderr @@ -233,11 +233,6 @@ LL | fn foo<X: K<_, _>>(x: X) {} | ^ ^ not allowed in type signatures | | | not allowed in type signatures - | -help: use type parameters instead - | -LL | fn foo<X: K<T, T>, T>(x: X) {} - | ~ ~ +++ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/bad-assoc-ty.rs:54:34 diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs index c9a097d3610..9cd32ffeb6d 100644 --- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.rs @@ -2,6 +2,6 @@ fn main() { let _: &Copy + 'static; //~ ERROR expected a path - //~^ ERROR cannot be made into an object + //~^ ERROR is not dyn compatible let _: &'static Copy + 'static; //~ ERROR expected a path } diff --git a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr index 8ef0d178444..7994ddf11c3 100644 --- a/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr +++ b/tests/ui/did_you_mean/trait-object-reference-without-parens-suggestion.stderr @@ -20,14 +20,15 @@ help: try adding parentheses LL | let _: &'static (Copy + 'static); | + + -error[E0038]: the trait `Copy` cannot be made into an object +error[E0038]: the trait `Copy` is not dyn compatible --> $DIR/trait-object-reference-without-parens-suggestion.rs:4:12 | LL | let _: &Copy + 'static; - | ^^^^^ `Copy` cannot be made into an object + | ^^^^^ `Copy` is not dyn compatible | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> error: aborting due to 3 previous errors diff --git a/tests/ui/drop/drop-order-comparisons.e2021.fixed b/tests/ui/drop/drop-order-comparisons.e2021.fixed new file mode 100644 index 00000000000..78cf421cfbf --- /dev/null +++ b/tests/ui/drop/drop-order-comparisons.e2021.fixed @@ -0,0 +1,575 @@ +// This tests various aspects of the drop order with a focus on: +// +// - The lifetime of temporaries with the `if let` construct (and with +// various similar constructs) and how these lifetimes were shortened +// for `if let` in Rust 2024. +// +// - The shortening of the lifetimes of temporaries in tail +// expressions in Rust 2024. +// +// - The behavior of `let` chains and how this behavior compares to +// nested `if let` expressions and chained `let .. else` statements. +// +// In the tests below, `Events` tracks a sequence of numbered events. +// Calling `e.mark(..)` logs a numbered event immediately. Calling +// `e.ok(..)` or `e.err(..)` returns an `Ok(_)` or `Err(_)` value, +// respectively, and logs the numbered event when that value is +// dropped. Calling `e.assert()` verifies that the correct number of +// events were logged and that they were logged in the correct order. + +//@ revisions: e2021 e2024 +//@ [e2021] edition: 2021 +//@ [e2021] run-rustfix +//@ [e2021] rustfix-only-machine-applicable +//@ [e2024] edition: 2024 +//@ run-pass + +#![feature(let_chains)] +#![cfg_attr(e2021, warn(rust_2024_compatibility))] + +fn t_bindings() { + let e = Events::new(); + _ = { + e.mark(1); + let _v = e.ok(8); + let _v = e.ok(2).is_ok(); + let _ = e.ok(3); + let Ok(_) = e.ok(4) else { unreachable!() }; + let Ok(_) = e.ok(5).as_ref() else { unreachable!() }; + let _v = e.ok(7); + e.mark(6); + }; + e.assert(8); +} + +fn t_tuples() { + let e = Events::new(); + _ = (e.ok(1), e.ok(4).is_ok(), e.ok(2), e.ok(3).is_ok()); + e.assert(4); +} + +fn t_arrays() { + let e = Events::new(); + trait Tr {} + impl<T> Tr for T {} + fn b<'a, T: 'a>(x: T) -> Box<dyn Tr + 'a> { + Box::new(x) + } + _ = [b(e.ok(1)), b(e.ok(4).is_ok()), b(e.ok(2)), b(e.ok(3).is_ok())]; + e.assert(4); +} + +fn t_fncalls() { + let e = Events::new(); + let f = |_, _, _, _| {}; + _ = f(e.ok(2), e.ok(4).is_ok(), e.ok(1), e.ok(3).is_ok()); + e.assert(4); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_tailexpr_bindings() { + let e = Events::new(); + _ = ({ + let _v = e.ok(2); + let _v = e.ok(1); + e.ok(5).is_ok() + //[e2021]~^ WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + }, e.mark(3), e.ok(4)); + e.assert(5); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_tailexpr_bindings() { + let e = Events::new(); + _ = ({ + let _v = e.ok(3); + let _v = e.ok(2); + e.ok(1).is_ok() + }, e.mark(4), e.ok(5)); + e.assert(5); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_tailexpr_tuples() { + let e = Events::new(); + _ = ({ + (e.ok(2), e.ok(6).is_ok(), e.ok(3), e.ok(5).is_ok()) + //[e2021]~^ WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + //[e2021]~| WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + }, e.mark(1), e.ok(4)); + e.assert(6); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_tailexpr_tuples() { + let e = Events::new(); + _ = ({ + (e.ok(4), e.ok(2).is_ok(), e.ok(5), e.ok(1).is_ok()) + }, e.mark(3), e.ok(6)); + e.assert(6); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_then() { + let e = Events::new(); + _ = (match e.ok(4).as_ref() { Ok(_) => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(1); + } _ => {}}, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_then() { + let e = Events::new(); + _ = (if let Ok(_) = e.ok(2).as_ref() { + e.mark(1); + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_else() { + let e = Events::new(); + _ = (match e.err(4).as_ref() { Ok(_) => {} _ => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(1); + }}, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_else() { + let e = Events::new(); + _ = (if let Ok(_) = e.err(1).as_ref() {} else { + e.mark(2); + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_match_then() { + let e = Events::new(); + _ = (match e.ok(4).as_ref() { + Ok(_) => e.mark(1), + _ => unreachable!(), + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_match_else() { + let e = Events::new(); + _ = (match e.err(4).as_ref() { + Ok(_) => unreachable!(), + _ => e.mark(1), + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_let_else_then() { + let e = Events::new(); + _ = ('top: { + 'chain: { + let Ok(_) = e.ok(1).as_ref() else { break 'chain }; + // The "then" branch: + e.mark(2); + break 'top; + } + // The "else" branch: + unreachable!() + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_let_else_else() { + let e = Events::new(); + _ = ('top: { + 'chain: { + let Ok(_) = e.err(1).as_ref() else { break 'chain }; + // The "then" branch: + unreachable!(); + #[allow(unreachable_code)] + break 'top; + } + // The "else" branch: + e.mark(2); + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_then_tailexpr() { + let e = Events::new(); + _ = ({ + if let Ok(_) = e.ok(4).as_ref() { + //[e2021]~^ WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(1); + } + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_then_tailexpr() { + let e = Events::new(); + _ = ({ + if let Ok(_) = e.ok(2).as_ref() { + e.mark(1); + } + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_else_tailexpr() { + let e = Events::new(); + _ = ({ + match e.err(4).as_ref() { Ok(_) => {} _ => { + //[e2021]~^ WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + //[e2021]~| WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(1); + }} + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_else_tailexpr() { + let e = Events::new(); + _ = ({ + if let Ok(_) = e.err(1).as_ref() {} else { + e.mark(2); + } + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_if_let_nested_then() { + let e = Events::new(); + _ = { + // The unusual formatting, here and below, is to make the + // comparison with `let` chains more direct. + if e.ok(1).is_ok() { + if let true = e.ok(9).is_ok() { + if let Ok(_v) = e.ok(8) { + if let Ok(_) = e.ok(7) { + if let Ok(_) = e.ok(6).as_ref() { + if e.ok(2).is_ok() { + if let Ok(_v) = e.ok(5) { + if let Ok(_) = e.ok(4).as_ref() { + e.mark(3); + }}}}}}}} + }; + e.assert(9); +} + +#[rustfmt::skip] +fn t_let_else_chained_then() { + let e = Events::new(); + _ = 'top: { + 'chain: { + if e.ok(1).is_ok() {} else { break 'chain }; + let true = e.ok(2).is_ok() else { break 'chain }; + let Ok(_v) = e.ok(9) else { break 'chain }; + let Ok(_) = e.ok(3) else { break 'chain }; + let Ok(_) = e.ok(4).as_ref() else { break 'chain }; + if e.ok(5).is_ok() {} else { break 'chain }; + let Ok(_v) = e.ok(8) else { break 'chain }; + let Ok(_) = e.ok(6).as_ref() else { break 'chain }; + // The "then" branch: + e.mark(7); + break 'top; + } + // The "else" branch: + unreachable!() + }; + e.assert(9); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_chains_then() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(9).is_ok() + && let Ok(_v) = e.ok(5) + && let Ok(_) = e.ok(8) + && let Ok(_) = e.ok(7).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(4) + && let Ok(_) = e.ok(6).as_ref() { + e.mark(3); + }; + e.assert(9); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_chains_then() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(9).is_ok() + && let Ok(_v) = e.ok(8) + && let Ok(_) = e.ok(7) + && let Ok(_) = e.ok(6).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(5) + && let Ok(_) = e.ok(4).as_ref() { + e.mark(3); + }; + e.assert(9); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_nested_else() { + let e = Events::new(); + _ = if e.err(1).is_ok() {} else { + match e.err(9).is_ok() { true => {} _ => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + match e.err(8) { Ok(_v) => {} _ => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + match e.err(7) { Ok(_) => {} _ => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + match e.err(6).as_ref() { Ok(_) => {} _ => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + if e.err(2).is_ok() {} else { + match e.err(5) { Ok(_v) => {} _ => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + match e.err(4) { Ok(_) => {} _ => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(3); + }}}}}}}}}}}}}}; + e.assert(9); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_nested_else() { + let e = Events::new(); + _ = if e.err(1).is_ok() {} else { + if let true = e.err(2).is_ok() {} else { + if let Ok(_v) = e.err(3) {} else { + if let Ok(_) = e.err(4) {} else { + if let Ok(_) = e.err(5).as_ref() {} else { + if e.err(6).is_ok() {} else { + if let Ok(_v) = e.err(7) {} else { + if let Ok(_) = e.err(8) {} else { + e.mark(9); + }}}}}}}}; + e.assert(9); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_nested_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() { + if let true = e.ok(9).is_ok() { + if let Ok(_v) = e.ok(8) { + if let Ok(_) = e.ok(7) { + if let Ok(_) = e.ok(6).as_ref() { + if e.ok(2).is_ok() { + if let Ok(_v) = e.ok(5) { + match e.err(4).as_ref() { Ok(_) => {} _ => { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(3); + }}}}}}}}}; + e.assert(9); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_nested_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() { + if let true = e.ok(9).is_ok() { + if let Ok(_v) = e.ok(8) { + if let Ok(_) = e.ok(7) { + if let Ok(_) = e.ok(6).as_ref() { + if e.ok(2).is_ok() { + if let Ok(_v) = e.ok(5) { + if let Ok(_) = e.err(3).as_ref() {} else { + e.mark(4); + }}}}}}}}; + e.assert(9); +} + +#[rustfmt::skip] +fn t_let_else_chained_then_else() { + let e = Events::new(); + _ = 'top: { + 'chain: { + if e.ok(1).is_ok() {} else { break 'chain }; + let true = e.ok(2).is_ok() else { break 'chain }; + let Ok(_v) = e.ok(8) else { break 'chain }; + let Ok(_) = e.ok(3) else { break 'chain }; + let Ok(_) = e.ok(4).as_ref() else { break 'chain }; + if e.ok(5).is_ok() {} else { break 'chain }; + let Ok(_v) = e.ok(7) else { break 'chain }; + let Ok(_) = e.err(6).as_ref() else { break 'chain }; + // The "then" branch: + unreachable!(); + #[allow(unreachable_code)] + break 'top; + } + // The "else" branch: + e.mark(9); + }; + e.assert(9); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_chains_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(9).is_ok() + && let Ok(_v) = e.ok(4) + && let Ok(_) = e.ok(8) + && let Ok(_) = e.ok(7).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(3) + && let Ok(_) = e.err(6) {} else { + e.mark(5); + }; + e.assert(9); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_chains_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(8).is_ok() + && let Ok(_v) = e.ok(7) + && let Ok(_) = e.ok(6) + && let Ok(_) = e.ok(5).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(4) + && let Ok(_) = e.err(3) {} else { + e.mark(9); + }; + e.assert(9); +} + +fn main() { + t_bindings(); + t_tuples(); + t_arrays(); + t_fncalls(); + t_tailexpr_bindings(); + t_tailexpr_tuples(); + t_if_let_then(); + t_if_let_else(); + t_match_then(); + t_match_else(); + t_let_else_then(); + t_let_else_else(); + t_if_let_then_tailexpr(); + t_if_let_else_tailexpr(); + t_if_let_nested_then(); + t_let_else_chained_then(); + t_if_let_chains_then(); + t_if_let_nested_else(); + t_if_let_nested_then_else(); + t_let_else_chained_then_else(); + t_if_let_chains_then_else(); +} + +// # Test scaffolding + +use core::cell::RefCell; +use std::collections::HashSet; + +/// A buffer to track the order of events. +/// +/// First, numbered events are logged into this buffer. +/// +/// Then, `assert` is called to verify that the correct number of +/// events were logged, and that they were logged in the expected +/// order. +struct Events(RefCell<Option<Vec<u64>>>); + +impl Events { + const fn new() -> Self { + Self(RefCell::new(Some(Vec::new()))) + } + #[track_caller] + fn assert(&self, max: u64) { + let buf = &self.0; + let v1 = buf.borrow().as_ref().unwrap().clone(); + let mut v2 = buf.borrow().as_ref().unwrap().clone(); + *buf.borrow_mut() = None; + v2.sort(); + let uniq_len = v2.iter().collect::<HashSet<_>>().len(); + // Check that the sequence is sorted. + assert_eq!(v1, v2); + // Check that there are no duplicates. + assert_eq!(v2.len(), uniq_len); + // Check that the length is the expected one. + assert_eq!(max, uniq_len as u64); + // Check that the last marker is the expected one. + assert_eq!(v2.last().unwrap(), &max); + } + /// Return an `Ok` value that logs its drop. + fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> { + Ok(LogDrop(self, m)) + } + /// Return an `Err` value that logs its drop. + fn err(&self, m: u64) -> Result<LogDrop, LogDrop> { + Err(LogDrop(self, m)) + } + /// Log an event. + fn mark(&self, m: u64) { + self.0.borrow_mut().as_mut().unwrap().push(m); + } +} + +impl Drop for Events { + fn drop(&mut self) { + if self.0.borrow().is_some() { + panic!("failed to call `Events::assert()`"); + } + } +} + +/// A type that logs its drop events. +struct LogDrop<'b>(&'b Events, u64); + +impl<'b> Drop for LogDrop<'b> { + fn drop(&mut self) { + self.0.mark(self.1); + } +} diff --git a/tests/ui/drop/drop-order-comparisons.e2021.stderr b/tests/ui/drop/drop-order-comparisons.e2021.stderr new file mode 100644 index 00000000000..158d18f6882 --- /dev/null +++ b/tests/ui/drop/drop-order-comparisons.e2021.stderr @@ -0,0 +1,477 @@ +warning: relative drop order changing in Rust 2024 + --> $DIR/drop-order-comparisons.rs:76:9 + | +LL | _ = ({ + | _________- +LL | | let _v = e.ok(2); + | | -- + | | | + | | `_v` calls a custom destructor + | | `_v` will be dropped later as of Edition 2024 +LL | | let _v = e.ok(1); + | | -- + | | | + | | this value will be stored in a temporary; let us call it `#2` + | | `#2` will be dropped later as of Edition 2024 +LL | | e.ok(5).is_ok() + | | ^^^^^^^ + | | | + | | this value will be stored in a temporary; let us call it `#3` + | | up until Edition 2021 `#3` is dropped last but will be dropped earlier in Edition 2024 +... | +LL | | }, e.mark(3), e.ok(4)); + | | - + | | | + | | now the temporary value is dropped here, before the local variables in the block or statement + | |__________________________this value will be stored in a temporary; let us call it `#1` + | `#1` will be dropped later as of Edition 2024 + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> +note: `#3` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ +note: `#1` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ +note: `_v` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ +note: `#2` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages +note: the lint level is defined here + --> $DIR/drop-order-comparisons.rs:28:25 + | +LL | #![cfg_attr(e2021, warn(rust_2024_compatibility))] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[warn(tail_expr_drop_order)]` implied by `#[warn(rust_2024_compatibility)]` + +warning: relative drop order changing in Rust 2024 + --> $DIR/drop-order-comparisons.rs:100:45 + | +LL | _ = ({ + | _________- +LL | | (e.ok(2), e.ok(6).is_ok(), e.ok(3), e.ok(5).is_ok()) + | | ^^^^^^^ + | | | + | | this value will be stored in a temporary; let us call it `#2` + | | up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024 +... | +LL | | }, e.mark(1), e.ok(4)); + | | - + | | | + | | now the temporary value is dropped here, before the local variables in the block or statement + | |__________________________this value will be stored in a temporary; let us call it `#1` + | `#1` will be dropped later as of Edition 2024 + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> +note: `#2` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ +note: `#1` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +warning: relative drop order changing in Rust 2024 + --> $DIR/drop-order-comparisons.rs:100:19 + | +LL | _ = ({ + | _________- +LL | | (e.ok(2), e.ok(6).is_ok(), e.ok(3), e.ok(5).is_ok()) + | | ^^^^^^^ + | | | + | | this value will be stored in a temporary; let us call it `#2` + | | up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024 +... | +LL | | }, e.mark(1), e.ok(4)); + | | - + | | | + | | now the temporary value is dropped here, before the local variables in the block or statement + | |__________________________this value will be stored in a temporary; let us call it `#1` + | `#1` will be dropped later as of Edition 2024 + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> +note: `#2` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ +note: `#1` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +warning: relative drop order changing in Rust 2024 + --> $DIR/drop-order-comparisons.rs:221:24 + | +LL | _ = ({ + | _________- +LL | | if let Ok(_) = e.ok(4).as_ref() { + | | ^^^^^^^ + | | | + | | this value will be stored in a temporary; let us call it `#2` + | | up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024 +... | +LL | | }, e.mark(2), e.ok(3)); + | | - + | | | + | | now the temporary value is dropped here, before the local variables in the block or statement + | |__________________________this value will be stored in a temporary; let us call it `#1` + | `#1` will be dropped later as of Edition 2024 + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> +note: `#2` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ +note: `#1` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +warning: relative drop order changing in Rust 2024 + --> $DIR/drop-order-comparisons.rs:247:24 + | +LL | _ = ({ + | _________- +LL | | if let Ok(_) = e.err(4).as_ref() {} else { + | | ^^^^^^^^ + | | | + | | this value will be stored in a temporary; let us call it `#2` + | | up until Edition 2021 `#2` is dropped last but will be dropped earlier in Edition 2024 +... | +LL | | }, e.mark(2), e.ok(3)); + | | - + | | | + | | now the temporary value is dropped here, before the local variables in the block or statement + | |__________________________this value will be stored in a temporary; let us call it `#1` + | `#1` will be dropped later as of Edition 2024 + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-tail-expr-scope.html> +note: `#2` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ +note: `#1` invokes this custom destructor + --> $DIR/drop-order-comparisons.rs:571:1 + | +LL | / impl<'b> Drop for LogDrop<'b> { +LL | | fn drop(&mut self) { +LL | | self.0.mark(self.1); +LL | | } +LL | | } + | |_^ + = note: most of the time, changing drop order is harmless; inspect the `impl Drop`s for side effects like releasing locks or sending messages + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:123:13 + | +LL | _ = (if let Ok(_) = e.ok(4).as_ref() { + | ^^^^^^^^^^^^-------^^^^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:127:5 + | +LL | }, e.mark(2), e.ok(3)); + | ^ + = note: `#[warn(if_let_rescope)]` implied by `#[warn(rust_2024_compatibility)]` +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ _ = (match e.ok(4).as_ref() { Ok(_) => { +LL | +LL | +LL | e.mark(1); +LL ~ } _ => {}}, e.mark(2), e.ok(3)); + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:145:13 + | +LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else { + | ^^^^^^^^^^^^--------^^^^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:145:44 + | +LL | _ = (if let Ok(_) = e.err(4).as_ref() {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ _ = (match e.err(4).as_ref() { Ok(_) => {} _ => { +LL | +LL | +LL | e.mark(1); +LL ~ }}, e.mark(2), e.ok(3)); + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:247:12 + | +LL | if let Ok(_) = e.err(4).as_ref() {} else { + | ^^^^^^^^^^^^--------^^^^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:247:43 + | +LL | if let Ok(_) = e.err(4).as_ref() {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ match e.err(4).as_ref() { Ok(_) => {} _ => { +LL | +... +LL | e.mark(1); +LL ~ }} + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:352:12 + | +LL | if let true = e.err(9).is_ok() {} else { + | ^^^^^^^^^^^--------^^^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:352:41 + | +LL | if let true = e.err(9).is_ok() {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ match e.err(9).is_ok() { true => {} _ => { +LL | +... +LL | e.mark(3); +LL ~ }}}}}}}}}; + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:355:12 + | +LL | if let Ok(_v) = e.err(8) {} else { + | ^^^^^^^^^^^^^-------- + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:355:35 + | +LL | if let Ok(_v) = e.err(8) {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ match e.err(8) { Ok(_v) => {} _ => { +LL | +... +LL | e.mark(3); +LL ~ }}}}}}}}}; + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:358:12 + | +LL | if let Ok(_) = e.err(7) {} else { + | ^^^^^^^^^^^^-------- + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:358:34 + | +LL | if let Ok(_) = e.err(7) {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ match e.err(7) { Ok(_) => {} _ => { +LL | +... +LL | e.mark(3); +LL ~ }}}}}}}}}; + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:361:12 + | +LL | if let Ok(_) = e.err(6).as_ref() {} else { + | ^^^^^^^^^^^^--------^^^^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:361:43 + | +LL | if let Ok(_) = e.err(6).as_ref() {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ match e.err(6).as_ref() { Ok(_) => {} _ => { +LL | +... +LL | e.mark(3); +LL ~ }}}}}}}}}; + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:365:12 + | +LL | if let Ok(_v) = e.err(5) {} else { + | ^^^^^^^^^^^^^-------- + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:365:35 + | +LL | if let Ok(_v) = e.err(5) {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ match e.err(5) { Ok(_v) => {} _ => { +LL | +... +LL | e.mark(3); +LL ~ }}}}}}}}}; + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:368:12 + | +LL | if let Ok(_) = e.err(4) {} else { + | ^^^^^^^^^^^^-------- + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:368:34 + | +LL | if let Ok(_) = e.err(4) {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ match e.err(4) { Ok(_) => {} _ => { +LL | +LL | +LL | e.mark(3); +LL ~ }}}}}}}}}; + | + +warning: `if let` assigns a shorter lifetime since Edition 2024 + --> $DIR/drop-order-comparisons.rs:404:12 + | +LL | if let Ok(_) = e.err(4).as_ref() {} else { + | ^^^^^^^^^^^^--------^^^^^^^^^ + | | + | this value has a significant drop implementation which may observe a major change in drop order and requires your discretion + | + = warning: this changes meaning in Rust 2024 + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/temporary-if-let-scope.html> +help: the value is now dropped here in Edition 2024 + --> $DIR/drop-order-comparisons.rs:404:43 + | +LL | if let Ok(_) = e.err(4).as_ref() {} else { + | ^ +help: a `match` with a single arm can preserve the drop order up to Edition 2021 + | +LL ~ match e.err(4).as_ref() { Ok(_) => {} _ => { +LL | +LL | +LL | e.mark(3); +LL ~ }}}}}}}}}; + | + +warning: 15 warnings emitted + diff --git a/tests/ui/drop/drop-order-comparisons.rs b/tests/ui/drop/drop-order-comparisons.rs new file mode 100644 index 00000000000..78c75a9449f --- /dev/null +++ b/tests/ui/drop/drop-order-comparisons.rs @@ -0,0 +1,575 @@ +// This tests various aspects of the drop order with a focus on: +// +// - The lifetime of temporaries with the `if let` construct (and with +// various similar constructs) and how these lifetimes were shortened +// for `if let` in Rust 2024. +// +// - The shortening of the lifetimes of temporaries in tail +// expressions in Rust 2024. +// +// - The behavior of `let` chains and how this behavior compares to +// nested `if let` expressions and chained `let .. else` statements. +// +// In the tests below, `Events` tracks a sequence of numbered events. +// Calling `e.mark(..)` logs a numbered event immediately. Calling +// `e.ok(..)` or `e.err(..)` returns an `Ok(_)` or `Err(_)` value, +// respectively, and logs the numbered event when that value is +// dropped. Calling `e.assert()` verifies that the correct number of +// events were logged and that they were logged in the correct order. + +//@ revisions: e2021 e2024 +//@ [e2021] edition: 2021 +//@ [e2021] run-rustfix +//@ [e2021] rustfix-only-machine-applicable +//@ [e2024] edition: 2024 +//@ run-pass + +#![feature(let_chains)] +#![cfg_attr(e2021, warn(rust_2024_compatibility))] + +fn t_bindings() { + let e = Events::new(); + _ = { + e.mark(1); + let _v = e.ok(8); + let _v = e.ok(2).is_ok(); + let _ = e.ok(3); + let Ok(_) = e.ok(4) else { unreachable!() }; + let Ok(_) = e.ok(5).as_ref() else { unreachable!() }; + let _v = e.ok(7); + e.mark(6); + }; + e.assert(8); +} + +fn t_tuples() { + let e = Events::new(); + _ = (e.ok(1), e.ok(4).is_ok(), e.ok(2), e.ok(3).is_ok()); + e.assert(4); +} + +fn t_arrays() { + let e = Events::new(); + trait Tr {} + impl<T> Tr for T {} + fn b<'a, T: 'a>(x: T) -> Box<dyn Tr + 'a> { + Box::new(x) + } + _ = [b(e.ok(1)), b(e.ok(4).is_ok()), b(e.ok(2)), b(e.ok(3).is_ok())]; + e.assert(4); +} + +fn t_fncalls() { + let e = Events::new(); + let f = |_, _, _, _| {}; + _ = f(e.ok(2), e.ok(4).is_ok(), e.ok(1), e.ok(3).is_ok()); + e.assert(4); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_tailexpr_bindings() { + let e = Events::new(); + _ = ({ + let _v = e.ok(2); + let _v = e.ok(1); + e.ok(5).is_ok() + //[e2021]~^ WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + }, e.mark(3), e.ok(4)); + e.assert(5); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_tailexpr_bindings() { + let e = Events::new(); + _ = ({ + let _v = e.ok(3); + let _v = e.ok(2); + e.ok(1).is_ok() + }, e.mark(4), e.ok(5)); + e.assert(5); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_tailexpr_tuples() { + let e = Events::new(); + _ = ({ + (e.ok(2), e.ok(6).is_ok(), e.ok(3), e.ok(5).is_ok()) + //[e2021]~^ WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + //[e2021]~| WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + }, e.mark(1), e.ok(4)); + e.assert(6); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_tailexpr_tuples() { + let e = Events::new(); + _ = ({ + (e.ok(4), e.ok(2).is_ok(), e.ok(5), e.ok(1).is_ok()) + }, e.mark(3), e.ok(6)); + e.assert(6); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_then() { + let e = Events::new(); + _ = (if let Ok(_) = e.ok(4).as_ref() { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(1); + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_then() { + let e = Events::new(); + _ = (if let Ok(_) = e.ok(2).as_ref() { + e.mark(1); + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_else() { + let e = Events::new(); + _ = (if let Ok(_) = e.err(4).as_ref() {} else { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(1); + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_else() { + let e = Events::new(); + _ = (if let Ok(_) = e.err(1).as_ref() {} else { + e.mark(2); + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_match_then() { + let e = Events::new(); + _ = (match e.ok(4).as_ref() { + Ok(_) => e.mark(1), + _ => unreachable!(), + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_match_else() { + let e = Events::new(); + _ = (match e.err(4).as_ref() { + Ok(_) => unreachable!(), + _ => e.mark(1), + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_let_else_then() { + let e = Events::new(); + _ = ('top: { + 'chain: { + let Ok(_) = e.ok(1).as_ref() else { break 'chain }; + // The "then" branch: + e.mark(2); + break 'top; + } + // The "else" branch: + unreachable!() + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_let_else_else() { + let e = Events::new(); + _ = ('top: { + 'chain: { + let Ok(_) = e.err(1).as_ref() else { break 'chain }; + // The "then" branch: + unreachable!(); + #[allow(unreachable_code)] + break 'top; + } + // The "else" branch: + e.mark(2); + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_then_tailexpr() { + let e = Events::new(); + _ = ({ + if let Ok(_) = e.ok(4).as_ref() { + //[e2021]~^ WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(1); + } + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_then_tailexpr() { + let e = Events::new(); + _ = ({ + if let Ok(_) = e.ok(2).as_ref() { + e.mark(1); + } + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_else_tailexpr() { + let e = Events::new(); + _ = ({ + if let Ok(_) = e.err(4).as_ref() {} else { + //[e2021]~^ WARN relative drop order changing in Rust 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + //[e2021]~| WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(1); + } + }, e.mark(2), e.ok(3)); + e.assert(4); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_else_tailexpr() { + let e = Events::new(); + _ = ({ + if let Ok(_) = e.err(1).as_ref() {} else { + e.mark(2); + } + }, e.mark(3), e.ok(4)); + e.assert(4); +} + +#[rustfmt::skip] +fn t_if_let_nested_then() { + let e = Events::new(); + _ = { + // The unusual formatting, here and below, is to make the + // comparison with `let` chains more direct. + if e.ok(1).is_ok() { + if let true = e.ok(9).is_ok() { + if let Ok(_v) = e.ok(8) { + if let Ok(_) = e.ok(7) { + if let Ok(_) = e.ok(6).as_ref() { + if e.ok(2).is_ok() { + if let Ok(_v) = e.ok(5) { + if let Ok(_) = e.ok(4).as_ref() { + e.mark(3); + }}}}}}}} + }; + e.assert(9); +} + +#[rustfmt::skip] +fn t_let_else_chained_then() { + let e = Events::new(); + _ = 'top: { + 'chain: { + if e.ok(1).is_ok() {} else { break 'chain }; + let true = e.ok(2).is_ok() else { break 'chain }; + let Ok(_v) = e.ok(9) else { break 'chain }; + let Ok(_) = e.ok(3) else { break 'chain }; + let Ok(_) = e.ok(4).as_ref() else { break 'chain }; + if e.ok(5).is_ok() {} else { break 'chain }; + let Ok(_v) = e.ok(8) else { break 'chain }; + let Ok(_) = e.ok(6).as_ref() else { break 'chain }; + // The "then" branch: + e.mark(7); + break 'top; + } + // The "else" branch: + unreachable!() + }; + e.assert(9); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_chains_then() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(9).is_ok() + && let Ok(_v) = e.ok(5) + && let Ok(_) = e.ok(8) + && let Ok(_) = e.ok(7).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(4) + && let Ok(_) = e.ok(6).as_ref() { + e.mark(3); + }; + e.assert(9); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_chains_then() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(9).is_ok() + && let Ok(_v) = e.ok(8) + && let Ok(_) = e.ok(7) + && let Ok(_) = e.ok(6).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(5) + && let Ok(_) = e.ok(4).as_ref() { + e.mark(3); + }; + e.assert(9); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_nested_else() { + let e = Events::new(); + _ = if e.err(1).is_ok() {} else { + if let true = e.err(9).is_ok() {} else { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + if let Ok(_v) = e.err(8) {} else { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + if let Ok(_) = e.err(7) {} else { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + if let Ok(_) = e.err(6).as_ref() {} else { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + if e.err(2).is_ok() {} else { + if let Ok(_v) = e.err(5) {} else { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + if let Ok(_) = e.err(4) {} else { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(3); + }}}}}}}}; + e.assert(9); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_nested_else() { + let e = Events::new(); + _ = if e.err(1).is_ok() {} else { + if let true = e.err(2).is_ok() {} else { + if let Ok(_v) = e.err(3) {} else { + if let Ok(_) = e.err(4) {} else { + if let Ok(_) = e.err(5).as_ref() {} else { + if e.err(6).is_ok() {} else { + if let Ok(_v) = e.err(7) {} else { + if let Ok(_) = e.err(8) {} else { + e.mark(9); + }}}}}}}}; + e.assert(9); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_nested_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() { + if let true = e.ok(9).is_ok() { + if let Ok(_v) = e.ok(8) { + if let Ok(_) = e.ok(7) { + if let Ok(_) = e.ok(6).as_ref() { + if e.ok(2).is_ok() { + if let Ok(_v) = e.ok(5) { + if let Ok(_) = e.err(4).as_ref() {} else { + //[e2021]~^ WARN if let` assigns a shorter lifetime since Edition 2024 + //[e2021]~| WARN this changes meaning in Rust 2024 + e.mark(3); + }}}}}}}}; + e.assert(9); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_nested_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() { + if let true = e.ok(9).is_ok() { + if let Ok(_v) = e.ok(8) { + if let Ok(_) = e.ok(7) { + if let Ok(_) = e.ok(6).as_ref() { + if e.ok(2).is_ok() { + if let Ok(_v) = e.ok(5) { + if let Ok(_) = e.err(3).as_ref() {} else { + e.mark(4); + }}}}}}}}; + e.assert(9); +} + +#[rustfmt::skip] +fn t_let_else_chained_then_else() { + let e = Events::new(); + _ = 'top: { + 'chain: { + if e.ok(1).is_ok() {} else { break 'chain }; + let true = e.ok(2).is_ok() else { break 'chain }; + let Ok(_v) = e.ok(8) else { break 'chain }; + let Ok(_) = e.ok(3) else { break 'chain }; + let Ok(_) = e.ok(4).as_ref() else { break 'chain }; + if e.ok(5).is_ok() {} else { break 'chain }; + let Ok(_v) = e.ok(7) else { break 'chain }; + let Ok(_) = e.err(6).as_ref() else { break 'chain }; + // The "then" branch: + unreachable!(); + #[allow(unreachable_code)] + break 'top; + } + // The "else" branch: + e.mark(9); + }; + e.assert(9); +} + +#[cfg(e2021)] +#[rustfmt::skip] +fn t_if_let_chains_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(9).is_ok() + && let Ok(_v) = e.ok(4) + && let Ok(_) = e.ok(8) + && let Ok(_) = e.ok(7).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(3) + && let Ok(_) = e.err(6) {} else { + e.mark(5); + }; + e.assert(9); +} + +#[cfg(e2024)] +#[rustfmt::skip] +fn t_if_let_chains_then_else() { + let e = Events::new(); + _ = if e.ok(1).is_ok() + && let true = e.ok(8).is_ok() + && let Ok(_v) = e.ok(7) + && let Ok(_) = e.ok(6) + && let Ok(_) = e.ok(5).as_ref() + && e.ok(2).is_ok() + && let Ok(_v) = e.ok(4) + && let Ok(_) = e.err(3) {} else { + e.mark(9); + }; + e.assert(9); +} + +fn main() { + t_bindings(); + t_tuples(); + t_arrays(); + t_fncalls(); + t_tailexpr_bindings(); + t_tailexpr_tuples(); + t_if_let_then(); + t_if_let_else(); + t_match_then(); + t_match_else(); + t_let_else_then(); + t_let_else_else(); + t_if_let_then_tailexpr(); + t_if_let_else_tailexpr(); + t_if_let_nested_then(); + t_let_else_chained_then(); + t_if_let_chains_then(); + t_if_let_nested_else(); + t_if_let_nested_then_else(); + t_let_else_chained_then_else(); + t_if_let_chains_then_else(); +} + +// # Test scaffolding + +use core::cell::RefCell; +use std::collections::HashSet; + +/// A buffer to track the order of events. +/// +/// First, numbered events are logged into this buffer. +/// +/// Then, `assert` is called to verify that the correct number of +/// events were logged, and that they were logged in the expected +/// order. +struct Events(RefCell<Option<Vec<u64>>>); + +impl Events { + const fn new() -> Self { + Self(RefCell::new(Some(Vec::new()))) + } + #[track_caller] + fn assert(&self, max: u64) { + let buf = &self.0; + let v1 = buf.borrow().as_ref().unwrap().clone(); + let mut v2 = buf.borrow().as_ref().unwrap().clone(); + *buf.borrow_mut() = None; + v2.sort(); + let uniq_len = v2.iter().collect::<HashSet<_>>().len(); + // Check that the sequence is sorted. + assert_eq!(v1, v2); + // Check that there are no duplicates. + assert_eq!(v2.len(), uniq_len); + // Check that the length is the expected one. + assert_eq!(max, uniq_len as u64); + // Check that the last marker is the expected one. + assert_eq!(v2.last().unwrap(), &max); + } + /// Return an `Ok` value that logs its drop. + fn ok(&self, m: u64) -> Result<LogDrop<'_>, LogDrop<'_>> { + Ok(LogDrop(self, m)) + } + /// Return an `Err` value that logs its drop. + fn err(&self, m: u64) -> Result<LogDrop, LogDrop> { + Err(LogDrop(self, m)) + } + /// Log an event. + fn mark(&self, m: u64) { + self.0.borrow_mut().as_mut().unwrap().push(m); + } +} + +impl Drop for Events { + fn drop(&mut self) { + if self.0.borrow().is_some() { + panic!("failed to call `Events::assert()`"); + } + } +} + +/// A type that logs its drop events. +struct LogDrop<'b>(&'b Events, u64); + +impl<'b> Drop for LogDrop<'b> { + fn drop(&mut self) { + self.0.mark(self.1); + } +} diff --git a/tests/ui/drop/drop-trait-enum.rs b/tests/ui/drop/drop-trait-enum.rs index 91b5bcdf730..5a88d959ec6 100644 --- a/tests/ui/drop/drop-trait-enum.rs +++ b/tests/ui/drop/drop-trait-enum.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] #![allow(unused_assignments)] #![allow(unused_variables)] -//@ ignore-emscripten no threads support +//@ needs-threads //@ needs-unwind use std::thread; diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr index d73a878c74f..029d5c74929 100644 --- a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr @@ -2,7 +2,7 @@ error: `if let` assigns a shorter lifetime since Edition 2024 --> $DIR/lint-if-let-rescope-with-macro.rs:12:12 | LL | if let $p = $e { $($conseq)* } else { $($alt)* } - | ^^^ + | ^^^^^^^^^^^ ... LL | / edition_2021_if_let! { LL | | Some(_value), diff --git a/tests/ui/drop/terminate-in-initializer.rs b/tests/ui/drop/terminate-in-initializer.rs index 23169aaf65b..24ec39fe096 100644 --- a/tests/ui/drop/terminate-in-initializer.rs +++ b/tests/ui/drop/terminate-in-initializer.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads // Issue #787 // Don't try to clean up uninitialized locals diff --git a/tests/ui/duplicate/dupe-symbols-7.stderr b/tests/ui/duplicate/dupe-symbols-7.stderr index ab9167e005a..aa6213af2e4 100644 --- a/tests/ui/duplicate/dupe-symbols-7.stderr +++ b/tests/ui/duplicate/dupe-symbols-7.stderr @@ -4,7 +4,7 @@ error: entry symbol `main` declared multiple times LL | fn main(){} | ^^^^^^^^^ | - = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead + = help: did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point error: aborting due to 1 previous error diff --git a/tests/ui/duplicate/dupe-symbols-8.stderr b/tests/ui/duplicate/dupe-symbols-8.stderr index d7d419c9aa4..0f47d3683b5 100644 --- a/tests/ui/duplicate/dupe-symbols-8.stderr +++ b/tests/ui/duplicate/dupe-symbols-8.stderr @@ -4,7 +4,7 @@ error: entry symbol `main` declared multiple times LL | fn main() { | ^^^^^^^^^ | - = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead + = help: did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point error: aborting due to 1 previous error diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs index 83076f7d5fc..1b1b8bcf03d 100644 --- a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs +++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.rs @@ -5,8 +5,8 @@ use std::marker::PhantomData; fn transmute<T, U>(t: T) -> U { (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t) - //~^ ERROR the trait `Foo` cannot be made into an object - //~| ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Foo` is not dyn compatible } struct ActuallySuper; @@ -19,7 +19,7 @@ trait Dyn { type Out; } impl<T, U> Dyn for dyn Foo<T, U> + '_ { -//~^ ERROR the trait `Foo` cannot be made into an object +//~^ ERROR the trait `Foo` is not dyn compatible type Out = U; } impl<S: Dyn<Out = U> + ?Sized, U> Super<NotActuallySuper> for S { diff --git a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr index 99bcccc20c0..f241333f2a7 100644 --- a/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr +++ b/tests/ui/dyn-compatibility/almost-supertrait-associated-type.stderr @@ -1,53 +1,53 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/almost-supertrait-associated-type.rs:21:20 | LL | impl<T, U> Dyn for dyn Foo<T, U> + '_ { - | ^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/almost-supertrait-associated-type.rs:33:34 | LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T> - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... ... LL | fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type = help: consider moving `transmute` to another trait - = help: only type `std::marker::PhantomData<T>` implements the trait, consider using it directly instead -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/almost-supertrait-associated-type.rs:7:27 | LL | (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t) - | ^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/almost-supertrait-associated-type.rs:33:34 | LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T> - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... ... LL | fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type = help: consider moving `transmute` to another trait - = help: only type `std::marker::PhantomData<T>` implements the trait, consider using it directly instead -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/almost-supertrait-associated-type.rs:7:6 | LL | (&PhantomData::<T> as &dyn Foo<T, U>).transmute(t) - | ^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/almost-supertrait-associated-type.rs:33:34 | LL | trait Foo<T, U>: Super<ActuallySuper, Assoc = T> - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... ... LL | fn transmute(&self, t: T) -> <Self as Super<NotActuallySuper>>::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `transmute` references the `Self` type in its return type = help: consider moving `transmute` to another trait - = help: only type `std::marker::PhantomData<T>` implements the trait, consider using it directly instead = note: required for the cast from `&PhantomData<T>` to `&dyn Foo<T, U>` error: aborting due to 3 previous errors diff --git a/tests/ui/dyn-compatibility/associated-consts.curr.stderr b/tests/ui/dyn-compatibility/associated-consts.curr.stderr index 17d184942c7..45d4f795542 100644 --- a/tests/ui/dyn-compatibility/associated-consts.curr.stderr +++ b/tests/ui/dyn-compatibility/associated-consts.curr.stderr @@ -1,29 +1,31 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/associated-consts.rs:12:31 | LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { - | ^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/associated-consts.rs:14:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait diff --git a/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr index cc5120232c2..4c8c82196ed 100644 --- a/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/associated-consts.dyn_compatible_for_dispatch.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/associated-consts.rs:14:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/associated-consts.rs:9:11 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | const X: usize; | ^ ...because it contains this associated `const` = help: consider moving `X` to another trait diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr index 54daefea31c..ff5e9fdb6b3 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.old.stderr @@ -26,14 +26,15 @@ help: if this is a dyn-compatible trait, use `dyn` LL | fn id<F>(f: dyn Copy) -> usize { | +++ -error[E0038]: the trait `Copy` cannot be made into an object +error[E0038]: the trait `Copy` is not dyn compatible --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id<F>(f: Copy) -> usize { - | ^^^^ `Copy` cannot be made into an object + | ^^^^ `Copy` is not dyn compatible | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> error[E0618]: expected function, found `(dyn Copy + 'static)` --> $DIR/avoid-ice-on-warning-2.rs:12:5 diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs index 3c2da667b39..312e0d666f1 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-2.rs @@ -3,7 +3,7 @@ //@[new] edition:2021 fn id<F>(f: Copy) -> usize { //[new]~^ ERROR expected a type, found a trait -//[old]~^^ ERROR the trait `Copy` cannot be made into an object +//[old]~^^ ERROR the trait `Copy` is not dyn compatible //[old]~| ERROR the size for values of type `(dyn Copy + 'static)` //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr index 6bc2d73a0d0..92a2d340115 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.old.stderr @@ -65,19 +65,20 @@ help: if this is a dyn-compatible trait, use `dyn` LL | trait B { fn f(a: dyn A) -> A; } | +++ -error[E0038]: the trait `A` cannot be made into an object +error[E0038]: the trait `A` is not dyn compatible --> $DIR/avoid-ice-on-warning-3.rs:4:19 | LL | trait B { fn f(a: A) -> A; } - | ^ `A` cannot be made into an object + | ^ `A` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/avoid-ice-on-warning-3.rs:14:14 | LL | trait A { fn g(b: B) -> B; } | - ^ ...because associated function `g` has no `self` parameter | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... help: consider turning `g` into a method by giving it a `&self` argument | LL | trait A { fn g(&self, b: B) -> B; } @@ -101,19 +102,20 @@ help: if this is a dyn-compatible trait, use `dyn` LL | trait A { fn g(b: dyn B) -> B; } | +++ -error[E0038]: the trait `B` cannot be made into an object +error[E0038]: the trait `B` is not dyn compatible --> $DIR/avoid-ice-on-warning-3.rs:14:19 | LL | trait A { fn g(b: B) -> B; } - | ^ `B` cannot be made into an object + | ^ `B` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/avoid-ice-on-warning-3.rs:4:14 | LL | trait B { fn f(a: A) -> A; } | - ^ ...because associated function `f` has no `self` parameter | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... help: consider turning `f` into a method by giving it a `&self` argument | LL | trait B { fn f(&self, a: A) -> A; } diff --git a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs index 00d47225e92..9ccbfc15a0d 100644 --- a/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs +++ b/tests/ui/dyn-compatibility/avoid-ice-on-warning-3.rs @@ -4,7 +4,7 @@ trait B { fn f(a: A) -> A; } //[new]~^ ERROR expected a type, found a trait //[new]~| ERROR expected a type, found a trait -//[old]~^^^ ERROR the trait `A` cannot be made into an object +//[old]~^^^ ERROR the trait `A` is not dyn compatible //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated @@ -14,7 +14,7 @@ trait B { fn f(a: A) -> A; } trait A { fn g(b: B) -> B; } //[new]~^ ERROR expected a type, found a trait //[new]~| ERROR expected a type, found a trait -//[old]~^^^ ERROR the trait `B` cannot be made into an object +//[old]~^^^ ERROR the trait `B` is not dyn compatible //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated //[old]~| WARN trait objects without an explicit `dyn` are deprecated diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed index a54892afd3e..b5200e9fff5 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.new.fixed @@ -5,7 +5,7 @@ #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> impl Ord { //[new]~^ ERROR expected a type, found a trait - //[old]~^^ ERROR the trait `Ord` cannot be made into an object + //[old]~^^ ERROR the trait `Ord` is not dyn compatible //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr index 45c9b0ce5d9..e3ec5b9c3c8 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.old.stderr @@ -16,19 +16,20 @@ help: if this is a dyn-compatible trait, use `dyn` LL | fn ord_prefer_dot(s: String) -> dyn Ord { | +++ -error[E0038]: the trait `Ord` cannot be made into an object +error[E0038]: the trait `Ord` is not dyn compatible --> $DIR/bare-trait-dont-suggest-dyn.rs:6:33 | LL | fn ord_prefer_dot(s: String) -> Ord { - | ^^^ `Ord` cannot be made into an object + | ^^^ `Ord` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $SRC_DIR/core/src/cmp.rs:LL:COL | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter + = note: the trait is not dyn compatible because it uses `Self` as a type parameter ::: $SRC_DIR/core/src/cmp.rs:LL:COL | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter + = note: the trait is not dyn compatible because it uses `Self` as a type parameter help: consider using an opaque type instead | LL | fn ord_prefer_dot(s: String) -> impl Ord { diff --git a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs index cf9be612d2e..385fd48102c 100644 --- a/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs +++ b/tests/ui/dyn-compatibility/bare-trait-dont-suggest-dyn.rs @@ -5,7 +5,7 @@ #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { //[new]~^ ERROR expected a type, found a trait - //[old]~^^ ERROR the trait `Ord` cannot be made into an object + //[old]~^^ ERROR the trait `Ord` is not dyn compatible //[old]~| ERROR trait objects without an explicit `dyn` are deprecated //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) diff --git a/tests/ui/dyn-compatibility/bounds.rs b/tests/ui/dyn-compatibility/bounds.rs index 1e04d11c516..ed4a69129af 100644 --- a/tests/ui/dyn-compatibility/bounds.rs +++ b/tests/ui/dyn-compatibility/bounds.rs @@ -5,7 +5,7 @@ trait X { } fn f() -> Box<dyn X<U = u32>> { - //~^ ERROR the trait `X` cannot be made into an object + //~^ ERROR the trait `X` is not dyn compatible loop {} } diff --git a/tests/ui/dyn-compatibility/bounds.stderr b/tests/ui/dyn-compatibility/bounds.stderr index 9231d524fd1..d45e66b1d5e 100644 --- a/tests/ui/dyn-compatibility/bounds.stderr +++ b/tests/ui/dyn-compatibility/bounds.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/bounds.rs:7:15 | LL | fn f() -> Box<dyn X<U = u32>> { - | ^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/bounds.rs:4:13 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type U: PartialEq<Self>; | ^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter diff --git a/tests/ui/dyn-compatibility/default-param-self-projection.rs b/tests/ui/dyn-compatibility/default-param-self-projection.rs new file mode 100644 index 00000000000..a440cd735da --- /dev/null +++ b/tests/ui/dyn-compatibility/default-param-self-projection.rs @@ -0,0 +1,17 @@ +trait A<C = <Self as D>::E> {} + +trait D { + type E; +} + +impl A<()> for () {} +impl D for () { + type E = (); +} + +fn f() { + let B: &dyn A = &(); + //~^ ERROR the type parameter `C` must be explicitly specified +} + +fn main() {} diff --git a/tests/ui/dyn-compatibility/default-param-self-projection.stderr b/tests/ui/dyn-compatibility/default-param-self-projection.stderr new file mode 100644 index 00000000000..ea252a99b04 --- /dev/null +++ b/tests/ui/dyn-compatibility/default-param-self-projection.stderr @@ -0,0 +1,18 @@ +error[E0393]: the type parameter `C` must be explicitly specified + --> $DIR/default-param-self-projection.rs:13:17 + | +LL | trait A<C = <Self as D>::E> {} + | --------------------------- type parameter `C` must be specified for this +... +LL | let B: &dyn A = &(); + | ^ + | + = note: because the parameter default references `Self`, the parameter must be specified on the object type +help: set the type parameter to the desired type + | +LL | let B: &dyn A<C> = &(); + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/dyn-compatibility/gat-incompatible-supertrait.rs b/tests/ui/dyn-compatibility/gat-incompatible-supertrait.rs new file mode 100644 index 00000000000..fff29ac2b51 --- /dev/null +++ b/tests/ui/dyn-compatibility/gat-incompatible-supertrait.rs @@ -0,0 +1,18 @@ +// Test that the dyn-compatibility diagnostics for GATs refer first to the +// user-named trait, not the GAT-containing supertrait. +// +// NOTE: this test is currently broken, and first reports: +// "the trait `Super` is not dyn compatible" +// +//@ edition:2018 + +trait Super { + type Assoc<'a>; +} + +trait Child: Super {} + +fn take_dyn(_: &dyn Child) {} +//~^ ERROR the trait `Super` is not dyn compatible + +fn main() {} diff --git a/tests/ui/dyn-compatibility/gat-incompatible-supertrait.stderr b/tests/ui/dyn-compatibility/gat-incompatible-supertrait.stderr new file mode 100644 index 00000000000..04dc0b1d6f4 --- /dev/null +++ b/tests/ui/dyn-compatibility/gat-incompatible-supertrait.stderr @@ -0,0 +1,19 @@ +error[E0038]: the trait `Super` is not dyn compatible + --> $DIR/gat-incompatible-supertrait.rs:15:21 + | +LL | fn take_dyn(_: &dyn Child) {} + | ^^^^^ `Super` is not dyn compatible + | +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/gat-incompatible-supertrait.rs:10:10 + | +LL | trait Super { + | ----- this trait is not dyn compatible... +LL | type Assoc<'a>; + | ^^^^^ ...because it contains the generic associated type `Assoc` + = help: consider moving `Assoc` to another trait + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/dyn-compatibility/generics.curr.stderr b/tests/ui/dyn-compatibility/generics.curr.stderr index c63db38a080..1607954ab70 100644 --- a/tests/ui/dyn-compatibility/generics.curr.stderr +++ b/tests/ui/dyn-compatibility/generics.curr.stderr @@ -1,75 +1,80 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/generics.rs:18:31 | LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { - | ^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/generics.rs:10:8 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar<T>(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/generics.rs:25:40 | LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar { - | ^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/generics.rs:10:8 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar<T>(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/generics.rs:20:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/generics.rs:10:8 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar<T>(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait = note: required for the cast from `&T` to `&dyn Bar` -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/generics.rs:27:10 | LL | t as &dyn Bar - | ^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/generics.rs:10:8 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar<T>(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/generics.rs:27:5 | LL | t as &dyn Bar - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/generics.rs:10:8 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar<T>(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait diff --git a/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr index ba2546ef2dc..7f31b29b39c 100644 --- a/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/generics.dyn_compatible_for_dispatch.stderr @@ -1,30 +1,32 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/generics.rs:20:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/generics.rs:10:8 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar<T>(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait = note: required for the cast from `&T` to `&dyn Bar` -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/generics.rs:27:5 | LL | t as &dyn Bar - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/generics.rs:10:8 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar<T>(&self, t: T); | ^^^ ...because method `bar` has generic type parameters = help: consider moving `bar` to another trait diff --git a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr index 7378ec023c9..1ed78e1e659 100644 --- a/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr +++ b/tests/ui/dyn-compatibility/mention-correct-dyn-incompatible-trait.stderr @@ -1,36 +1,38 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:15 | LL | let test: &mut dyn Bar = &mut thing; - | ^^^^^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 | LL | fn foo<T>(&self, val: T); | ^^^ ...because method `foo` has generic type parameters ... LL | trait Bar: Foo { } - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait - = help: only type `Thing` implements the trait, consider using it directly instead + = help: only type `Thing` implements `Bar`; consider using it directly instead. -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/mention-correct-dyn-incompatible-trait.rs:19:30 | LL | let test: &mut dyn Bar = &mut thing; - | ^^^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mention-correct-dyn-incompatible-trait.rs:4:8 | LL | fn foo<T>(&self, val: T); | ^^^ ...because method `foo` has generic type parameters ... LL | trait Bar: Foo { } - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait - = help: only type `Thing` implements the trait, consider using it directly instead + = help: only type `Thing` implements `Bar`; consider using it directly instead. = note: required for the cast from `&mut Thing` to `&mut dyn Bar` error: aborting due to 2 previous errors diff --git a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs index c9ec44cc0b8..2ab0c6c8f5d 100644 --- a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs +++ b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.rs @@ -36,9 +36,9 @@ impl <'x> Expr for SExpr<'x> { fn main() { let a: Box<dyn Expr> = Box::new(SExpr::new()); - //~^ ERROR: `Expr` cannot be made into an object + //~^ ERROR: `Expr` is not dyn compatible let b: Box<dyn Expr> = Box::new(SExpr::new()); - //~^ ERROR: `Expr` cannot be made into an object + //~^ ERROR: `Expr` is not dyn compatible // assert_eq!(a , b); } diff --git a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr index 7578edce7d1..eba2c15dd74 100644 --- a/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self-in-super-predicates.stderr @@ -1,47 +1,47 @@ -error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/mentions-Self-in-super-predicates.rs:12:23 +error[E0038]: the trait `Expr` is not dyn compatible + --> $DIR/mentions-Self-in-super-predicates.rs:12:27 | LL | elements: Vec<Box<dyn Expr + 'x>>, - | ^^^^^^^^^^^^^ `Expr` cannot be made into an object + | ^^^^ `Expr` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter | | - | this trait cannot be made into an object... - = help: only type `SExpr<'x>` implements the trait, consider using it directly instead + | this trait is not dyn compatible... -error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/mentions-Self-in-super-predicates.rs:38:16 +error[E0038]: the trait `Expr` is not dyn compatible + --> $DIR/mentions-Self-in-super-predicates.rs:38:20 | LL | let a: Box<dyn Expr> = Box::new(SExpr::new()); - | ^^^^^^^^ `Expr` cannot be made into an object + | ^^^^ `Expr` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter | | - | this trait cannot be made into an object... - = help: only type `SExpr<'x>` implements the trait, consider using it directly instead + | this trait is not dyn compatible... -error[E0038]: the trait `Expr` cannot be made into an object - --> $DIR/mentions-Self-in-super-predicates.rs:40:16 +error[E0038]: the trait `Expr` is not dyn compatible + --> $DIR/mentions-Self-in-super-predicates.rs:40:20 | LL | let b: Box<dyn Expr> = Box::new(SExpr::new()); - | ^^^^^^^^ `Expr` cannot be made into an object + | ^^^^ `Expr` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self-in-super-predicates.rs:5:21 | LL | trait Expr: Debug + PartialEq { | ---- ^^^^^^^^^ ...because it uses `Self` as a type parameter | | - | this trait cannot be made into an object... - = help: only type `SExpr<'x>` implements the trait, consider using it directly instead + | this trait is not dyn compatible... error: aborting due to 3 previous errors diff --git a/tests/ui/dyn-compatibility/mentions-Self.curr.stderr b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr index 434e41cf218..90db86ffef9 100644 --- a/tests/ui/dyn-compatibility/mentions-Self.curr.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self.curr.stderr @@ -1,60 +1,64 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/mentions-Self.rs:22:31 | LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { - | ^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar(&self, x: &Self); | ^^^^^ ...because method `bar` references the `Self` type in this parameter = help: consider moving `bar` to another trait -error[E0038]: the trait `Baz` cannot be made into an object +error[E0038]: the trait `Baz` is not dyn compatible --> $DIR/mentions-Self.rs:28:31 | LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz { - | ^^^^^^^ `Baz` cannot be made into an object + | ^^^^^^^ `Baz` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn baz(&self) -> Self; | ^^^^ ...because method `baz` references the `Self` type in its return type = help: consider moving `baz` to another trait -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/mentions-Self.rs:24:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar(&self, x: &Self); | ^^^^^ ...because method `bar` references the `Self` type in this parameter = help: consider moving `bar` to another trait = note: required for the cast from `&T` to `&dyn Bar` -error[E0038]: the trait `Baz` cannot be made into an object +error[E0038]: the trait `Baz` is not dyn compatible --> $DIR/mentions-Self.rs:30:5 | LL | t - | ^ `Baz` cannot be made into an object + | ^ `Baz` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn baz(&self) -> Self; | ^^^^ ...because method `baz` references the `Self` type in its return type = help: consider moving `baz` to another trait diff --git a/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr index dc2d1f87eb7..4a50d3f07e4 100644 --- a/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/mentions-Self.dyn_compatible_for_dispatch.stderr @@ -1,30 +1,32 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/mentions-Self.rs:24:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self.rs:11:22 | LL | trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar(&self, x: &Self); | ^^^^^ ...because method `bar` references the `Self` type in this parameter = help: consider moving `bar` to another trait = note: required for the cast from `&T` to `&dyn Bar` -error[E0038]: the trait `Baz` cannot be made into an object +error[E0038]: the trait `Baz` is not dyn compatible --> $DIR/mentions-Self.rs:30:5 | LL | t - | ^ `Baz` cannot be made into an object + | ^ `Baz` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/mentions-Self.rs:15:22 | LL | trait Baz { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn baz(&self) -> Self; | ^^^^ ...because method `baz` references the `Self` type in its return type = help: consider moving `baz` to another trait diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.rs b/tests/ui/dyn-compatibility/missing-assoc-type.rs index 21f7fd92e80..135761dd036 100644 --- a/tests/ui/dyn-compatibility/missing-assoc-type.rs +++ b/tests/ui/dyn-compatibility/missing-assoc-type.rs @@ -2,6 +2,6 @@ trait Foo { type Bar<T>; } -fn bar(x: &dyn Foo) {} //~ ERROR the trait `Foo` cannot be made into an object +fn bar(x: &dyn Foo) {} //~ ERROR the trait `Foo` is not dyn compatible fn main() {} diff --git a/tests/ui/dyn-compatibility/missing-assoc-type.stderr b/tests/ui/dyn-compatibility/missing-assoc-type.stderr index 184201dd1ce..3f550494b33 100644 --- a/tests/ui/dyn-compatibility/missing-assoc-type.stderr +++ b/tests/ui/dyn-compatibility/missing-assoc-type.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/missing-assoc-type.rs:5:16 | LL | fn bar(x: &dyn Foo) {} - | ^^^ `Foo` cannot be made into an object + | ^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/missing-assoc-type.rs:2:10 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | type Bar<T>; | ^^^ ...because it contains the generic associated type `Bar` = help: consider moving `Bar` to another trait diff --git a/tests/ui/dyn-compatibility/no-static.curr.stderr b/tests/ui/dyn-compatibility/no-static.curr.stderr index 584db779855..867c485053d 100644 --- a/tests/ui/dyn-compatibility/no-static.curr.stderr +++ b/tests/ui/dyn-compatibility/no-static.curr.stderr @@ -1,17 +1,18 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/no-static.rs:12:22 | LL | fn diverges() -> Box<dyn Foo> { - | ^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/no-static.rs:9:8 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn foo() {} | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `Bar` implements the trait, consider using it directly instead + = help: only type `Bar` implements `Foo`; consider using it directly instead. help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) {} @@ -21,20 +22,21 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() where Self: Sized {} | +++++++++++++++++ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/no-static.rs:22:12 | LL | let b: Box<dyn Foo> = Box::new(Bar); - | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/no-static.rs:9:8 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn foo() {} | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `Bar` implements the trait, consider using it directly instead + = help: only type `Bar` implements `Foo`; consider using it directly instead. help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) {} @@ -44,20 +46,21 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() where Self: Sized {} | +++++++++++++++++ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/no-static.rs:22:27 | LL | let b: Box<dyn Foo> = Box::new(Bar); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/no-static.rs:9:8 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn foo() {} | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `Bar` implements the trait, consider using it directly instead + = help: only type `Bar` implements `Foo`; consider using it directly instead. = note: required for the cast from `Box<Bar>` to `Box<dyn Foo>` help: consider turning `foo` into a method by giving it a `&self` argument | diff --git a/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr index f2deb3b8d84..65608a9cca7 100644 --- a/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/no-static.dyn_compatible_for_dispatch.stderr @@ -1,17 +1,18 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/no-static.rs:22:27 | LL | let b: Box<dyn Foo> = Box::new(Bar); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/no-static.rs:9:8 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn foo() {} | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `Bar` implements the trait, consider using it directly instead + = help: only type `Bar` implements `Foo`; consider using it directly instead. = note: required for the cast from `Box<Bar>` to `Box<dyn Foo>` help: consider turning `foo` into a method by giving it a `&self` argument | diff --git a/tests/ui/dyn-compatibility/sized-2.curr.stderr b/tests/ui/dyn-compatibility/sized-2.curr.stderr index 1017fde53d3..c8fd1056237 100644 --- a/tests/ui/dyn-compatibility/sized-2.curr.stderr +++ b/tests/ui/dyn-compatibility/sized-2.curr.stderr @@ -1,28 +1,30 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/sized-2.rs:14:31 | LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { - | ^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/sized-2.rs:9:18 | LL | trait Bar - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/sized-2.rs:16:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/sized-2.rs:9:18 | LL | trait Bar - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` = note: required for the cast from `&T` to `&dyn Bar` diff --git a/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr index 534cf0f1b03..477dacdf5a1 100644 --- a/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/sized-2.dyn_compatible_for_dispatch.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/sized-2.rs:16:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/sized-2.rs:9:18 | LL | trait Bar - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | where Self : Sized | ^^^^^ ...because it requires `Self: Sized` = note: required for the cast from `&T` to `&dyn Bar` diff --git a/tests/ui/dyn-compatibility/sized.curr.stderr b/tests/ui/dyn-compatibility/sized.curr.stderr index 613833aad12..d86ea9197b9 100644 --- a/tests/ui/dyn-compatibility/sized.curr.stderr +++ b/tests/ui/dyn-compatibility/sized.curr.stderr @@ -1,30 +1,32 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/sized.rs:12:32 | LL | fn make_bar<T: Bar>(t: &T) -> &dyn Bar { - | ^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/sized.rs:14:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... = note: required for the cast from `&T` to `&dyn Bar` error: aborting due to 2 previous errors diff --git a/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr index cf847bc1577..b763173594b 100644 --- a/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/sized.dyn_compatible_for_dispatch.stderr @@ -1,16 +1,17 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/sized.rs:14:5 | LL | t - | ^ `Bar` cannot be made into an object + | ^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/sized.rs:8:12 | LL | trait Bar: Sized { | --- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... = note: required for the cast from `&T` to `&dyn Bar` error: aborting due to 1 previous error diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs index 14e00d2ef32..9e5c1bfe416 100644 --- a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs +++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.rs @@ -9,7 +9,7 @@ trait GatTrait { trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> { fn c(&self) -> dyn SuperTrait<T>; //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `SuperTrait` cannot be made into an object + //~| ERROR the trait `SuperTrait` is not dyn compatible } fn main() {} diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr index ac5a5b28d94..f5dea256469 100644 --- a/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr +++ b/tests/ui/dyn-compatibility/supertrait-mentions-GAT.stderr @@ -20,20 +20,21 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn c(&self) -> Self; | ~~~~ -error[E0038]: the trait `SuperTrait` cannot be made into an object +error[E0038]: the trait `SuperTrait` is not dyn compatible --> $DIR/supertrait-mentions-GAT.rs:10:20 | LL | fn c(&self) -> dyn SuperTrait<T>; - | ^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | ^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/supertrait-mentions-GAT.rs:4:10 | LL | type Gat<'a> | ^^^ ...because it contains the generic associated type `Gat` ... LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> { - | ---------- this trait cannot be made into an object... + | ---------- this trait is not dyn compatible... = help: consider moving `Gat` to another trait error: aborting due to 3 previous errors diff --git a/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr index 6474b115c46..f9ef0c9b2e0 100644 --- a/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr +++ b/tests/ui/dyn-compatibility/supertrait-mentions-Self.stderr @@ -18,19 +18,20 @@ help: consider relaxing the implicit `Sized` restriction LL | trait Bar<T: ?Sized> { | ++++++++ -error[E0038]: the trait `Baz` cannot be made into an object - --> $DIR/supertrait-mentions-Self.rs:16:31 +error[E0038]: the trait `Baz` is not dyn compatible + --> $DIR/supertrait-mentions-Self.rs:16:35 | LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz { - | ^^^^^^^ `Baz` cannot be made into an object + | ^^^ `Baz` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/supertrait-mentions-Self.rs:8:13 | LL | trait Baz : Bar<Self> { | --- ^^^^^^^^^ ...because it uses `Self` as a type parameter | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... help: consider using an opaque type instead | LL | fn make_baz<T:Baz>(t: &T) -> &impl Baz { diff --git a/tests/ui/dyn-compatibility/taint-const-eval.curr.stderr b/tests/ui/dyn-compatibility/taint-const-eval.curr.stderr index ef0abc16342..8442314835e 100644 --- a/tests/ui/dyn-compatibility/taint-const-eval.curr.stderr +++ b/tests/ui/dyn-compatibility/taint-const-eval.curr.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Qux` cannot be made into an object +error[E0038]: the trait `Qux` is not dyn compatible --> $DIR/taint-const-eval.rs:11:15 | LL | static FOO: &(dyn Qux + Sync) = "desc"; - | ^^^^^^^^^^^^^^ `Qux` cannot be made into an object + | ^^^^^^^^^^^^^^ `Qux` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/taint-const-eval.rs:8:8 | LL | trait Qux { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar(); | ^^^ ...because associated function `bar` has no `self` parameter help: consider turning `bar` into a method by giving it a `&self` argument @@ -20,17 +21,18 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o LL | fn bar() where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Qux` cannot be made into an object +error[E0038]: the trait `Qux` is not dyn compatible --> $DIR/taint-const-eval.rs:11:33 | LL | static FOO: &(dyn Qux + Sync) = "desc"; - | ^^^^^^ `Qux` cannot be made into an object + | ^^^^^^ `Qux` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/taint-const-eval.rs:8:8 | LL | trait Qux { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar(); | ^^^ ...because associated function `bar` has no `self` parameter = note: required for the cast from `&'static str` to `&'static (dyn Qux + Sync + 'static)` @@ -43,17 +45,18 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o LL | fn bar() where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Qux` cannot be made into an object +error[E0038]: the trait `Qux` is not dyn compatible --> $DIR/taint-const-eval.rs:11:15 | LL | static FOO: &(dyn Qux + Sync) = "desc"; - | ^^^^^^^^^^^^^^ `Qux` cannot be made into an object + | ^^^^^^^^^^^^^^ `Qux` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/taint-const-eval.rs:8:8 | LL | trait Qux { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar(); | ^^^ ...because associated function `bar` has no `self` parameter = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr b/tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr index 14940365d23..1c51df8501f 100644 --- a/tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/dyn-compatibility/taint-const-eval.dyn_compatible_for_dispatch.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Qux` cannot be made into an object +error[E0038]: the trait `Qux` is not dyn compatible --> $DIR/taint-const-eval.rs:11:33 | LL | static FOO: &(dyn Qux + Sync) = "desc"; - | ^^^^^^ `Qux` cannot be made into an object + | ^^^^^^ `Qux` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/taint-const-eval.rs:8:8 | LL | trait Qux { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar(); | ^^^ ...because associated function `bar` has no `self` parameter = note: required for the cast from `&'static str` to `&'static (dyn Qux + Sync + 'static)` diff --git a/tests/ui/dyn-compatibility/taint-const-eval.rs b/tests/ui/dyn-compatibility/taint-const-eval.rs index 9825ec0ca1c..2feae58080b 100644 --- a/tests/ui/dyn-compatibility/taint-const-eval.rs +++ b/tests/ui/dyn-compatibility/taint-const-eval.rs @@ -9,8 +9,8 @@ trait Qux { } static FOO: &(dyn Qux + Sync) = "desc"; -//~^ the trait `Qux` cannot be made into an object -//[curr]~| the trait `Qux` cannot be made into an object -//[curr]~| the trait `Qux` cannot be made into an object +//~^ the trait `Qux` is not dyn compatible +//[curr]~| the trait `Qux` is not dyn compatible +//[curr]~| the trait `Qux` is not dyn compatible fn main() {} diff --git a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs index 5c71bd7769c..ec32bec7785 100644 --- a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs +++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.rs @@ -17,13 +17,13 @@ pub trait Fetcher: Send + Sync { } fn fetcher() -> Box<dyn Fetcher> { - //~^ ERROR the trait `Fetcher` cannot be made into an object + //~^ ERROR the trait `Fetcher` is not dyn compatible todo!() } pub fn foo() { let fetcher = fetcher(); - //~^ ERROR the trait `Fetcher` cannot be made into an object + //~^ ERROR the trait `Fetcher` is not dyn compatible let _ = fetcher.get(); - //~^ ERROR the trait `Fetcher` cannot be made into an object + //~^ ERROR the trait `Fetcher` is not dyn compatible } diff --git a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr index 8d62ac9d923..45a924008c7 100644 --- a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr +++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr @@ -1,51 +1,54 @@ -error[E0038]: the trait `Fetcher` cannot be made into an object +error[E0038]: the trait `Fetcher` is not dyn compatible --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:19:21 | LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` ... LL | fn fetcher() -> Box<dyn Fetcher> { - | ^^^^^^^^^^^ `Fetcher` cannot be made into an object + | ^^^^^^^^^^^ `Fetcher` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { - | ------- this trait cannot be made into an object... + | ------- this trait is not dyn compatible... LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>> | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on -error[E0038]: the trait `Fetcher` cannot be made into an object +error[E0038]: the trait `Fetcher` is not dyn compatible --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:25:19 | LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` ... LL | let fetcher = fetcher(); - | ^^^^^^^^^ `Fetcher` cannot be made into an object + | ^^^^^^^^^ `Fetcher` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { - | ------- this trait cannot be made into an object... + | ------- this trait is not dyn compatible... LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>> | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on -error[E0038]: the trait `Fetcher` cannot be made into an object +error[E0038]: the trait `Fetcher` is not dyn compatible --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:27:13 | LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>> | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` ... LL | let _ = fetcher.get(); - | ^^^^^^^^^^^^^ `Fetcher` cannot be made into an object + | ^^^^^^^^^^^^^ `Fetcher` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 | LL | pub trait Fetcher: Send + Sync { - | ------- this trait cannot be made into an object... + | ------- this trait is not dyn compatible... LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>> | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on diff --git a/tests/ui/enum-discriminant/eval-error.rs b/tests/ui/enum-discriminant/eval-error.rs index f2c3b581627..08b71d52a8b 100644 --- a/tests/ui/enum-discriminant/eval-error.rs +++ b/tests/ui/enum-discriminant/eval-error.rs @@ -6,7 +6,7 @@ union Foo { enum Bar { Boo = { - let _: Option<Foo> = None; + let _: Option<Foo> = None; //~ ERROR evaluation of constant value failed 0 }, } diff --git a/tests/ui/enum-discriminant/eval-error.stderr b/tests/ui/enum-discriminant/eval-error.stderr index 0f12308de3c..6bec2c8b420 100644 --- a/tests/ui/enum-discriminant/eval-error.stderr +++ b/tests/ui/enum-discriminant/eval-error.stderr @@ -45,7 +45,13 @@ help: wrap the field type in `ManuallyDrop<...>` LL | a: std::mem::ManuallyDrop<str>, | +++++++++++++++++++++++ + -error: aborting due to 4 previous errors +error[E0080]: evaluation of constant value failed + --> $DIR/eval-error.rs:9:30 + | +LL | let _: Option<Foo> = None; + | ^^^^ the type `Foo` has an unknown layout + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0277, E0517, E0740. -For more information about an error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0080, E0277, E0517, E0740. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/error-codes/E0038.stderr b/tests/ui/error-codes/E0038.stderr index 54b489c655f..59e9f504d17 100644 --- a/tests/ui/error-codes/E0038.stderr +++ b/tests/ui/error-codes/E0038.stderr @@ -1,29 +1,31 @@ -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/E0038.rs:5:20 | LL | fn call_foo(x: Box<dyn Trait>) { - | ^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/E0038.rs:2:22 | LL | trait Trait { - | ----- this trait cannot be made into an object... + | ----- this trait is not dyn compatible... LL | fn foo(&self) -> Self; | ^^^^ ...because method `foo` references the `Self` type in its return type = help: consider moving `foo` to another trait -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/E0038.rs:7:13 | LL | let y = x.foo(); - | ^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/E0038.rs:2:22 | LL | trait Trait { - | ----- this trait cannot be made into an object... + | ----- this trait is not dyn compatible... LL | fn foo(&self) -> Self; | ^^^^ ...because method `foo` references the `Self` type in its return type = help: consider moving `foo` to another trait diff --git a/tests/ui/error-codes/E0132.rs b/tests/ui/error-codes/E0132.rs deleted file mode 100644 index fb5e5d7b95a..00000000000 --- a/tests/ui/error-codes/E0132.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(start)] - -#[start] -fn f< T >() {} //~ ERROR E0132 - -fn main() { -} diff --git a/tests/ui/error-codes/E0132.stderr b/tests/ui/error-codes/E0132.stderr deleted file mode 100644 index b1990afa3ae..00000000000 --- a/tests/ui/error-codes/E0132.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0132]: `#[start]` function is not allowed to have type parameters - --> $DIR/E0132.rs:4:5 - | -LL | fn f< T >() {} - | ^^^^^ `#[start]` function cannot have type parameters - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0132`. diff --git a/tests/ui/error-codes/E0138.rs b/tests/ui/error-codes/E0138.rs deleted file mode 100644 index 6f3c36282e8..00000000000 --- a/tests/ui/error-codes/E0138.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } - -#[start] -fn f(argc: isize, argv: *const *const u8) -> isize { 0 } -//~^ ERROR E0138 diff --git a/tests/ui/error-codes/E0138.stderr b/tests/ui/error-codes/E0138.stderr deleted file mode 100644 index 04877ab4082..00000000000 --- a/tests/ui/error-codes/E0138.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0138]: multiple `start` functions - --> $DIR/E0138.rs:7:1 - | -LL | fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } - | ---------------------------------------------------- previous `#[start]` function here -... -LL | fn f(argc: isize, argv: *const *const u8) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `start` functions - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0138`. diff --git a/tests/ui/error-codes/E0225.stderr b/tests/ui/error-codes/E0225.stderr index a4b33a0b7b4..e6781282c8f 100644 --- a/tests/ui/error-codes/E0225.stderr +++ b/tests/ui/error-codes/E0225.stderr @@ -20,8 +20,8 @@ LL | trait Foo = std::io::Read + std::io::Write; LL | let _: Box<dyn Foo>; | ^^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> diff --git a/tests/ui/error-codes/E0393.stderr b/tests/ui/error-codes/E0393.stderr index 489398b7be5..4847aa2508d 100644 --- a/tests/ui/error-codes/E0393.stderr +++ b/tests/ui/error-codes/E0393.stderr @@ -7,7 +7,7 @@ LL | LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {} | ^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn together_we_will_rule_the_galaxy(son: &dyn A<T>) {} diff --git a/tests/ui/error-codes/E0432.stderr b/tests/ui/error-codes/E0432.stderr index 36fefc95897..4ff8b40d196 100644 --- a/tests/ui/error-codes/E0432.stderr +++ b/tests/ui/error-codes/E0432.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `something` --> $DIR/E0432.rs:1:5 | LL | use something::Foo; - | ^^^^^^^^^ you might be missing crate `something` + | ^^^^^^^^^ use of unresolved module or unlinked crate `something` | -help: consider importing the `something` crate +help: you might be missing a crate named `something`, add it to your project and import it in your code | LL + extern crate something; | diff --git a/tests/ui/error-codes/E0451.stderr b/tests/ui/error-codes/E0451.stderr index 419cf117efe..2cd30095c80 100644 --- a/tests/ui/error-codes/E0451.stderr +++ b/tests/ui/error-codes/E0451.stderr @@ -8,7 +8,7 @@ error[E0451]: field `b` of struct `Foo` is private --> $DIR/E0451.rs:18:29 | LL | let f = bar::Foo{ a: 0, b: 0 }; - | ^^^^ private field + | ^ private field error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/E0647.rs b/tests/ui/error-codes/E0647.rs deleted file mode 100644 index fc085511cbc..00000000000 --- a/tests/ui/error-codes/E0647.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![no_std] -#![feature(start)] - -extern crate std; - -#[start] -fn start(_: isize, _: *const *const u8) -> isize where (): Copy { //~ ERROR [E0647] - 0 -} diff --git a/tests/ui/error-codes/E0647.stderr b/tests/ui/error-codes/E0647.stderr deleted file mode 100644 index 4b444e5a397..00000000000 --- a/tests/ui/error-codes/E0647.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0647]: `#[start]` function is not allowed to have a `where` clause - --> $DIR/E0647.rs:7:50 - | -LL | fn start(_: isize, _: *const *const u8) -> isize where (): Copy { - | ^^^^^^^^^^^^^^ `#[start]` function cannot have a `where` clause - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0647`. diff --git a/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.stderr b/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.stderr index 75fb13c378c..ece581dc626 100644 --- a/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.stderr +++ b/tests/ui/explicit-tail-calls/ctfe-arg-bad-borrow.stderr @@ -4,10 +4,9 @@ error[E0597]: `local` does not live long enough LL | let local = Type; | ----- binding `local` declared here LL | become takes_borrow(&local); - | ^^^^^^ borrowed value does not live long enough -LL | -LL | } - | - `local` dropped here while still borrowed + | ^^^^^^- `local` dropped here while still borrowed + | | + | borrowed value does not live long enough error: aborting due to 1 previous error diff --git a/tests/ui/explicit-tail-calls/two-phase.rs b/tests/ui/explicit-tail-calls/two-phase.rs new file mode 100644 index 00000000000..91365b5e739 --- /dev/null +++ b/tests/ui/explicit-tail-calls/two-phase.rs @@ -0,0 +1,14 @@ +// regression test for <https://github.com/rust-lang/rust/issues/112788>. +// this test used to ICE because we tried to run drop glue of `x` +// if dropping `_y` (happening at the `become` site) panicked and caused an unwind. +// +//@ check-pass +#![expect(incomplete_features)] +#![feature(explicit_tail_calls)] + +fn f(x: &mut ()) { + let _y = String::new(); + become f(x); +} + +fn main() {} diff --git a/tests/ui/expr/if/expr-if-panic-fn.rs b/tests/ui/expr/if/expr-if-panic-fn.rs index 4f3d7fd48e3..0b4742d4a89 100644 --- a/tests/ui/expr/if/expr-if-panic-fn.rs +++ b/tests/ui/expr/if/expr-if-panic-fn.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn f() -> ! { panic!() diff --git a/tests/ui/expr/if/expr-if-panic.rs b/tests/ui/expr/if/expr-if-panic.rs index 0b43d1d6b00..2f35878e844 100644 --- a/tests/ui/expr/if/expr-if-panic.rs +++ b/tests/ui/expr/if/expr-if-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let _x = if false { diff --git a/tests/ui/expr/if/if-check-panic.rs b/tests/ui/expr/if/if-check-panic.rs index 4b400deaca4..eb0413f42fc 100644 --- a/tests/ui/expr/if/if-check-panic.rs +++ b/tests/ui/expr/if/if-check-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:Number is odd -//@ ignore-emscripten no processes +//@ needs-subprocess fn even(x: usize) -> bool { if x < 2 { diff --git a/tests/ui/expr/if/if-cond-bot.rs b/tests/ui/expr/if/if-cond-bot.rs index ddb5559ffca..56bd5ec35f9 100644 --- a/tests/ui/expr/if/if-cond-bot.rs +++ b/tests/ui/expr/if/if-cond-bot.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:quux -//@ ignore-emscripten no processes +//@ needs-subprocess fn my_err(s: String) -> ! { println!("{}", s); diff --git a/tests/ui/expr/if/if-let.stderr b/tests/ui/expr/if/if-let.stderr index c4bba3cb1a8..792504a9772 100644 --- a/tests/ui/expr/if/if-let.stderr +++ b/tests/ui/expr/if/if-let.stderr @@ -2,7 +2,7 @@ warning: irrefutable `if let` pattern --> $DIR/if-let.rs:6:16 | LL | if let $p = $e $b - | ^^^ + | ^^^^^^^^^^^ ... LL | / foo!(a, 1, { LL | | println!("irrefutable pattern"); diff --git a/tests/ui/extern-flag/multiple-opts.stderr b/tests/ui/extern-flag/multiple-opts.stderr index 0aaca5ee253..d0f38bad94c 100644 --- a/tests/ui/extern-flag/multiple-opts.stderr +++ b/tests/ui/extern-flag/multiple-opts.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `somedep` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `somedep` --> $DIR/multiple-opts.rs:19:5 | LL | somedep::somefun(); - | ^^^^^^^ use of undeclared crate or module `somedep` + | ^^^^^^^ use of unresolved module or unlinked crate `somedep` + | + = help: you might be missing a crate named `somedep` error: aborting due to 1 previous error diff --git a/tests/ui/extern-flag/noprelude.stderr b/tests/ui/extern-flag/noprelude.stderr index 23b9b2fd94b..fbd84956f66 100644 --- a/tests/ui/extern-flag/noprelude.stderr +++ b/tests/ui/extern-flag/noprelude.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `somedep` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `somedep` --> $DIR/noprelude.rs:6:5 | LL | somedep::somefun(); - | ^^^^^^^ use of undeclared crate or module `somedep` + | ^^^^^^^ use of unresolved module or unlinked crate `somedep` + | + = help: you might be missing a crate named `somedep` error: aborting due to 1 previous error diff --git a/tests/ui/extern/extern-prelude-core.rs b/tests/ui/extern/extern-prelude-core.rs index ced1e5c3915..5108c02517c 100644 --- a/tests/ui/extern/extern-prelude-core.rs +++ b/tests/ui/extern/extern-prelude-core.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(lang_items, start)] +#![feature(lang_items)] #![no_std] extern crate std as other; @@ -11,8 +11,6 @@ mod foo { } } -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { +fn main() { foo::test(); - 0 } diff --git a/tests/ui/extern/issue-18576.rs b/tests/ui/extern/issue-18576.rs index 0a98e85e484..6b41fe73631 100644 --- a/tests/ui/extern/issue-18576.rs +++ b/tests/ui/extern/issue-18576.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:stop -//@ ignore-emscripten no processes +//@ needs-subprocess // #18576 // Make sure that calling an extern function pointer in an unreachable diff --git a/tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs index e9471d207da..1cd52b70315 100644 --- a/tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ b/tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine // should still run destructors as it unwinds the stack. However, diff --git a/tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index 9486b5f1178..a44eb3828d0 100644 --- a/tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine // should still run destructors as it unwinds the stack. However, diff --git a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs index d9ff45f57ec..278a5451e84 100644 --- a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs +++ b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.rs @@ -5,10 +5,10 @@ trait Foo { } async fn takes_dyn_trait(x: &dyn Foo) { - //~^ ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible x.bar().await; - //~^ ERROR the trait `Foo` cannot be made into an object - //~| ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Foo` is not dyn compatible } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr index f78fc422410..b4de6b66469 100644 --- a/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr +++ b/tests/ui/feature-gates/feature-gate-async-fn-in-dyn-trait.stderr @@ -1,44 +1,47 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:7:30 | LL | async fn takes_dyn_trait(x: &dyn Foo) { - | ^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | async fn bar(&self); | ^^^ ...because method `bar` is `async` = help: consider moving `bar` to another trait -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:9:7 | LL | x.bar().await; - | ^^^ `Foo` cannot be made into an object + | ^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | async fn bar(&self); | ^^^ ...because method `bar` is `async` = help: consider moving `bar` to another trait -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:9:5 | LL | x.bar().await; - | ^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-async-fn-in-dyn-trait.rs:4:14 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | async fn bar(&self); | ^^^ ...because method `bar` is `async` = help: consider moving `bar` to another trait diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs index 3c9e903d4ba..37eabbf1602 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs @@ -30,6 +30,6 @@ impl Trait for i32 { fn main() { Ptr(Box::new(4)) as Ptr<dyn Trait>; - //~^ ERROR the trait `Trait` cannot be made into an object - //~^^ ERROR the trait `Trait` cannot be made into an object + //~^ ERROR the trait `Trait` is not dyn compatible + //~^^ ERROR the trait `Trait` is not dyn compatible } diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr index 28caaf8356f..f8fc086c441 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr @@ -1,38 +1,40 @@ -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:25 | LL | fn ptr(self: Ptr<Self>); | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` ... LL | Ptr(Box::new(4)) as Ptr<dyn Trait>; - | ^^^^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 | LL | trait Trait { - | ----- this trait cannot be made into an object... + | ----- this trait is not dyn compatible... LL | fn ptr(self: Ptr<Self>); | ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on - = help: only type `i32` implements the trait, consider using it directly instead + = help: only type `i32` implements `Trait`; consider using it directly instead. -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:5 | LL | fn ptr(self: Ptr<Self>); | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` ... LL | Ptr(Box::new(4)) as Ptr<dyn Trait>; - | ^^^^^^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 | LL | trait Trait { - | ----- this trait cannot be made into an object... + | ----- this trait is not dyn compatible... LL | fn ptr(self: Ptr<Self>); | ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on - = help: only type `i32` implements the trait, consider using it directly instead + = help: only type `i32` implements `Trait`; consider using it directly instead. = note: required for the cast from `Ptr<{integer}>` to `Ptr<dyn Trait>` error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr index ed021c154a5..10540f0219d 100644 --- a/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr +++ b/tests/ui/feature-gates/feature-gate-dyn_compatible_for_dispatch.stderr @@ -1,28 +1,30 @@ -error[E0038]: the trait `DynIncompatible1` cannot be made into an object +error[E0038]: the trait `DynIncompatible1` is not dyn compatible --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:18:40 | LL | fn takes_dyn_incompatible_ref<T>(obj: &dyn DynIncompatible1) { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 | LL | trait DynIncompatible1: Sized {} | ---------------- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... -error[E0038]: the trait `DynIncompatible2` cannot be made into an object +error[E0038]: the trait `DynIncompatible2` is not dyn compatible --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:22:46 | LL | fn return_dyn_incompatible_ref() -> &'static dyn DynIncompatible2 { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible2` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:7:8 | LL | trait DynIncompatible2 { - | ---------------- this trait cannot be made into an object... + | ---------------- this trait is not dyn compatible... LL | fn static_fn() {} | ^^^^^^^^^ ...because associated function `static_fn` has no `self` parameter help: consider turning `static_fn` into a method by giving it a `&self` argument @@ -34,49 +36,52 @@ help: alternatively, consider constraining `static_fn` so it does not apply to t LL | fn static_fn() where Self: Sized {} | +++++++++++++++++ -error[E0038]: the trait `DynIncompatible3` cannot be made into an object +error[E0038]: the trait `DynIncompatible3` is not dyn compatible --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:27:40 | LL | fn takes_dyn_incompatible_box(obj: Box<dyn DynIncompatible3>) { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible3` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:11:8 | LL | trait DynIncompatible3 { - | ---------------- this trait cannot be made into an object... + | ---------------- this trait is not dyn compatible... LL | fn foo<T>(&self); | ^^^ ...because method `foo` has generic type parameters = help: consider moving `foo` to another trait -error[E0038]: the trait `DynIncompatible4` cannot be made into an object +error[E0038]: the trait `DynIncompatible4` is not dyn compatible --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:31:48 | LL | fn return_dyn_incompatible_rc() -> std::rc::Rc<dyn DynIncompatible4> { - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible4` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:15:22 | LL | trait DynIncompatible4 { - | ---------------- this trait cannot be made into an object... + | ---------------- this trait is not dyn compatible... LL | fn foo(&self, s: &Self); | ^^^^^ ...because method `foo` references the `Self` type in this parameter = help: consider moving `foo` to another trait -error[E0038]: the trait `DynIncompatible1` cannot be made into an object +error[E0038]: the trait `DynIncompatible1` is not dyn compatible --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:38:16 | LL | impl Trait for dyn DynIncompatible1 {} - | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `DynIncompatible1` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/feature-gate-dyn_compatible_for_dispatch.rs:4:25 | LL | trait DynIncompatible1: Sized {} | ---------------- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... error: aborting due to 5 previous errors diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr index 96fb4a53609..73e6988b09c 100644 --- a/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr +++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.normal.stderr @@ -8,17 +8,15 @@ LL | let _y: [u8; _] = [0; 3]; = help: add `#![feature(generic_arg_infer)]` 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[E0747]: type provided when a constant was expected +error[E0658]: const arguments cannot yet be inferred with `_` --> $DIR/feature-gate-generic_arg_infer.rs:18:20 | -LL | let _x = foo::<_>([1,2]); +LL | let _x = foo::<_>([1, 2]); | ^ | - = help: const arguments cannot yet be inferred with `_` -help: add `#![feature(generic_arg_infer)]` to the crate attributes to enable - | -LL + #![feature(generic_arg_infer)] - | + = note: see issue #85077 <https://github.com/rust-lang/rust/issues/85077> for more information + = help: add `#![feature(generic_arg_infer)]` 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]: using `_` for array lengths is unstable --> $DIR/feature-gate-generic_arg_infer.rs:11:27 @@ -32,5 +30,4 @@ LL | let _x: [u8; 3] = [0; _]; error: aborting due to 3 previous errors -Some errors have detailed explanations: E0658, E0747. -For more information about an error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs index de4b7078ea6..147978b0557 100644 --- a/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs +++ b/tests/ui/feature-gates/feature-gate-generic_arg_infer.rs @@ -4,7 +4,7 @@ #![cfg_attr(feature, feature(generic_arg_infer))] fn foo<const N: usize>(_: [u8; N]) -> [u8; N] { - [0; N] + [0; N] } fn bar() { @@ -15,7 +15,7 @@ fn bar() { } fn main() { - let _x = foo::<_>([1,2]); - //[normal]~^ ERROR: type provided when a constant was expected + let _x = foo::<_>([1, 2]); + //[normal]~^ ERROR: const arguments cannot yet be inferred with `_` bar(); } diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs index 7f9cada6a47..77cc307c9f4 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.rs +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.rs @@ -6,6 +6,9 @@ fn size() {} #[optimize(speed)] //~ ERROR the `#[optimize]` attribute is an experimental feature fn speed() {} +#[optimize(none)] //~ ERROR the `#[optimize]` attribute is an experimental feature +fn none() {} + #[optimize(banana)] //~^ ERROR the `#[optimize]` attribute is an experimental feature //~| ERROR E0722 diff --git a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr index ca8f4a078f0..4e6e4ac2703 100644 --- a/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr +++ b/tests/ui/feature-gates/feature-gate-optimize_attribute.stderr @@ -21,6 +21,16 @@ LL | #[optimize(speed)] error[E0658]: the `#[optimize]` attribute is an experimental feature --> $DIR/feature-gate-optimize_attribute.rs:9:1 | +LL | #[optimize(none)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #54882 <https://github.com/rust-lang/rust/issues/54882> for more information + = help: add `#![feature(optimize_attribute)]` 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]: the `#[optimize]` attribute is an experimental feature + --> $DIR/feature-gate-optimize_attribute.rs:12:1 + | LL | #[optimize(banana)] | ^^^^^^^^^^^^^^^^^^^ | @@ -29,12 +39,12 @@ LL | #[optimize(banana)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0722]: invalid argument - --> $DIR/feature-gate-optimize_attribute.rs:9:12 + --> $DIR/feature-gate-optimize_attribute.rs:12:12 | LL | #[optimize(banana)] | ^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0658, E0722. For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-start.rs b/tests/ui/feature-gates/feature-gate-start.rs deleted file mode 100644 index e617f1c4759..00000000000 --- a/tests/ui/feature-gates/feature-gate-start.rs +++ /dev/null @@ -1,3 +0,0 @@ -#[start] -fn foo(_: isize, _: *const *const u8) -> isize { 0 } -//~^ ERROR `#[start]` functions are experimental diff --git a/tests/ui/feature-gates/feature-gate-start.stderr b/tests/ui/feature-gates/feature-gate-start.stderr deleted file mode 100644 index b1859c43718..00000000000 --- a/tests/ui/feature-gates/feature-gate-start.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: `#[start]` functions are experimental and their signature may change over time - --> $DIR/feature-gate-start.rs:2:1 - | -LL | fn foo(_: isize, _: *const *const u8) -> isize { 0 } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #29633 <https://github.com/rust-lang/rust/issues/29633> for more information - = help: add `#![feature(start)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs index afffb3b1443..02a56c7e6aa 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs @@ -14,8 +14,6 @@ #![rustc_main] //~ ERROR: the `#[rustc_main]` attribute is used internally to specify //~^ ERROR: `rustc_main` attribute cannot be used at crate level //~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -#![start] -//~^ ERROR: `start` attribute cannot be used at crate level #![repr()] //~^ ERROR: `repr` attribute cannot be used at crate level #![path = "3800"] @@ -38,7 +36,6 @@ mod inline { //~| NOTE the inner attribute doesn't annotate this module //~| NOTE the inner attribute doesn't annotate this module //~| NOTE the inner attribute doesn't annotate this module - //~| NOTE the inner attribute doesn't annotate this module mod inner { #![inline] } //~^ ERROR attribute should be applied to function or closure @@ -123,24 +120,6 @@ mod export_name { } } -#[start] -//~^ ERROR: `start` attribute can only be used on functions -mod start { - mod inner { #![start] } - //~^ ERROR: `start` attribute can only be used on functions - - // for `fn f()` case, see feature-gate-start.rs - - #[start] struct S; - //~^ ERROR: `start` attribute can only be used on functions - - #[start] type T = S; - //~^ ERROR: `start` attribute can only be used on functions - - #[start] impl S { } - //~^ ERROR: `start` attribute can only be used on functions -} - #[repr(C)] //~^ ERROR: attribute should be applied to a struct, enum, or union mod repr { diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index db8c5295a2d..648bafe6460 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -8,7 +8,7 @@ LL | #![rustc_main] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: valid forms for the attribute are `#[inline]` and `#[inline(always|never)]` - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:47:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:44:5 | LL | #[inline = "2100"] fn f() { } | ^^^^^^^^^^^^^^^^^^ @@ -17,38 +17,8 @@ LL | #[inline = "2100"] fn f() { } = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571> = note: `#[deny(ill_formed_attribute_input)]` on by default -error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:126:1 - | -LL | #[start] - | ^^^^^^^^ - -error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:129:17 - | -LL | mod inner { #![start] } - | ^^^^^^^^^ - -error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:134:5 - | -LL | #[start] struct S; - | ^^^^^^^^ - -error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:5 - | -LL | #[start] type T = S; - | ^^^^^^^^ - -error: `start` attribute can only be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:140:5 - | -LL | #[start] impl S { } - | ^^^^^^^^ - error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:32:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1 | LL | #[inline] | ^^^^^^^^^ @@ -59,7 +29,7 @@ LL | | } | |_- not a function or closure error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:66:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:63:1 | LL | #[no_link] | ^^^^^^^^^^ @@ -73,7 +43,7 @@ LL | | } | |_- not an `extern crate` item error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:92:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:89:1 | LL | #[export_name = "2200"] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -87,7 +57,7 @@ LL | | } | |_- not a free function, impl method or static error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:144:8 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:8 | LL | #[repr(C)] | ^ @@ -100,7 +70,7 @@ LL | | } | |_- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:168:8 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:147:8 | LL | #[repr(Rust)] | ^^^^ @@ -113,19 +83,19 @@ LL | | } | |_- not a struct, enum, or union error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:24:1 | LL | #![no_link] | ^^^^^^^^^^^ not an `extern crate` item error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1 | LL | #![export_name = "2200"] | ^^^^^^^^^^^^^^^^^^^^^^^^ not a free function, impl method or static error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:30:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1 | LL | #![inline] | ^^^^^^^^^^ not a function or closure @@ -160,23 +130,8 @@ LL - #![rustc_main] LL + #[rustc_main] | -error: `start` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1 - | -LL | #![start] - | ^^^^^^^^^ -... -LL | mod inline { - | ------ the inner attribute doesn't annotate this module - | -help: perhaps you meant to use an outer attribute - | -LL - #![start] -LL + #[start] - | - error: `repr` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1 | LL | #![repr()] | ^^^^^^^^^^ @@ -191,7 +146,7 @@ LL + #[repr()] | error: `path` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1 | LL | #![path = "3800"] | ^^^^^^^^^^^^^^^^^ @@ -206,7 +161,7 @@ LL + #[path = "3800"] | error: `automatically_derived` attribute cannot be used at crate level - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1 | LL | #![automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -221,144 +176,144 @@ LL + #[automatically_derived] | error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:43:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:40:17 | LL | mod inner { #![inline] } | ------------^^^^^^^^^^-- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:53:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:50:5 | LL | #[inline] struct S; | ^^^^^^^^^ --------- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:57:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:54:5 | LL | #[inline] type T = S; | ^^^^^^^^^ ----------- not a function or closure error[E0518]: attribute should be applied to function or closure - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:61:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:58:5 | LL | #[inline] impl S { } | ^^^^^^^^^ ---------- not a function or closure error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:71:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:68:17 | LL | mod inner { #![no_link] } | ------------^^^^^^^^^^^-- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:75:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:72:5 | LL | #[no_link] fn f() { } | ^^^^^^^^^^ ---------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:79:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:76:5 | LL | #[no_link] struct S; | ^^^^^^^^^^ --------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:83:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:5 | LL | #[no_link]type T = S; | ^^^^^^^^^^----------- not an `extern crate` item error: attribute should be applied to an `extern crate` item - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:87:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:84:5 | LL | #[no_link] impl S { } | ^^^^^^^^^^ ---------- not an `extern crate` item error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:97:17 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:94:17 | LL | mod inner { #![export_name="2200"] } | ------------^^^^^^^^^^^^^^^^^^^^^^-- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:103:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:100:5 | LL | #[export_name = "2200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:107:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:104:5 | LL | #[export_name = "2200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:111:5 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:108:5 | LL | #[export_name = "2200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:116:9 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:9 | LL | #[export_name = "2200"] fn foo(); | ^^^^^^^^^^^^^^^^^^^^^^^ --------- not a free function, impl method or static error: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:120:9 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:117:9 | LL | #[export_name = "2200"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a free function, impl method or static error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:148:25 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:127:25 | LL | mod inner { #![repr(C)] } | --------------------^---- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:152:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:131:12 | LL | #[repr(C)] fn f() { } | ^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:158:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:12 | LL | #[repr(C)] type T = S; | ^ ----------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:162:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:141:12 | LL | #[repr(C)] impl S { } | ^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:172:25 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:151:25 | LL | mod inner { #![repr(Rust)] } | --------------------^^^^---- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:176:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:155:12 | LL | #[repr(Rust)] fn f() { } | ^^^^ ---------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:182:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:161:12 | LL | #[repr(Rust)] type T = S; | ^^^^ ----------- not a struct, enum, or union error[E0517]: attribute should be applied to a struct, enum, or union - --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:186:12 + --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:165:12 | LL | #[repr(Rust)] impl S { } | ^^^^ ---------- not a struct, enum, or union -error: aborting due to 44 previous errors +error: aborting due to 38 previous errors Some errors have detailed explanations: E0517, E0518, E0658. For more information about an error, try `rustc --explain E0517`. 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 141927b4de8..a196b8ecdb3 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 @@ -81,20 +81,11 @@ #![crate_name = "0900"] #![crate_type = "bin"] // cannot pass "0800" here -#![crate_id = "10"] -//~^ WARN use of deprecated attribute -//~| HELP remove this attribute -//~| NOTE `#[warn(deprecated)]` on by default - // FIXME(#44232) we should warn that this isn't used. #![feature(rust1)] //~^ WARN no longer requires an attribute to enable //~| NOTE `#[warn(stable_features)]` on by default -#![no_start] -//~^ WARN use of deprecated attribute -//~| HELP remove this attribute - // (cannot easily gating state of crate-level #[no_main]; but non crate-level is below at "0400") #![no_builtins] #![recursion_limit = "0200"] 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 18fb75aafbb..1c6868dc95d 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -1,5 +1,5 @@ warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:400:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:391:17 | LL | mod inner { #![macro_escape] } | ^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | mod inner { #![macro_escape] } = help: try an outer attribute: `#[macro_use]` warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:397:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:388:1 | LL | #[macro_escape] | ^^^^^^^^^^^^^^^ @@ -42,166 +42,152 @@ warning: unknown lint: `x5100` LL | #![deny(x5100)] | ^^^^^ -warning: use of deprecated attribute `crate_id`: no longer used - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:84:1 - | -LL | #![crate_id = "10"] - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | - = note: `#[warn(deprecated)]` on by default - -warning: use of deprecated attribute `no_start`: no longer used - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:94:1 - | -LL | #![no_start] - | ^^^^^^^^^^^^ help: remove this attribute - warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:96:8 | LL | #[warn(x5400)] | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:108:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:99:25 | LL | mod inner { #![warn(x5400)] } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:111:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:102:12 | LL | #[warn(x5400)] fn f() { } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:114:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:105:12 | LL | #[warn(x5400)] struct S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:117:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:108:12 | LL | #[warn(x5400)] type T = S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:120:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:111:12 | LL | #[warn(x5400)] impl S { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:124:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:115:9 | LL | #[allow(x5300)] | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:127:26 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:118:26 | LL | mod inner { #![allow(x5300)] } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:130:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:121:13 | LL | #[allow(x5300)] fn f() { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:133:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:124:13 | LL | #[allow(x5300)] struct S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:136:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:127:13 | LL | #[allow(x5300)] type T = S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:139:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:130:13 | LL | #[allow(x5300)] impl S { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:143:10 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:134:10 | LL | #[forbid(x5200)] | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:146:27 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:137:27 | LL | mod inner { #![forbid(x5200)] } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:149:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:140:14 | LL | #[forbid(x5200)] fn f() { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:152:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:143:14 | LL | #[forbid(x5200)] struct S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:155:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:146:14 | LL | #[forbid(x5200)] type T = S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:158:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:149:14 | LL | #[forbid(x5200)] impl S { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:162:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:153:8 | LL | #[deny(x5100)] | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:165:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:156:25 | LL | mod inner { #![deny(x5100)] } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:168:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:159:12 | LL | #[deny(x5100)] fn f() { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:171:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:162:12 | LL | #[deny(x5100)] struct S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:174:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:165:12 | LL | #[deny(x5100)] type T = S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:177:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:168:12 | LL | #[deny(x5100)] impl S { } | ^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:1 | LL | #[macro_export] | ^^^^^^^^^^^^^^^ @@ -213,13 +199,13 @@ LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:257:1 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:284:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:275:1 | LL | #[no_mangle] | ^^^^^^^^^^^^ @@ -234,31 +220,31 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:315:1 | LL | #[should_panic] | ^^^^^^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:1 | LL | #[ignore] | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:1 | LL | #[reexport_test_harness_main = "2900"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:1 | LL | #[no_std] | ^^^^^^^^^ warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:453:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:444:1 | LL | #[cold] | ^^^^^^^ @@ -274,7 +260,7 @@ LL | | } = 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 a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:482:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:1 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ @@ -290,7 +276,7 @@ LL | | } = 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 a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1 | LL | #[link_section = "1800"] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -306,7 +292,7 @@ LL | | } = 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:553:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:1 | LL | #[link()] | ^^^^^^^^^ @@ -322,55 +308,55 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[must_use]` has no effect when applied to a module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:604:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:595:1 | LL | #[must_use] | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:608:1 | LL | #[windows_subsystem = "windows"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:629:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:648:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:1 | LL | #[no_main] | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:1 | LL | #[no_builtins] | ^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -432,109 +418,109 @@ LL | #![must_use] | ^^^^^^^^^^^^ warning: `#[macro_use]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:5 | LL | #[macro_use] fn f() { } | ^^^^^^^^^^^^ warning: `#[macro_use]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:188:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:179:5 | LL | #[macro_use] struct S; | ^^^^^^^^^^^^ warning: `#[macro_use]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:182:5 | LL | #[macro_use] type T = S; | ^^^^^^^^^^^^ warning: `#[macro_use]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:194:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:5 | LL | #[macro_use] impl S { } | ^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:17 | LL | mod inner { #![macro_export] } | ^^^^^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5 | LL | #[macro_export] fn f() { } | ^^^^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:207:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5 | LL | #[macro_export] struct S; | ^^^^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:210:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5 | LL | #[macro_export] type T = S; | ^^^^^^^^^^^^^^^ warning: `#[macro_export]` only has an effect on macro definitions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:213:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5 | LL | #[macro_export] impl S { } | ^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:244:5 | LL | #[path = "3800"] fn f() { } | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:247:5 | LL | #[path = "3800"] struct S; | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:259:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:250:5 | LL | #[path = "3800"] type T = S; | ^^^^^^^^^^^^^^^^ warning: `#[path]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:262:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5 | LL | #[path = "3800"] impl S { } | ^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:17 | LL | mod inner { #![automatically_derived] } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:272:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:5 | LL | #[automatically_derived] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:275:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:266:5 | LL | #[automatically_derived] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` only has an effect on implementation blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:278:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:5 | LL | #[automatically_derived] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:17 | LL | mod inner { #![no_mangle] } | ------------^^^^^^^^^^^^^-- not a free function, impl method or static @@ -542,7 +528,7 @@ LL | mod inner { #![no_mangle] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:296:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:287:5 | LL | #[no_mangle] struct S; | ^^^^^^^^^^^^ --------- not a free function, impl method or static @@ -550,7 +536,7 @@ LL | #[no_mangle] struct S; = 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 a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:292:5 | LL | #[no_mangle] type T = S; | ^^^^^^^^^^^^ ----------- not a free function, impl method or static @@ -558,7 +544,7 @@ LL | #[no_mangle] type T = S; = 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 a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:306:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:297:5 | LL | #[no_mangle] impl S { } | ^^^^^^^^^^^^ ---------- not a free function, impl method or static @@ -566,7 +552,7 @@ LL | #[no_mangle] impl S { } = 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 a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:312:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:303:9 | LL | #[no_mangle] fn foo(); | ^^^^^^^^^^^^ --------- not a free function, impl method or static @@ -574,7 +560,7 @@ LL | #[no_mangle] fn foo(); = 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 a free function, impl method or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:317:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:308:9 | LL | #[no_mangle] fn bar() {} | ^^^^^^^^^^^^ ----------- not a free function, impl method or static @@ -582,163 +568,163 @@ LL | #[no_mangle] fn bar() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:327:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:17 | LL | mod inner { #![should_panic] } | ^^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:323:5 | LL | #[should_panic] struct S; | ^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:326:5 | LL | #[should_panic] type T = S; | ^^^^^^^^^^^^^^^ warning: `#[should_panic]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:329:5 | LL | #[should_panic] impl S { } | ^^^^^^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:17 | LL | mod inner { #![ignore] } | ^^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:350:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5 | LL | #[ignore] struct S; | ^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:353:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5 | LL | #[ignore] type T = S; | ^^^^^^^^^ warning: `#[ignore]` only has an effect on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:356:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:5 | LL | #[ignore] impl S { } | ^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5 | LL | #[no_implicit_prelude] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:5 | LL | #[no_implicit_prelude] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5 | LL | #[no_implicit_prelude] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: `#[no_implicit_prelude]` only has an effect on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:5 | LL | #[no_implicit_prelude] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:17 | LL | mod inner { #![reexport_test_harness_main="2900"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5 | LL | #[reexport_test_harness_main = "2900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5 | LL | #[reexport_test_harness_main = "2900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5 | LL | #[reexport_test_harness_main = "2900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:392:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:383:5 | LL | #[reexport_test_harness_main = "2900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:5 | LL | #[macro_escape] fn f() { } | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:398:5 | LL | #[macro_escape] struct S; | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:410:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:5 | LL | #[macro_escape] type T = S; | ^^^^^^^^^^^^^^^ warning: `#[macro_escape]` only has an effect on `extern crate` and modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:413:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:5 | LL | #[macro_escape] impl S { } | ^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5 | LL | #[no_std] fn f() { } | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:5 | LL | #[no_std] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:5 | LL | #[no_std] type T = S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ warning: attribute should be applied to a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:459:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:17 | LL | mod inner { #![cold] } | ------------^^^^^^^^-- not a function definition @@ -746,7 +732,7 @@ LL | mod inner { #![cold] } = 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 a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:5 | LL | #[cold] struct S; | ^^^^^^^ --------- not a function definition @@ -754,7 +740,7 @@ LL | #[cold] struct S; = 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 a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:5 | LL | #[cold] type T = S; | ^^^^^^^ ----------- not a function definition @@ -762,7 +748,7 @@ LL | #[cold] type T = S; = 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 a function definition - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5 | LL | #[cold] impl S { } | ^^^^^^^ ---------- not a function definition @@ -770,7 +756,7 @@ LL | #[cold] impl S { } = 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 a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:5 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ @@ -780,13 +766,13 @@ LL | extern "C" { } | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! help: try `#[link(name = "1900")]` instead - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:5 | LL | #[link_name = "1900"] | ^^^^^^^^^^^^^^^^^^^^^ warning: attribute should be applied to a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:17 | LL | mod inner { #![link_name="1900"] } | ------------^^^^^^^^^^^^^^^^^^^^-- not a foreign function or static @@ -794,7 +780,7 @@ LL | mod inner { #![link_name="1900"] } = 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 a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:491:5 | LL | #[link_name = "1900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static @@ -802,7 +788,7 @@ LL | #[link_name = "1900"] fn f() { } = 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 a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5 | LL | #[link_name = "1900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^ --------- not a foreign function or static @@ -810,7 +796,7 @@ LL | #[link_name = "1900"] struct S; = 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 a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:501:5 | LL | #[link_name = "1900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^ ----------- not a foreign function or static @@ -818,7 +804,7 @@ LL | #[link_name = "1900"] type T = S; = 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 a foreign function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:506:5 | LL | #[link_name = "1900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^ ---------- not a foreign function or static @@ -826,7 +812,7 @@ LL | #[link_name = "1900"] impl S { } = 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 a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:17 | LL | mod inner { #![link_section="1800"] } | ------------^^^^^^^^^^^^^^^^^^^^^^^-- not a function or static @@ -834,7 +820,7 @@ LL | mod inner { #![link_section="1800"] } = 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 a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:534:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:525:5 | LL | #[link_section = "1800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ --------- not a function or static @@ -842,7 +828,7 @@ LL | #[link_section = "1800"] struct S; = 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 a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:539:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:530:5 | LL | #[link_section = "1800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ ----------- not a function or static @@ -850,7 +836,7 @@ LL | #[link_section = "1800"] type T = S; = 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 a function or static - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:5 | LL | #[link_section = "1800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^ ---------- not a function or static @@ -858,7 +844,7 @@ LL | #[link_section = "1800"] impl S { } = 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:559:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:550:17 | LL | mod inner { #![link()] } | ------------^^^^^^^^^^-- not an `extern` block @@ -866,7 +852,7 @@ LL | mod inner { #![link()] } = 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:564:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:5 | LL | #[link()] fn f() { } | ^^^^^^^^^ ---------- not an `extern` block @@ -874,7 +860,7 @@ LL | #[link()] fn f() { } = 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:569:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:560:5 | LL | #[link()] struct S; | ^^^^^^^^^ --------- not an `extern` block @@ -882,7 +868,7 @@ LL | #[link()] struct S; = 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:574:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:565:5 | LL | #[link()] type T = S; | ^^^^^^^^^ ----------- not an `extern` block @@ -890,7 +876,7 @@ LL | #[link()] type T = S; = 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:579:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:570:5 | LL | #[link()] impl S { } | ^^^^^^^^^ ---------- not an `extern` block @@ -898,7 +884,7 @@ LL | #[link()] impl S { } = 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:584:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:575:5 | LL | #[link()] extern "Rust" {} | ^^^^^^^^^ @@ -906,270 +892,270 @@ LL | #[link()] extern "Rust" {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[must_use]` has no effect when applied to a module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:606:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:597:17 | LL | mod inner { #![must_use] } | ^^^^^^^^^^^^ warning: `#[must_use]` has no effect when applied to a type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:612:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:603:5 | LL | #[must_use] type T = S; | ^^^^^^^^^^^ warning: `#[must_use]` has no effect when applied to an implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:605:5 | LL | #[must_use] impl S { } | ^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:17 | LL | mod inner { #![windows_subsystem="windows"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:5 | LL | #[windows_subsystem = "windows"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:626:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:617:5 | LL | #[windows_subsystem = "windows"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:629:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:5 | LL | #[windows_subsystem = "windows"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:632:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:623:5 | LL | #[windows_subsystem = "windows"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:632:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:635:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:638:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:650:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:653:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:644:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:651:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:666:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:657:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:670:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:690:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:702:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:17 | LL | mod inner { #![no_builtins] } | ^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5 | LL | #[no_builtins] fn f() { } | ^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5 | LL | #[no_builtins] struct S; | ^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:5 | LL | #[no_builtins] type T = S; | ^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 | LL | #[no_builtins] impl S { } | ^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:85:12 | LL | #![feature(rust1)] | ^^^^^ | = note: `#[warn(stable_features)]` on by default -warning: 173 warnings emitted +warning: 171 warnings emitted diff --git a/tests/ui/fn/expr-fn-panic.rs b/tests/ui/fn/expr-fn-panic.rs index 23946b7533d..d726aac2a4c 100644 --- a/tests/ui/fn/expr-fn-panic.rs +++ b/tests/ui/fn/expr-fn-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn f() -> ! { panic!() diff --git a/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.fixed b/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.fixed index 914ca1f3a06..b58c3a6720d 100644 --- a/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.fixed +++ b/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.fixed @@ -1,17 +1,26 @@ //@ run-rustfix #![deny(unused_assignments, unused_variables)] +#![allow(unused_mut)] struct Object; fn change_object(object: &mut Object) { //~ HELP you might have meant to mutate - let object2 = Object; - *object = object2; //~ ERROR mismatched types + let object2 = Object; + *object = object2; //~ ERROR mismatched types } fn change_object2(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used + //~^ HELP you might have meant to mutate + let object2 = Object; + *object = object2; + //~^ ERROR `object2` does not live long enough + //~| ERROR value assigned to `object` is never read +} + +fn change_object3(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used //~^ HELP you might have meant to mutate - let object2 = Object; + let mut object2 = Object; //~ HELP consider changing this to be mutable *object = object2; - //~^ ERROR `object2` does not live long enough + //~^ ERROR cannot borrow `object2` as mutable //~| ERROR value assigned to `object` is never read } @@ -19,4 +28,5 @@ fn main() { let mut object = Object; change_object(&mut object); change_object2(&mut object); + change_object3(&mut object); } diff --git a/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs b/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs index 331359a98d1..1fd222e0db1 100644 --- a/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs +++ b/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs @@ -1,17 +1,26 @@ //@ run-rustfix #![deny(unused_assignments, unused_variables)] +#![allow(unused_mut)] struct Object; fn change_object(mut object: &Object) { //~ HELP you might have meant to mutate - let object2 = Object; - object = object2; //~ ERROR mismatched types + let object2 = Object; + object = object2; //~ ERROR mismatched types } fn change_object2(mut object: &Object) { //~ ERROR variable `object` is assigned to, but never used + //~^ HELP you might have meant to mutate + let object2 = Object; + object = &object2; + //~^ ERROR `object2` does not live long enough + //~| ERROR value assigned to `object` is never read +} + +fn change_object3(mut object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used //~^ HELP you might have meant to mutate - let object2 = Object; - object = &object2; - //~^ ERROR `object2` does not live long enough + let object2 = Object; //~ HELP consider changing this to be mutable + object = &mut object2; + //~^ ERROR cannot borrow `object2` as mutable //~| ERROR value assigned to `object` is never read } @@ -19,4 +28,5 @@ fn main() { let mut object = Object; change_object(&mut object); change_object2(&mut object); + change_object3(&mut object); } diff --git a/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.stderr b/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.stderr index e7e4003936a..0330853d922 100644 --- a/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.stderr +++ b/tests/ui/fn/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.stderr @@ -1,24 +1,24 @@ error[E0308]: mismatched types - --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:7:14 + --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:8:13 | LL | fn change_object(mut object: &Object) { | ------- expected due to this parameter type -LL | let object2 = Object; -LL | object = object2; - | ^^^^^^^ expected `&Object`, found `Object` +LL | let object2 = Object; +LL | object = object2; + | ^^^^^^^ expected `&Object`, found `Object` | help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding | LL ~ fn change_object(object: &mut Object) { -LL | let object2 = Object; -LL ~ *object = object2; +LL | let object2 = Object; +LL ~ *object = object2; | error: value assigned to `object` is never read - --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:13:5 + --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:14:4 | -LL | object = &object2; - | ^^^^^^ +LL | object = &object2; + | ^^^^^^ | note: the lint level is defined here --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:2:9 @@ -29,12 +29,12 @@ help: you might have meant to mutate the pointed at value being passed in, inste | LL ~ fn change_object2(object: &mut Object) { LL | -LL | let object2 = Object; -LL ~ *object = object2; +LL | let object2 = Object; +LL ~ *object = object2; | error: variable `object` is assigned to, but never used - --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:10:23 + --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:11:23 | LL | fn change_object2(mut object: &Object) { | ^^^^^^ @@ -47,23 +47,56 @@ LL | #![deny(unused_assignments, unused_variables)] | ^^^^^^^^^^^^^^^^ error[E0597]: `object2` does not live long enough - --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:13:14 + --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:14:13 | LL | fn change_object2(mut object: &Object) { | - let's call the lifetime of this reference `'1` LL | -LL | let object2 = Object; - | ------- binding `object2` declared here -LL | object = &object2; - | ---------^^^^^^^^ - | | | - | | borrowed value does not live long enough - | assignment requires that `object2` is borrowed for `'1` +LL | let object2 = Object; + | ------- binding `object2` declared here +LL | object = &object2; + | ---------^^^^^^^^ + | | | + | | borrowed value does not live long enough + | assignment requires that `object2` is borrowed for `'1` ... LL | } | - `object2` dropped here while still borrowed -error: aborting due to 4 previous errors +error: value assigned to `object` is never read + --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:22:5 + | +LL | object = &mut object2; + | ^^^^^^ + | +help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding + | +LL ~ fn change_object3(object: &mut Object) { +LL | +LL | let object2 = Object; +LL ~ *object = object2; + | + +error: variable `object` is assigned to, but never used + --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:19:23 + | +LL | fn change_object3(mut object: &mut Object) { + | ^^^^^^ + | + = note: consider using `_object` instead + +error[E0596]: cannot borrow `object2` as mutable, as it is not declared as mutable + --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:22:14 + | +LL | object = &mut object2; + | ^^^^^^^^^^^^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut object2 = Object; + | +++ + +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0308, E0597. +Some errors have detailed explanations: E0308, E0596, E0597. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/for-loop-while/for-loop-no-std.rs b/tests/ui/for-loop-while/for-loop-no-std.rs index 4511146dc75..8255d7b4200 100644 --- a/tests/ui/for-loop-while/for-loop-no-std.rs +++ b/tests/ui/for-loop-while/for-loop-no-std.rs @@ -1,14 +1,19 @@ //@ run-pass +//@ ignore-emscripten no no_std executables +//@ ignore-wasm different `main` convention #![allow(unused_imports)] -#![feature(lang_items, start)] #![no_std] +#![no_main] +// Import global allocator and panic handler. extern crate std as other; #[macro_use] extern crate alloc; -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { +use alloc::string::ToString; + +#[no_mangle] +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { for _ in [1,2,3].iter() { } 0 } diff --git a/tests/ui/for-loop-while/while-let-2.stderr b/tests/ui/for-loop-while/while-let-2.stderr index 1b1cf679243..355ae6f718e 100644 --- a/tests/ui/for-loop-while/while-let-2.stderr +++ b/tests/ui/for-loop-while/while-let-2.stderr @@ -2,7 +2,7 @@ warning: irrefutable `while let` pattern --> $DIR/while-let-2.rs:7:19 | LL | while let $p = $e $b - | ^^^ + | ^^^^^^^^^^^ ... LL | / foo!(_a, 1, { LL | | println!("irrefutable pattern"); diff --git a/tests/ui/foreign/stashed-issue-121451.rs b/tests/ui/foreign/stashed-issue-121451.rs index 97a4af37475..77a736739bf 100644 --- a/tests/ui/foreign/stashed-issue-121451.rs +++ b/tests/ui/foreign/stashed-issue-121451.rs @@ -1,4 +1,4 @@ extern "C" fn _f() -> libc::uintptr_t {} -//~^ ERROR failed to resolve: use of undeclared crate or module `libc` +//~^ ERROR failed to resolve fn main() {} diff --git a/tests/ui/foreign/stashed-issue-121451.stderr b/tests/ui/foreign/stashed-issue-121451.stderr index 440d98d6f46..31dd3b4fb5e 100644 --- a/tests/ui/foreign/stashed-issue-121451.stderr +++ b/tests/ui/foreign/stashed-issue-121451.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `libc` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `libc` --> $DIR/stashed-issue-121451.rs:1:23 | LL | extern "C" fn _f() -> libc::uintptr_t {} - | ^^^^ use of undeclared crate or module `libc` + | ^^^^ use of unresolved module or unlinked crate `libc` + | + = help: you might be missing a crate named `libc` error: aborting due to 1 previous error diff --git a/tests/ui/format-no-std.rs b/tests/ui/format-no-std.rs index 27c31f48a00..657b210a9a0 100644 --- a/tests/ui/format-no-std.rs +++ b/tests/ui/format-no-std.rs @@ -1,17 +1,20 @@ //@ run-pass //@ ignore-emscripten no no_std executables +//@ ignore-wasm different `main` convention -#![feature(lang_items, start)] +#![feature(lang_items)] #![no_std] +#![no_main] +// Import global allocator and panic handler. extern crate std as other; #[macro_use] extern crate alloc; use alloc::string::ToString; -#[start] -fn start(_argc: isize, _argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: core::ffi::c_int, _argv: *const *const u8) -> core::ffi::c_int { let s = format!("{}", 1_isize); assert_eq!(s, "1".to_string()); diff --git a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs index 1a4678c7e70..b02739a7d0a 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs +++ b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.rs @@ -8,5 +8,5 @@ fn main() { //~| ERROR: binding for associated type `Y` references lifetime //~| ERROR: binding for associated type `Y` references lifetime //~| ERROR: binding for associated type `Y` references lifetime - //~| ERROR: the trait `X` cannot be made into an object + //~| ERROR: the trait `X` is not dyn compatible } diff --git a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr index 867f55b0dee..4c5a47e73c6 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr +++ b/tests/ui/generic-associated-types/gat-in-trait-path-undeclared-lifetime.stderr @@ -36,17 +36,18 @@ LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:6:19 | LL | fn _f(arg : Box<dyn for<'a> X<Y<'x> = &'a [u32]>>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/gat-in-trait-path-undeclared-lifetime.rs:2:8 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'x>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr deleted file mode 100644 index 34642f8fdc6..00000000000 --- a/tests/ui/generic-associated-types/gat-in-trait-path.base.stderr +++ /dev/null @@ -1,58 +0,0 @@ -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/gat-in-trait-path.rs:26:17 - | -LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/gat-in-trait-path.rs:10:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type A<'a> where Self: 'a; - | ^ ...because it contains the generic associated type `A` - = help: consider moving `A` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: - Fooy - Fooer<T> - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/gat-in-trait-path.rs:32:5 - | -LL | f(Box::new(foo)); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/gat-in-trait-path.rs:10:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type A<'a> where Self: 'a; - | ^ ...because it contains the generic associated type `A` - = help: consider moving `A` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: - Fooy - Fooer<T> - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/gat-in-trait-path.rs:32:5 - | -LL | f(Box::new(foo)); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/gat-in-trait-path.rs:10:10 - | -LL | trait Foo { - | --- this trait cannot be made into an object... -LL | type A<'a> where Self: 'a; - | ^ ...because it contains the generic associated type `A` - = help: consider moving `A` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: - Fooy - Fooer<T> - = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A<'a> = &'a ()> + 'static)>` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.rs b/tests/ui/generic-associated-types/gat-in-trait-path.rs index cd759a73cf2..24cae213e0a 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.rs +++ b/tests/ui/generic-associated-types/gat-in-trait-path.rs @@ -20,12 +20,11 @@ impl<T> Foo for Fooer<T> { } fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} -//~^ the trait `Foo` cannot be made into an object - +//~^ the trait `Foo` is not dyn compatible fn main() { let foo = Fooer(5); f(Box::new(foo)); - //~^ the trait `Foo` cannot be made into an object - //~| the trait `Foo` cannot be made into an object + //~^ the trait `Foo` is not dyn compatible + //~| the trait `Foo` is not dyn compatible } diff --git a/tests/ui/generic-associated-types/gat-in-trait-path.stderr b/tests/ui/generic-associated-types/gat-in-trait-path.stderr index b2176fa6de3..df79556c825 100644 --- a/tests/ui/generic-associated-types/gat-in-trait-path.stderr +++ b/tests/ui/generic-associated-types/gat-in-trait-path.stderr @@ -1,56 +1,50 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/gat-in-trait-path.rs:22:17 | LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/gat-in-trait-path.rs:6:10 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | type A<'a> where Self: 'a; | ^ ...because it contains the generic associated type `A` = help: consider moving `A` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: - Fooy - Fooer<T> -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/gat-in-trait-path.rs:28:5 +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/gat-in-trait-path.rs:27:5 | LL | f(Box::new(foo)); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/gat-in-trait-path.rs:6:10 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | type A<'a> where Self: 'a; | ^ ...because it contains the generic associated type `A` = help: consider moving `A` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: - Fooy - Fooer<T> -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/gat-in-trait-path.rs:28:5 +error[E0038]: the trait `Foo` is not dyn compatible + --> $DIR/gat-in-trait-path.rs:27:5 | LL | f(Box::new(foo)); - | ^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/gat-in-trait-path.rs:6:10 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | type A<'a> where Self: 'a; | ^ ...because it contains the generic associated type `A` = help: consider moving `A` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead: - Fooy - Fooer<T> = note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A<'a> = &'a ()> + 'static)>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs index c4134427013..85661c1b844 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.rs @@ -12,7 +12,7 @@ fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} //~| ERROR associated type takes 0 generic arguments but 1 generic argument //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments //~| ERROR at least one trait is required - //~| ERROR: the trait `X` cannot be made into an object + //~| ERROR: the trait `X` is not dyn compatible fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {} @@ -20,6 +20,6 @@ fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {} //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments - //~| ERROR: the trait `X` cannot be made into an object + //~| ERROR: the trait `X` is not dyn compatible fn main() {} diff --git a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr index 97b7019b385..499ce8e4a32 100644 --- a/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr +++ b/tests/ui/generic-associated-types/gat-trait-path-parenthesised-args.stderr @@ -123,17 +123,18 @@ error[E0224]: at least one trait is required for an object type LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} | ^^ -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/gat-trait-path-parenthesised-args.rs:5:21 | LL | fn foo<'a>(arg: Box<dyn X<Y('a) = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait @@ -188,17 +189,18 @@ help: add missing lifetime argument LL | fn bar<'a>(arg: Box<dyn X<Y('_) = ()>>) {} | ++ -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/gat-trait-path-parenthesised-args.rs:18:21 | LL | fn bar<'a>(arg: Box<dyn X<Y() = ()>>) {} - | ^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/gat-trait-path-parenthesised-args.rs:2:8 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait diff --git a/tests/ui/generic-associated-types/issue-67510-pass.base.stderr b/tests/ui/generic-associated-types/issue-67510-pass.base.stderr deleted file mode 100644 index cac8010018e..00000000000 --- a/tests/ui/generic-associated-types/issue-67510-pass.base.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0038]: the trait `X` cannot be made into an object - --> $DIR/issue-67510-pass.rs:12:23 - | -LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/issue-67510-pass.rs:9:10 - | -LL | trait X { - | - this trait cannot be made into an object... -LL | type Y<'a>; - | ^ ...because it contains the generic associated type `Y` - = help: consider moving `Y` to another trait - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-67510-pass.rs b/tests/ui/generic-associated-types/issue-67510-pass.rs index a48d9c37cd4..2bfba7f6942 100644 --- a/tests/ui/generic-associated-types/issue-67510-pass.rs +++ b/tests/ui/generic-associated-types/issue-67510-pass.rs @@ -5,6 +5,6 @@ trait X { } fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} -//~^ ERROR the trait `X` cannot be made into an object +//~^ ERROR the trait `X` is not dyn compatible fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510-pass.stderr b/tests/ui/generic-associated-types/issue-67510-pass.stderr index 5560cb0f64d..f6846f833fe 100644 --- a/tests/ui/generic-associated-types/issue-67510-pass.stderr +++ b/tests/ui/generic-associated-types/issue-67510-pass.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/issue-67510-pass.rs:7:23 | LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-67510-pass.rs:4:10 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait diff --git a/tests/ui/generic-associated-types/issue-67510.rs b/tests/ui/generic-associated-types/issue-67510.rs index ab5c25d74da..5c3150a77ed 100644 --- a/tests/ui/generic-associated-types/issue-67510.rs +++ b/tests/ui/generic-associated-types/issue-67510.rs @@ -5,6 +5,6 @@ trait X { fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {} //~^ ERROR: use of undeclared lifetime name `'a` //~| ERROR: use of undeclared lifetime name `'a` -//~| ERROR: the trait `X` cannot be made into an object [E0038] +//~| ERROR: the trait `X` is not dyn compatible [E0038] fn main() {} diff --git a/tests/ui/generic-associated-types/issue-67510.stderr b/tests/ui/generic-associated-types/issue-67510.stderr index 416f04ac2fd..e8555a7aa1f 100644 --- a/tests/ui/generic-associated-types/issue-67510.stderr +++ b/tests/ui/generic-associated-types/issue-67510.stderr @@ -29,17 +29,18 @@ help: consider introducing lifetime `'a` here LL | fn f<'a>(x: Box<dyn X<Y<'a> = &'a ()>>) {} | ++++ -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/issue-67510.rs:5:13 | LL | fn f(x: Box<dyn X<Y<'a> = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-67510.rs:2:10 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait diff --git a/tests/ui/generic-associated-types/issue-71176.rs b/tests/ui/generic-associated-types/issue-71176.rs index 7fffe312f4b..d3a0caffec1 100644 --- a/tests/ui/generic-associated-types/issue-71176.rs +++ b/tests/ui/generic-associated-types/issue-71176.rs @@ -11,13 +11,13 @@ struct Holder<B> { //~^ ERROR: missing generics for associated type //~| ERROR: missing generics for associated type //~| ERROR: missing generics for associated type - //~| ERROR: the trait `Provider` cannot be made into an object + //~| ERROR: the trait `Provider` is not dyn compatible } fn main() { Holder { inner: Box::new(()), - //~^ ERROR: the trait `Provider` cannot be made into an object - //~| ERROR: the trait `Provider` cannot be made into an object + //~^ ERROR: the trait `Provider` is not dyn compatible + //~| ERROR: the trait `Provider` is not dyn compatible }; } diff --git a/tests/ui/generic-associated-types/issue-71176.stderr b/tests/ui/generic-associated-types/issue-71176.stderr index 1cd2ed0d313..a78151384d4 100644 --- a/tests/ui/generic-associated-types/issue-71176.stderr +++ b/tests/ui/generic-associated-types/issue-71176.stderr @@ -48,53 +48,56 @@ help: add missing lifetime argument LL | inner: Box<dyn Provider<A<'a> = B>>, | ++++ -error[E0038]: the trait `Provider` cannot be made into an object +error[E0038]: the trait `Provider` is not dyn compatible --> $DIR/issue-71176.rs:10:14 | LL | inner: Box<dyn Provider<A = B>>, - | ^^^^^^^^^^^^^^^^^^^ `Provider` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `Provider` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-71176.rs:2:10 | LL | trait Provider { - | -------- this trait cannot be made into an object... + | -------- this trait is not dyn compatible... LL | type A<'a>; | ^ ...because it contains the generic associated type `A` = help: consider moving `A` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `Provider`; consider using it directly instead. -error[E0038]: the trait `Provider` cannot be made into an object +error[E0038]: the trait `Provider` is not dyn compatible --> $DIR/issue-71176.rs:19:16 | LL | inner: Box::new(()), - | ^^^^^^^^^^^^ `Provider` cannot be made into an object + | ^^^^^^^^^^^^ `Provider` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-71176.rs:2:10 | LL | trait Provider { - | -------- this trait cannot be made into an object... + | -------- this trait is not dyn compatible... LL | type A<'a>; | ^ ...because it contains the generic associated type `A` = help: consider moving `A` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `Provider`; consider using it directly instead. -error[E0038]: the trait `Provider` cannot be made into an object +error[E0038]: the trait `Provider` is not dyn compatible --> $DIR/issue-71176.rs:19:16 | LL | inner: Box::new(()), - | ^^^^^^^^^^^^ `Provider` cannot be made into an object + | ^^^^^^^^^^^^ `Provider` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-71176.rs:2:10 | LL | trait Provider { - | -------- this trait cannot be made into an object... + | -------- this trait is not dyn compatible... LL | type A<'a>; | ^ ...because it contains the generic associated type `A` = help: consider moving `A` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `Provider`; consider using it directly instead. = note: required for the cast from `Box<()>` to `Box<(dyn Provider<A<'_> = _> + 'static), {type error}>` error: aborting due to 6 previous errors diff --git a/tests/ui/generic-associated-types/issue-76535.base.stderr b/tests/ui/generic-associated-types/issue-76535.base.stderr deleted file mode 100644 index a44c8dc51e7..00000000000 --- a/tests/ui/generic-associated-types/issue-76535.base.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error[E0107]: missing generics for associated type `SuperTrait::SubType` - --> $DIR/issue-76535.rs:39:33 - | -LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); - | ^^^^^^^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-76535.rs:9:10 - | -LL | type SubType<'a>: SubTrait where Self: 'a; - | ^^^^^^^ -- -help: add missing lifetime argument - | -LL | let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0)); - | ++++ - -error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/issue-76535.rs:39:14 - | -LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/issue-76535.rs:9:10 - | -LL | pub trait SuperTrait { - | ---------- this trait cannot be made into an object... -LL | type SubType<'a>: SubTrait where Self: 'a; - | ^^^^^^^ ...because it contains the generic associated type `SubType` - = help: consider moving `SubType` to another trait - = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead - = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type - -error[E0038]: the trait `SuperTrait` cannot be made into an object - --> $DIR/issue-76535.rs:39:57 - | -LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/issue-76535.rs:9:10 - | -LL | pub trait SuperTrait { - | ---------- this trait cannot be made into an object... -LL | type SubType<'a>: SubTrait where Self: 'a; - | ^^^^^^^ ...because it contains the generic associated type `SubType` - = help: consider moving `SubType` to another trait - = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead - = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type - = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType<'_> = SubStruct<'_>>>` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0038, E0107. -For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-76535.extended.stderr b/tests/ui/generic-associated-types/issue-76535.extended.stderr deleted file mode 100644 index f6fe8b16902..00000000000 --- a/tests/ui/generic-associated-types/issue-76535.extended.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0107]: missing generics for associated type `SuperTrait::SubType` - --> $DIR/issue-76535.rs:39:33 - | -LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); - | ^^^^^^^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-76535.rs:9:10 - | -LL | type SubType<'a>: SubTrait where Self: 'a; - | ^^^^^^^ -- -help: add missing lifetime argument - | -LL | let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0)); - | ++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-76535.stderr b/tests/ui/generic-associated-types/issue-76535.stderr index 613ded6f1ef..6b7c3bfe731 100644 --- a/tests/ui/generic-associated-types/issue-76535.stderr +++ b/tests/ui/generic-associated-types/issue-76535.stderr @@ -14,39 +14,41 @@ help: add missing lifetime argument LL | let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0)); | ++++ -error[E0038]: the trait `SuperTrait` cannot be made into an object +error[E0038]: the trait `SuperTrait` is not dyn compatible --> $DIR/issue-76535.rs:34:14 | LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-76535.rs:4:10 | LL | pub trait SuperTrait { - | ---------- this trait cannot be made into an object... + | ---------- this trait is not dyn compatible... LL | type SubType<'a>: SubTrait where Self: 'a; | ^^^^^^^ ...because it contains the generic associated type `SubType` = help: consider moving `SubType` to another trait - = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead - = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type + = help: only type `SuperStruct` implements `SuperTrait` within this crate; consider using it directly instead. + = note: `SuperTrait` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type -error[E0038]: the trait `SuperTrait` cannot be made into an object +error[E0038]: the trait `SuperTrait` is not dyn compatible --> $DIR/issue-76535.rs:34:57 | LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-76535.rs:4:10 | LL | pub trait SuperTrait { - | ---------- this trait cannot be made into an object... + | ---------- this trait is not dyn compatible... LL | type SubType<'a>: SubTrait where Self: 'a; | ^^^^^^^ ...because it contains the generic associated type `SubType` = help: consider moving `SubType` to another trait - = help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead - = note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type + = help: only type `SuperStruct` implements `SuperTrait` within this crate; consider using it directly instead. + = note: `SuperTrait` may be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type = note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType<'_> = SubStruct<'_>>>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-78671.base.stderr b/tests/ui/generic-associated-types/issue-78671.base.stderr deleted file mode 100644 index 9f2be785460..00000000000 --- a/tests/ui/generic-associated-types/issue-78671.base.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0107]: missing generics for associated type `CollectionFamily::Member` - --> $DIR/issue-78671.rs:10:47 - | -LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> - | ^^^^^^ expected 1 generic argument - | -note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-78671.rs:7:10 - | -LL | type Member<T>; - | ^^^^^^ - -help: add missing generic argument - | -LL | Box::new(Family) as &dyn CollectionFamily<Member<T>=usize> - | +++ - -error[E0038]: the trait `CollectionFamily` cannot be made into an object - --> $DIR/issue-78671.rs:10:25 - | -LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/issue-78671.rs:7:10 - | -LL | trait CollectionFamily { - | ---------------- this trait cannot be made into an object... -LL | type Member<T>; - | ^^^^^^ ...because it contains the generic associated type `Member` - = help: consider moving `Member` to another trait - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0038, E0107. -For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-78671.extended.stderr b/tests/ui/generic-associated-types/issue-78671.extended.stderr deleted file mode 100644 index a5d56256d28..00000000000 --- a/tests/ui/generic-associated-types/issue-78671.extended.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0107]: missing generics for associated type `CollectionFamily::Member` - --> $DIR/issue-78671.rs:10:47 - | -LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> - | ^^^^^^ expected 1 generic argument - | -note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-78671.rs:7:10 - | -LL | type Member<T>; - | ^^^^^^ - -help: add missing generic argument - | -LL | Box::new(Family) as &dyn CollectionFamily<Member<T>=usize> - | +++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-78671.rs b/tests/ui/generic-associated-types/issue-78671.rs index 0871def1731..1e1863799a5 100644 --- a/tests/ui/generic-associated-types/issue-78671.rs +++ b/tests/ui/generic-associated-types/issue-78671.rs @@ -4,7 +4,7 @@ trait CollectionFamily { fn floatify() { Box::new(Family) as &dyn CollectionFamily<Member=usize> //~^ ERROR: missing generics for associated type - //~| ERROR: the trait `CollectionFamily` cannot be made into an object + //~| ERROR: the trait `CollectionFamily` is not dyn compatible } struct Family; diff --git a/tests/ui/generic-associated-types/issue-78671.stderr b/tests/ui/generic-associated-types/issue-78671.stderr index fbd76c73895..c85e97067cb 100644 --- a/tests/ui/generic-associated-types/issue-78671.stderr +++ b/tests/ui/generic-associated-types/issue-78671.stderr @@ -14,17 +14,18 @@ help: add missing generic argument LL | Box::new(Family) as &dyn CollectionFamily<Member<T>=usize> | +++ -error[E0038]: the trait `CollectionFamily` cannot be made into an object +error[E0038]: the trait `CollectionFamily` is not dyn compatible --> $DIR/issue-78671.rs:5:25 | LL | Box::new(Family) as &dyn CollectionFamily<Member=usize> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-78671.rs:2:10 | LL | trait CollectionFamily { - | ---------------- this trait cannot be made into an object... + | ---------------- this trait is not dyn compatible... LL | type Member<T>; | ^^^^^^ ...because it contains the generic associated type `Member` = help: consider moving `Member` to another trait diff --git a/tests/ui/generic-associated-types/issue-79422.base.stderr b/tests/ui/generic-associated-types/issue-79422.base.stderr deleted file mode 100644 index 3ea62bdbb27..00000000000 --- a/tests/ui/generic-associated-types/issue-79422.base.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error[E0107]: missing generics for associated type `MapLike::VRefCont` - --> $DIR/issue-79422.rs:47:36 - | -LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; - | ^^^^^^^^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-79422.rs:23:10 - | -LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; - | ^^^^^^^^ -- -help: add missing lifetime argument - | -LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>; - | ++++ - -error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:47:12 - | -LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/issue-79422.rs:23:10 - | -LL | trait MapLike<K, V> { - | ------- this trait cannot be made into an object... -LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; - | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` - = help: consider moving `VRefCont` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: - std::collections::BTreeMap<K, V> - Source - -error[E0038]: the trait `MapLike` cannot be made into an object - --> $DIR/issue-79422.rs:44:13 - | -LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/issue-79422.rs:23:10 - | -LL | trait MapLike<K, V> { - | ------- this trait cannot be made into an object... -LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; - | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` - = help: consider moving `VRefCont` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: - std::collections::BTreeMap<K, V> - Source - = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>` - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0038, E0107. -For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/issue-79422.extended.stderr b/tests/ui/generic-associated-types/issue-79422.extended.stderr deleted file mode 100644 index 031f8d8d851..00000000000 --- a/tests/ui/generic-associated-types/issue-79422.extended.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error[E0107]: missing generics for associated type `MapLike::VRefCont` - --> $DIR/issue-79422.rs:47:36 - | -LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; - | ^^^^^^^^ expected 1 lifetime argument - | -note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-79422.rs:23:10 - | -LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; - | ^^^^^^^^ -- -help: add missing lifetime argument - | -LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>; - | ++++ - -error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == dyn RefCont<'_, u8>` - --> $DIR/issue-79422.rs:44:13 - | -LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'_> == dyn RefCont<'_, u8>` - | -note: expected this to be `(dyn RefCont<'_, u8> + 'static)` - --> $DIR/issue-79422.rs:28:25 - | -LL | type VRefCont<'a> = &'a V where Self: 'a; - | ^^^^^ - = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` - found reference `&u8` - = help: `&u8` implements `RefCont` so you could box the found value and coerce it to the trait object `Box<dyn RefCont>`, you will have to change the expected type as well - = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0107, E0271. -For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/generic-associated-types/issue-79422.stderr b/tests/ui/generic-associated-types/issue-79422.stderr index 26567e5e927..a81217e96c3 100644 --- a/tests/ui/generic-associated-types/issue-79422.stderr +++ b/tests/ui/generic-associated-types/issue-79422.stderr @@ -14,41 +14,37 @@ help: add missing lifetime argument LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>; | ++++ -error[E0038]: the trait `MapLike` cannot be made into an object +error[E0038]: the trait `MapLike` is not dyn compatible --> $DIR/issue-79422.rs:41:12 | LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-79422.rs:18:10 | LL | trait MapLike<K, V> { - | ------- this trait cannot be made into an object... + | ------- this trait is not dyn compatible... LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` = help: consider moving `VRefCont` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: - std::collections::BTreeMap<K, V> - Source -error[E0038]: the trait `MapLike` cannot be made into an object +error[E0038]: the trait `MapLike` is not dyn compatible --> $DIR/issue-79422.rs:39:13 | LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-79422.rs:18:10 | LL | trait MapLike<K, V> { - | ------- this trait cannot be made into an object... + | ------- this trait is not dyn compatible... LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; | ^^^^^^^^ ...because it contains the generic associated type `VRefCont` = help: consider moving `VRefCont` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead: - std::collections::BTreeMap<K, V> - Source = note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>` error: aborting due to 3 previous errors diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.next-solver.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.next-solver.stderr deleted file mode 100644 index 85c5dad7fc0..00000000000 --- a/tests/ui/generic-associated-types/issue-90014-tait2.next-solver.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-90014-tait2.rs:27:9 - | -LL | fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> { - | ------------------------------------------- expected `Box<(dyn for<'a> Trait<'a, Thing = Fut<'a>> + 'static)>` because of return type -LL | Box::new((async { () },)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Trait<'a, Thing = Fut<'_>>>`, found `Box<(...,)>` - | - = note: expected struct `Box<(dyn for<'a> Trait<'a, Thing = Fut<'a>> + 'static)>` - found struct `Box<({async block@$DIR/issue-90014-tait2.rs:27:19: 27:31},)>` - = help: `({async block@$DIR/issue-90014-tait2.rs:27:19: 27:31},)` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/generic-associated-types/issue-91139.migrate.stderr b/tests/ui/generic-associated-types/issue-91139.migrate.stderr deleted file mode 100644 index e3b658558e3..00000000000 --- a/tests/ui/generic-associated-types/issue-91139.migrate.stderr +++ /dev/null @@ -1,7 +0,0 @@ -error: expected identifier, found `<<` - --> $DIR/issue-91139.rs:1:1 - | - | ^^ expected identifier - -error: aborting due to 1 previous error - diff --git a/tests/ui/generic-associated-types/issue-92096.migrate.stderr b/tests/ui/generic-associated-types/issue-92096.migrate.stderr deleted file mode 100644 index ce1fd6dd983..00000000000 --- a/tests/ui/generic-associated-types/issue-92096.migrate.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0311]: the parameter type `C` may not live long enough - --> $DIR/issue-92096.rs:19:33 - | -LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send - | ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound... - | -LL | C: Client + Send + Sync + 'a, - | ++++ - -error[E0311]: the parameter type `C` may not live long enough - --> $DIR/issue-92096.rs:19:33 - | -LL | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send - | ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound... - | -LL | C: Client + Send + Sync + 'a, - | ++++ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.rs b/tests/ui/generic-associated-types/missing_lifetime_args.rs index 470db5412b2..e0f2db5eb21 100644 --- a/tests/ui/generic-associated-types/missing_lifetime_args.rs +++ b/tests/ui/generic-associated-types/missing_lifetime_args.rs @@ -12,7 +12,7 @@ fn foo<'c, 'd>(_arg: Box<dyn X<Y = (&'c u32, &'d u32)>>) {} //~^ ERROR missing generics for associated type //~| ERROR missing generics for associated type //~| ERROR missing generics for associated type -//~| ERROR the trait `X` cannot be made into an object +//~| ERROR the trait `X` is not dyn compatible fn bar<'a, 'b, 'c>(_arg: Foo<'a, 'b>) {} //~^ ERROR struct takes 3 lifetime arguments but 2 lifetime diff --git a/tests/ui/generic-associated-types/missing_lifetime_args.stderr b/tests/ui/generic-associated-types/missing_lifetime_args.stderr index 61cf4f3dd4a..6b8df5cc12f 100644 --- a/tests/ui/generic-associated-types/missing_lifetime_args.stderr +++ b/tests/ui/generic-associated-types/missing_lifetime_args.stderr @@ -48,17 +48,18 @@ help: add missing lifetime arguments LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y<'_, '_> = (&'c u32, &'d u32)>>) {} | ++++++++ -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/missing_lifetime_args.rs:11:26 | LL | fn foo<'c, 'd>(_arg: Box<dyn X<Y = (&'c u32, &'d u32)>>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/missing_lifetime_args.rs:2:10 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'a, 'b>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs index d6fc3df1026..c828691bb30 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs +++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.rs @@ -10,7 +10,7 @@ const _: () = { //~| ERROR associated type takes 0 generic arguments but 1 generic argument //~| ERROR associated type takes 1 lifetime argument but 0 lifetime arguments //~| ERROR associated type takes 0 generic arguments but 1 generic argument - //~| ERROR the trait `X` cannot be made into an object + //~| ERROR the trait `X` is not dyn compatible }; fn main() {} diff --git a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr index 91f0f7b3fcf..5c9e9dbe3d7 100644 --- a/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr +++ b/tests/ui/generic-associated-types/parse/trait-path-type-error-once-implemented.stderr @@ -92,17 +92,18 @@ LL | type Y<'a>; | ^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/trait-path-type-error-once-implemented.rs:6:23 | LL | fn f2<'a>(arg : Box<dyn X<Y<1> = &'a ()>>) {} - | ^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/trait-path-type-error-once-implemented.rs:2:10 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | type Y<'a>; | ^ ...because it contains the generic associated type `Y` = help: consider moving `Y` to another trait diff --git a/tests/ui/generic-associated-types/trait-objects.base.stderr b/tests/ui/generic-associated-types/trait-objects.base.stderr deleted file mode 100644 index 0b5a9b9f7fb..00000000000 --- a/tests/ui/generic-associated-types/trait-objects.base.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error[E0038]: the trait `StreamingIterator` cannot be made into an object - --> $DIR/trait-objects.rs:13:21 - | -LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/trait-objects.rs:7:10 - | -LL | trait StreamingIterator { - | ----------------- this trait cannot be made into an object... -LL | type Item<'a> where Self: 'a; - | ^^^^ ...because it contains the generic associated type `Item` - = help: consider moving `Item` to another trait - -error[E0038]: the trait `StreamingIterator` cannot be made into an object - --> $DIR/trait-objects.rs:15:7 - | -LL | x.size_hint().0 - | ^^^^^^^^^ `StreamingIterator` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/trait-objects.rs:7:10 - | -LL | trait StreamingIterator { - | ----------------- this trait cannot be made into an object... -LL | type Item<'a> where Self: 'a; - | ^^^^ ...because it contains the generic associated type `Item` - = help: consider moving `Item` to another trait - -error[E0038]: the trait `StreamingIterator` cannot be made into an object - --> $DIR/trait-objects.rs:15:5 - | -LL | x.size_hint().0 - | ^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/trait-objects.rs:7:10 - | -LL | trait StreamingIterator { - | ----------------- this trait cannot be made into an object... -LL | type Item<'a> where Self: 'a; - | ^^^^ ...because it contains the generic associated type `Item` - = help: consider moving `Item` to another trait - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/generic-associated-types/trait-objects.extended.stderr b/tests/ui/generic-associated-types/trait-objects.extended.stderr deleted file mode 100644 index 9f9418e20b9..00000000000 --- a/tests/ui/generic-associated-types/trait-objects.extended.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0521]: borrowed data escapes outside of function - --> $DIR/trait-objects.rs:15:5 - | -LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { - | - - let's call the lifetime of this reference `'1` - | | - | `x` is a reference that is only valid in the function body -LL | -LL | x.size_hint().0 - | ^^^^^^^^^^^^^ - | | - | `x` escapes the function body here - | argument requires that `'1` must outlive `'static` - | - = note: due to current limitations in the borrow checker, this implies a `'static` lifetime - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/generic-associated-types/trait-objects.rs b/tests/ui/generic-associated-types/trait-objects.rs index bad9289ee5e..ed324b562e1 100644 --- a/tests/ui/generic-associated-types/trait-objects.rs +++ b/tests/ui/generic-associated-types/trait-objects.rs @@ -6,10 +6,10 @@ trait StreamingIterator { } fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { - //~^ the trait `StreamingIterator` cannot be made into an object + //~^ the trait `StreamingIterator` is not dyn compatible x.size_hint().0 - //~^ the trait `StreamingIterator` cannot be made into an object - //~| the trait `StreamingIterator` cannot be made into an object + //~^ the trait `StreamingIterator` is not dyn compatible + //~| the trait `StreamingIterator` is not dyn compatible } fn main() {} diff --git a/tests/ui/generic-associated-types/trait-objects.stderr b/tests/ui/generic-associated-types/trait-objects.stderr index 3e74776f999..56a1cb1906f 100644 --- a/tests/ui/generic-associated-types/trait-objects.stderr +++ b/tests/ui/generic-associated-types/trait-objects.stderr @@ -1,44 +1,47 @@ -error[E0038]: the trait `StreamingIterator` cannot be made into an object +error[E0038]: the trait `StreamingIterator` is not dyn compatible --> $DIR/trait-objects.rs:8:21 | LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/trait-objects.rs:2:10 | LL | trait StreamingIterator { - | ----------------- this trait cannot be made into an object... + | ----------------- this trait is not dyn compatible... LL | type Item<'a> where Self: 'a; | ^^^^ ...because it contains the generic associated type `Item` = help: consider moving `Item` to another trait -error[E0038]: the trait `StreamingIterator` cannot be made into an object +error[E0038]: the trait `StreamingIterator` is not dyn compatible --> $DIR/trait-objects.rs:10:7 | LL | x.size_hint().0 - | ^^^^^^^^^ `StreamingIterator` cannot be made into an object + | ^^^^^^^^^ `StreamingIterator` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/trait-objects.rs:2:10 | LL | trait StreamingIterator { - | ----------------- this trait cannot be made into an object... + | ----------------- this trait is not dyn compatible... LL | type Item<'a> where Self: 'a; | ^^^^ ...because it contains the generic associated type `Item` = help: consider moving `Item` to another trait -error[E0038]: the trait `StreamingIterator` cannot be made into an object +error[E0038]: the trait `StreamingIterator` is not dyn compatible --> $DIR/trait-objects.rs:10:5 | LL | x.size_hint().0 - | ^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object + | ^^^^^^^^^^^^^ `StreamingIterator` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/trait-objects.rs:2:10 | LL | trait StreamingIterator { - | ----------------- this trait cannot be made into an object... + | ----------------- this trait is not dyn compatible... LL | type Item<'a> where Self: 'a; | ^^^^ ...because it contains the generic associated type `Item` = help: consider moving `Item` to another trait diff --git a/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr b/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr deleted file mode 100644 index b6f9bdce1cb..00000000000 --- a/tests/ui/generic-const-items/evaluatable-bounds.unconstrained.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: unconstrained generic constant - --> $DIR/evaluatable-bounds.rs:16:5 - | -LL | const ARRAY: [i32; Self::LEN]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: try adding a `where` bound - | -LL | const ARRAY: [i32; Self::LEN] where [(); Self::LEN]:; - | ++++++++++++++++++++++ - -error: aborting due to 1 previous error - diff --git a/tests/ui/generics/issue-79605.stderr b/tests/ui/generics/issue-79605.stderr index 67fed200f96..049f77a6584 100644 --- a/tests/ui/generics/issue-79605.stderr +++ b/tests/ui/generics/issue-79605.stderr @@ -3,11 +3,6 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures | LL | impl X<'_, _> {} | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | impl<T> X<'_, T> {} - | +++ ~ error: aborting due to 1 previous error diff --git a/tests/ui/hashmap/hashmap-capacity-overflow.rs b/tests/ui/hashmap/hashmap-capacity-overflow.rs index 91aebc3bbba..502dbe9fa93 100644 --- a/tests/ui/hashmap/hashmap-capacity-overflow.rs +++ b/tests/ui/hashmap/hashmap-capacity-overflow.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:capacity overflow -//@ ignore-emscripten no processes +//@ needs-subprocess use std::collections::hash_map::HashMap; use std::mem::size_of; diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr deleted file mode 100644 index 795484f1108..00000000000 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.polonius.stderr +++ /dev/null @@ -1,71 +0,0 @@ -warning: function cannot return without recursing - --> $DIR/hrtb-perfect-forwarding.rs:16:1 - | -LL | / fn no_hrtb<'b, T>(mut t: T) -LL | | where -LL | | T: Bar<&'b isize>, -LL | | { -... | -LL | | no_hrtb(&mut t); - | | --------------- recursive call site -LL | | } - | |_^ cannot return without recursing - | - = note: `#[warn(unconditional_recursion)]` on by default - = help: a `loop` may express intention better if this is on purpose - -warning: function cannot return without recursing - --> $DIR/hrtb-perfect-forwarding.rs:25:1 - | -LL | / fn bar_hrtb<T>(mut t: T) -LL | | where -LL | | T: for<'b> Bar<&'b isize>, -LL | | { -... | -LL | | bar_hrtb(&mut t); - | | ---------------- recursive call site -LL | | } - | |_^ cannot return without recursing - | - = help: a `loop` may express intention better if this is on purpose - -warning: function cannot return without recursing - --> $DIR/hrtb-perfect-forwarding.rs:35:1 - | -LL | / fn foo_hrtb_bar_not<'b, T>(mut t: T) -LL | | where -LL | | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, -LL | | { -... | -LL | | foo_hrtb_bar_not(&mut t); - | | ------------------------ recursive call site -LL | | -LL | | -LL | | } - | |_^ cannot return without recursing - | - = help: a `loop` may express intention better if this is on purpose - -error: higher-ranked subtype error - --> $DIR/hrtb-perfect-forwarding.rs:43:5 - | -LL | foo_hrtb_bar_not(&mut t); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: function cannot return without recursing - --> $DIR/hrtb-perfect-forwarding.rs:48:1 - | -LL | / fn foo_hrtb_bar_hrtb<T>(mut t: T) -LL | | where -LL | | T: for<'a> Foo<&'a isize> + for<'b> Bar<&'b isize>, -LL | | { -LL | | // OK -- now we have `T : for<'b> Bar<&'b isize>`. -LL | | foo_hrtb_bar_hrtb(&mut t); - | | ------------------------- recursive call site -LL | | } - | |_^ cannot return without recursing - | - = help: a `loop` may express intention better if this is on purpose - -error: aborting due to 1 previous error; 4 warnings emitted - diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs index a44ed9e5ef5..34548e2487e 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs @@ -43,9 +43,9 @@ fn main() { } foo(bar, "string", |s| s.len() == 5); - //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough + //~^ ERROR implementation of `Parser` is not general enough + //~| ERROR implementation of `Parser` is not general enough foo(baz, "string", |s| s.0.len() == 5); - //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough + //~^ ERROR implementation of `Parser` is not general enough + //~| ERROR implementation of `Parser` is not general enough } diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr index b2bb417a8f0..23fc6e2f7f4 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr @@ -1,39 +1,39 @@ -error: implementation of `FnOnce` is not general enough +error: implementation of `Parser` is not general enough --> $DIR/issue-71955.rs:45:5 | LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough | - = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` -error: implementation of `FnOnce` is not general enough +error: implementation of `Parser` is not general enough --> $DIR/issue-71955.rs:45:5 | LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough | - = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` + = note: `for<'a> fn(&'a str) -> (&'a str, &'a str) {bar}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: implementation of `FnOnce` is not general enough +error: implementation of `Parser` is not general enough --> $DIR/issue-71955.rs:48:5 | LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough | - = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` -error: implementation of `FnOnce` is not general enough +error: implementation of `Parser` is not general enough --> $DIR/issue-71955.rs:48:5 | LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Parser` is not general enough | - = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` + = note: `for<'a> fn(&'a str) -> (&'a str, Wrapper<'a>) {baz}` must implement `Parser<'0>`, for any lifetime `'0`... + = note: ...but it actually implements `Parser<'1>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs index aeace9f2158..5d039cd5dc6 100644 --- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs +++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.rs @@ -12,8 +12,8 @@ fn needs_bar(_: *mut Type2) {} fn main() { let x: &dyn Foo = &(); - //~^ ERROR the trait `Foo` cannot be made into an object - //~| ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Foo` is not dyn compatible needs_bar(x); //~^ ERROR mismatched types diff --git a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr index d48bf8a471d..fc3d9c2171d 100644 --- a/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr +++ b/tests/ui/higher-ranked/trait-bounds/span-bug-issue-121597.stderr @@ -1,31 +1,33 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/span-bug-issue-121597.rs:14:23 | LL | let x: &dyn Foo = &(); - | ^^^ `Foo` cannot be made into an object + | ^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/span-bug-issue-121597.rs:4:12 | LL | trait Foo: for<T> Bar<T> {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... = note: required for the cast from `&()` to `&dyn Foo` -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/span-bug-issue-121597.rs:14:12 | LL | let x: &dyn Foo = &(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/span-bug-issue-121597.rs:4:12 | LL | trait Foo: for<T> Bar<T> {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... error[E0308]: mismatched types --> $DIR/span-bug-issue-121597.rs:18:15 diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs index aaf831d1983..71c33674b37 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs @@ -10,7 +10,7 @@ macro a() { mod u { // Late resolution. fn f() { my_core::mem::drop(0); } - //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `my_core` } } @@ -23,7 +23,7 @@ mod v { mod u { // Late resolution. fn f() { my_core::mem::drop(0); } - //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `my_core` } fn main() {} diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr index cc229764ad3..87ef07c27f5 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr @@ -15,25 +15,27 @@ LL | a!(); | = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `my_core` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `my_core` --> $DIR/extern-prelude-from-opaque-fail-2018.rs:12:18 | LL | fn f() { my_core::mem::drop(0); } - | ^^^^^^^ use of undeclared crate or module `my_core` + | ^^^^^^^ use of unresolved module or unlinked crate `my_core` ... LL | a!(); | ---- in this macro invocation | + = help: you might be missing a crate named `my_core` = help: consider importing this module: std::mem = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `my_core` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `my_core` --> $DIR/extern-prelude-from-opaque-fail-2018.rs:25:14 | LL | fn f() { my_core::mem::drop(0); } - | ^^^^^^^ use of undeclared crate or module `my_core` + | ^^^^^^^ use of unresolved module or unlinked crate `my_core` | + = help: you might be missing a crate named `my_core` help: consider importing this module | LL + use std::mem; diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs index be3102aeab0..8265b73cc56 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs @@ -10,7 +10,7 @@ macro a() { mod u { // Late resolution. fn f() { my_core::mem::drop(0); } - //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `my_core` } } @@ -23,7 +23,7 @@ mod v { mod u { // Late resolution. fn f() { my_core::mem::drop(0); } - //~^ ERROR failed to resolve: use of undeclared crate or module `my_core` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `my_core` } fn main() {} diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr index 13b2827ef39..d36bc913095 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -15,25 +15,27 @@ LL | a!(); | = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `my_core` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `my_core` --> $DIR/extern-prelude-from-opaque-fail.rs:12:18 | LL | fn f() { my_core::mem::drop(0); } - | ^^^^^^^ use of undeclared crate or module `my_core` + | ^^^^^^^ use of unresolved module or unlinked crate `my_core` ... LL | a!(); | ---- in this macro invocation | + = help: you might be missing a crate named `my_core` = help: consider importing this module: my_core::mem = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `my_core` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `my_core` --> $DIR/extern-prelude-from-opaque-fail.rs:25:14 | LL | fn f() { my_core::mem::drop(0); } - | ^^^^^^^ use of undeclared crate or module `my_core` + | ^^^^^^^ use of unresolved module or unlinked crate `my_core` | + = help: you might be missing a crate named `my_core` help: consider importing this module | LL + use my_core::mem; diff --git a/tests/ui/impl-trait/auto-trait-coherence.next.stderr b/tests/ui/impl-trait/auto-trait-coherence.next.stderr deleted file mode 100644 index cd91bfcb48d..00000000000 --- a/tests/ui/impl-trait/auto-trait-coherence.next.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` - --> $DIR/auto-trait-coherence.rs:24:1 - | -LL | impl<T: Send> AnotherTrait for T {} - | -------------------------------- first implementation here -... -LL | impl AnotherTrait for D<OpaqueType> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/auto-trait-coherence.old.stderr b/tests/ui/impl-trait/auto-trait-coherence.old.stderr deleted file mode 100644 index cd91bfcb48d..00000000000 --- a/tests/ui/impl-trait/auto-trait-coherence.old.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>` - --> $DIR/auto-trait-coherence.rs:24:1 - | -LL | impl<T: Send> AnotherTrait for T {} - | -------------------------------- first implementation here -... -LL | impl AnotherTrait for D<OpaqueType> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<_>` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr b/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr deleted file mode 100644 index 444f3d6689f..00000000000 --- a/tests/ui/impl-trait/coherence-treats-tait-ambig.current.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0119]: conflicting implementations of trait `Into<T>` for type `Foo` - --> $DIR/coherence-treats-tait-ambig.rs:10:1 - | -LL | impl Into<T> for Foo { - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<T, U> Into<U> for T - where U: From<T>; - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs index 76dbb05f53d..046ced072ba 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.rs @@ -19,7 +19,7 @@ impl DynIncompatible for B { } } -fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` cannot be made into an object +fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` is not dyn compatible //~^ ERROR return type cannot have an unboxed trait object if true { return A; @@ -27,11 +27,11 @@ fn car() -> dyn DynIncompatible { //~ ERROR the trait `DynIncompatible` cannot b B } -fn cat() -> Box<dyn DynIncompatible> { //~ ERROR the trait `DynIncompatible` cannot be made into an +fn cat() -> Box<dyn DynIncompatible> { //~ ERROR the trait `DynIncompatible` is not dyn compatible if true { - return Box::new(A); //~ ERROR cannot be made into an object + return Box::new(A); //~ ERROR is not dyn compatible } - Box::new(B) //~ ERROR cannot be made into an object + Box::new(B) //~ ERROR is not dyn compatible } fn main() {} diff --git a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr index 576bd909cbc..4abd7bcf31c 100644 --- a/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr +++ b/tests/ui/impl-trait/dyn-incompatible-trait-in-return-position-dyn-trait.stderr @@ -1,19 +1,22 @@ -error[E0038]: the trait `DynIncompatible` cannot be made into an object +error[E0038]: the trait `DynIncompatible` is not dyn compatible --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:22:13 | LL | fn car() -> dyn DynIncompatible { - | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | LL | trait DynIncompatible { - | --------------- this trait cannot be made into an object... + | --------------- this trait is not dyn compatible... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: + = help: the following types implement `DynIncompatible`: A B + consider defining an enum where each variant holds one of these types, + implementing `DynIncompatible` for this new enum and using it instead help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) -> Self; @@ -23,22 +26,25 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `DynIncompatible` cannot be made into an object +error[E0038]: the trait `DynIncompatible` is not dyn compatible --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:30:17 | LL | fn cat() -> Box<dyn DynIncompatible> { - | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^ `DynIncompatible` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | LL | trait DynIncompatible { - | --------------- this trait cannot be made into an object... + | --------------- this trait is not dyn compatible... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: + = help: the following types implement `DynIncompatible`: A B + consider defining an enum where each variant holds one of these types, + implementing `DynIncompatible` for this new enum and using it instead help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self) -> Self; @@ -65,22 +71,25 @@ LL | } LL ~ Box::new(B) | -error[E0038]: the trait `DynIncompatible` cannot be made into an object +error[E0038]: the trait `DynIncompatible` is not dyn compatible --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:32:16 | LL | return Box::new(A); - | ^^^^^^^^^^^ `DynIncompatible` cannot be made into an object + | ^^^^^^^^^^^ `DynIncompatible` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | LL | trait DynIncompatible { - | --------------- this trait cannot be made into an object... + | --------------- this trait is not dyn compatible... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: + = help: the following types implement `DynIncompatible`: A B + consider defining an enum where each variant holds one of these types, + implementing `DynIncompatible` for this new enum and using it instead = note: required for the cast from `Box<A>` to `Box<(dyn DynIncompatible + 'static)>` help: consider turning `foo` into a method by giving it a `&self` argument | @@ -91,22 +100,25 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `DynIncompatible` cannot be made into an object +error[E0038]: the trait `DynIncompatible` is not dyn compatible --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:34:5 | LL | Box::new(B) - | ^^^^^^^^^^^ `DynIncompatible` cannot be made into an object + | ^^^^^^^^^^^ `DynIncompatible` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-in-return-position-dyn-trait.rs:4:8 | LL | trait DynIncompatible { - | --------------- this trait cannot be made into an object... + | --------------- this trait is not dyn compatible... LL | fn foo() -> Self; | ^^^ ...because associated function `foo` has no `self` parameter - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `DynIncompatible` for this new enum and using it instead: + = help: the following types implement `DynIncompatible`: A B + consider defining an enum where each variant holds one of these types, + implementing `DynIncompatible` for this new enum and using it instead = note: required for the cast from `Box<B>` to `Box<(dyn DynIncompatible + 'static)>` help: consider turning `foo` into a method by giving it a `&self` argument | diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr index 28a0f7461e2..146a3d21068 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.stderr +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr @@ -1,11 +1,11 @@ error[E0407]: method `line_stream` is not a member of trait `X` - --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:5 + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:5 | LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X` error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:22:21 + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21 | LL | type LineStream<'a, Repr> | -- ---- @@ -18,7 +18,7 @@ LL | type LineStream<'c, 'd> = impl Stream; | found 0 type parameters error[E0277]: `()` is not a future - --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:43 + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:43 | LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr new file mode 100644 index 00000000000..3c24eb9adbe --- /dev/null +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr @@ -0,0 +1,29 @@ +error[E0407]: method `line_stream` is not a member of trait `X` + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:5 + | +LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X` + +error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21 + | +LL | type LineStream<'a, Repr> + | -- ---- + | | + | expected 1 type parameter +... +LL | type LineStream<'c, 'd> = impl Stream; + | ^^ ^^ + | | + | found 0 type parameters + +error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()` + --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:43 + | +LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0049, E0271, E0407. +For more information about an error, try `rustc --explain E0049`. diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs index d6fa56663a3..c97bd179943 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver // test for ICE #112823 // Unexpected parameter Type(Repr) when substituting in region @@ -23,8 +26,9 @@ impl X for Y { //~^ ERROR type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>; fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} - //~^ ERROR `()` is not a future - //~^^ method `line_stream` is not a member of trait `X` + //[current]~^ ERROR `()` is not a future + //[next]~^^ ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()` + //~^^^ method `line_stream` is not a member of trait `X` } pub fn main() {} diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.rs b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.rs index daf29a0005d..d6fa34419d2 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.rs +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.rs @@ -14,13 +14,13 @@ impl MyTrait for Outer { } impl dyn MyTrait { - //~^ ERROR the trait `MyTrait` cannot be made into an object + //~^ ERROR the trait `MyTrait` is not dyn compatible fn other(&self) -> impl Marker { - //~^ ERROR the trait `MyTrait` cannot be made into an object + //~^ ERROR the trait `MyTrait` is not dyn compatible MyTrait::foo(&self) //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied - //~| ERROR the trait `MyTrait` cannot be made into an object + //~| ERROR the trait `MyTrait` is not dyn compatible } } diff --git a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr index a975b6204aa..44ca09150fe 100644 --- a/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr +++ b/tests/ui/impl-trait/in-trait/cycle-effective-visibilities-during-dyn-compatibility-check.stderr @@ -8,21 +8,22 @@ LL | MyTrait::foo(&self) | = help: the trait `MyTrait` is implemented for `Outer` -error[E0038]: the trait `MyTrait` cannot be made into an object +error[E0038]: the trait `MyTrait` is not dyn compatible --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:20:9 | LL | MyTrait::foo(&self) - | ^^^^^^^^^^^^ `MyTrait` cannot be made into an object + | ^^^^^^^^^^^^ `MyTrait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { - | ------- this trait cannot be made into an object... + | ------- this trait is not dyn compatible... LL | fn foo(&self) -> impl Marker; | ^^^^^^^^^^^ ...because method `foo` references an `impl Trait` type in its return type = help: consider moving `foo` to another trait - = help: only type `Outer` implements the trait, consider using it directly instead + = help: only type `Outer` implements `MyTrait`; consider using it directly instead. error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:20:9 @@ -32,37 +33,39 @@ LL | MyTrait::foo(&self) | = help: the trait `MyTrait` is implemented for `Outer` -error[E0038]: the trait `MyTrait` cannot be made into an object +error[E0038]: the trait `MyTrait` is not dyn compatible --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:16:6 | LL | impl dyn MyTrait { - | ^^^^^^^^^^^ `MyTrait` cannot be made into an object + | ^^^^^^^^^^^ `MyTrait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { - | ------- this trait cannot be made into an object... + | ------- this trait is not dyn compatible... LL | fn foo(&self) -> impl Marker; | ^^^^^^^^^^^ ...because method `foo` references an `impl Trait` type in its return type = help: consider moving `foo` to another trait - = help: only type `Outer` implements the trait, consider using it directly instead + = help: only type `Outer` implements `MyTrait`; consider using it directly instead. -error[E0038]: the trait `MyTrait` cannot be made into an object +error[E0038]: the trait `MyTrait` is not dyn compatible --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:18:15 | LL | fn other(&self) -> impl Marker { - | ^^^^ `MyTrait` cannot be made into an object + | ^^^^ `MyTrait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/cycle-effective-visibilities-during-dyn-compatibility-check.rs:5:22 | LL | trait MyTrait { - | ------- this trait cannot be made into an object... + | ------- this trait is not dyn compatible... LL | fn foo(&self) -> impl Marker; | ^^^^^^^^^^^ ...because method `foo` references an `impl Trait` type in its return type = help: consider moving `foo` to another trait - = help: only type `Outer` implements the trait, consider using it directly instead + = help: only type `Outer` implements `MyTrait`; consider using it directly instead. error: aborting due to 5 previous errors diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.rs b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs index 5cca4ad839c..85b1ba269fc 100644 --- a/tests/ui/impl-trait/in-trait/dyn-compatibility.rs +++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.rs @@ -12,9 +12,9 @@ impl Foo for u32 { fn main() { let i = Box::new(42_u32) as Box<dyn Foo>; - //~^ ERROR the trait `Foo` cannot be made into an object - //~| ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Foo` is not dyn compatible let s = i.baz(); - //~^ ERROR the trait `Foo` cannot be made into an object - //~| ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr index 115cb014b8c..87a5480b1e3 100644 --- a/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr +++ b/tests/ui/impl-trait/in-trait/dyn-compatibility.stderr @@ -1,66 +1,70 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility.rs:14:33 | LL | let i = Box::new(42_u32) as Box<dyn Foo>; - | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn baz(&self) -> impl Debug; | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type = help: consider moving `baz` to another trait - = help: only type `u32` implements the trait, consider using it directly instead + = help: only type `u32` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility.rs:17:15 | LL | let s = i.baz(); - | ^^^ `Foo` cannot be made into an object + | ^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn baz(&self) -> impl Debug; | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type = help: consider moving `baz` to another trait - = help: only type `u32` implements the trait, consider using it directly instead + = help: only type `u32` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility.rs:17:13 | LL | let s = i.baz(); - | ^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn baz(&self) -> impl Debug; | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type = help: consider moving `baz` to another trait - = help: only type `u32` implements the trait, consider using it directly instead + = help: only type `u32` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dyn-compatibility.rs:14:13 | LL | let i = Box::new(42_u32) as Box<dyn Foo>; - | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-compatibility.rs:4:22 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn baz(&self) -> impl Debug; | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type = help: consider moving `baz` to another trait - = help: only type `u32` implements the trait, consider using it directly instead + = help: only type `u32` implements `Foo`; consider using it directly instead. = note: required for the cast from `Box<u32>` to `Box<dyn Foo>` error: aborting due to 4 previous errors diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs b/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs index 600dba03b74..5b891170a4f 100644 --- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.rs @@ -4,5 +4,5 @@ extern crate rpitit; fn main() { let _: &dyn rpitit::Foo = todo!(); - //~^ ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr index 895d8686742..07d09468b04 100644 --- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr +++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr @@ -1,15 +1,16 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/foreign-dyn-error.rs:6:12 | LL | let _: &dyn rpitit::Foo = todo!(); - | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/auxiliary/rpitit.rs:4:21 | LL | fn bar(self) -> impl Deref<Target = impl Sized>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type - = help: only type `rpitit::Foreign` implements the trait, consider using it directly instead + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait is not dyn compatible because method `bar` references an `impl Trait` type in its return type + = help: only type `rpitit::Foreign` implements `Foo`; consider using it directly instead. error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/issue-102605.stderr b/tests/ui/impl-trait/issue-102605.stderr index dcb22797173..ed6663fa61f 100644 --- a/tests/ui/impl-trait/issue-102605.stderr +++ b/tests/ui/impl-trait/issue-102605.stderr @@ -14,20 +14,11 @@ LL | convert_result(foo()) | | | arguments to this function are incorrect | -note: calling an async function returns a future - --> $DIR/issue-102605.rs:13:20 - | -LL | convert_result(foo()) - | ^^^^^ note: function defined here --> $DIR/issue-102605.rs:7:4 | LL | fn convert_result<T, E>(r: Result<T, E>) -> Option<T> { | ^^^^^^^^^^^^^^ --------------- -help: consider `await`ing on the `Future` - | -LL | convert_result(foo().await) - | ++++++ help: try wrapping the expression in `Err` | LL | convert_result(Err(foo())) diff --git a/tests/ui/impl-trait/issue-72911.stderr b/tests/ui/impl-trait/issue-72911.stderr index 0e86561aa27..063b7f68dc0 100644 --- a/tests/ui/impl-trait/issue-72911.stderr +++ b/tests/ui/impl-trait/issue-72911.stderr @@ -1,14 +1,18 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `foo` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `foo` --> $DIR/issue-72911.rs:11:33 | LL | fn gather_from_file(dir_entry: &foo::MissingItem) -> impl Iterator<Item = Lint> { - | ^^^ use of undeclared crate or module `foo` + | ^^^ use of unresolved module or unlinked crate `foo` + | + = help: you might be missing a crate named `foo` -error[E0433]: failed to resolve: use of undeclared crate or module `foo` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `foo` --> $DIR/issue-72911.rs:16:41 | LL | fn lint_files() -> impl Iterator<Item = foo::MissingItem> { - | ^^^ use of undeclared crate or module `foo` + | ^^^ use of unresolved module or unlinked crate `foo` + | + = help: you might be missing a crate named `foo` error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr deleted file mode 100644 index c511081a86f..00000000000 --- a/tests/ui/impl-trait/multiple-lifetimes/error-handling.polonius.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/error-handling.rs:22:16 - | -LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | let _: &'b i32 = *u.0; - | ^^^^^^^ type annotation requires that `'a` must outlive `'b` - | - = help: consider adding the following bound: `'a: 'b` - -error: aborting due to 1 previous error - diff --git a/tests/ui/impl-trait/stashed-diag-issue-121504.rs b/tests/ui/impl-trait/stashed-diag-issue-121504.rs index 4ac8ffe8931..84686ba4f7d 100644 --- a/tests/ui/impl-trait/stashed-diag-issue-121504.rs +++ b/tests/ui/impl-trait/stashed-diag-issue-121504.rs @@ -4,7 +4,7 @@ trait MyTrait { async fn foo(self) -> (Self, i32); } -impl MyTrait for xyz::T { //~ ERROR failed to resolve: use of undeclared crate or module `xyz` +impl MyTrait for xyz::T { //~ ERROR failed to resolve: use of unresolved module or unlinked crate `xyz` async fn foo(self, key: i32) -> (u32, i32) { (self, key) } diff --git a/tests/ui/impl-trait/stashed-diag-issue-121504.stderr b/tests/ui/impl-trait/stashed-diag-issue-121504.stderr index 6a881dc7f9f..41c6cc42555 100644 --- a/tests/ui/impl-trait/stashed-diag-issue-121504.stderr +++ b/tests/ui/impl-trait/stashed-diag-issue-121504.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `xyz` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `xyz` --> $DIR/stashed-diag-issue-121504.rs:7:18 | LL | impl MyTrait for xyz::T { - | ^^^ use of undeclared crate or module `xyz` + | ^^^ use of unresolved module or unlinked crate `xyz` + | + = help: you might be missing a crate named `xyz` error: aborting due to 1 previous error diff --git a/tests/ui/imports/extern-prelude-extern-crate-fail.rs b/tests/ui/imports/extern-prelude-extern-crate-fail.rs index 2f018851d19..84751ecc02b 100644 --- a/tests/ui/imports/extern-prelude-extern-crate-fail.rs +++ b/tests/ui/imports/extern-prelude-extern-crate-fail.rs @@ -7,7 +7,7 @@ mod n { mod m { fn check() { - two_macros::m!(); //~ ERROR failed to resolve: use of undeclared crate or module `two_macros` + two_macros::m!(); //~ ERROR failed to resolve: use of unresolved module or unlinked crate `two_macros` } } diff --git a/tests/ui/imports/extern-prelude-extern-crate-fail.stderr b/tests/ui/imports/extern-prelude-extern-crate-fail.stderr index f7e37449eeb..ec53730afa0 100644 --- a/tests/ui/imports/extern-prelude-extern-crate-fail.stderr +++ b/tests/ui/imports/extern-prelude-extern-crate-fail.stderr @@ -9,11 +9,11 @@ LL | define_std_as_non_existent!(); | = note: this error originates in the macro `define_std_as_non_existent` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0433]: failed to resolve: use of undeclared crate or module `two_macros` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `two_macros` --> $DIR/extern-prelude-extern-crate-fail.rs:10:9 | LL | two_macros::m!(); - | ^^^^^^^^^^ use of undeclared crate or module `two_macros` + | ^^^^^^^^^^ use of unresolved module or unlinked crate `two_macros` error: aborting due to 2 previous errors diff --git a/tests/ui/imports/glob-use-std.rs b/tests/ui/imports/glob-use-std.rs index b625543da81..d2af816e24f 100644 --- a/tests/ui/imports/glob-use-std.rs +++ b/tests/ui/imports/glob-use-std.rs @@ -2,7 +2,7 @@ //@ run-fail //@ error-pattern:panic works -//@ ignore-emscripten no processes +//@ needs-subprocess use std::*; diff --git a/tests/ui/imports/import-from-missing-star-2.stderr b/tests/ui/imports/import-from-missing-star-2.stderr index dd35627c684..9fe2bdbcfa2 100644 --- a/tests/ui/imports/import-from-missing-star-2.stderr +++ b/tests/ui/imports/import-from-missing-star-2.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-2.rs:2:9 | LL | use spam::*; - | ^^^^ you might be missing crate `spam` + | ^^^^ use of unresolved module or unlinked crate `spam` | -help: consider importing the `spam` crate +help: you might be missing a crate named `spam`, add it to your project and import it in your code | LL + extern crate spam; | diff --git a/tests/ui/imports/import-from-missing-star-3.stderr b/tests/ui/imports/import-from-missing-star-3.stderr index 1e2412b0959..c0b2e5675d3 100644 --- a/tests/ui/imports/import-from-missing-star-3.stderr +++ b/tests/ui/imports/import-from-missing-star-3.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-3.rs:2:9 | LL | use spam::*; - | ^^^^ you might be missing crate `spam` + | ^^^^ use of unresolved module or unlinked crate `spam` | -help: consider importing the `spam` crate +help: you might be missing a crate named `spam`, add it to your project and import it in your code | LL + extern crate spam; | @@ -13,9 +13,9 @@ error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star-3.rs:27:13 | LL | use spam::*; - | ^^^^ you might be missing crate `spam` + | ^^^^ use of unresolved module or unlinked crate `spam` | -help: consider importing the `spam` crate +help: you might be missing a crate named `spam`, add it to your project and import it in your code | LL + extern crate spam; | diff --git a/tests/ui/imports/import-from-missing-star.stderr b/tests/ui/imports/import-from-missing-star.stderr index c9bb9baeb4d..768e1ea1e2c 100644 --- a/tests/ui/imports/import-from-missing-star.stderr +++ b/tests/ui/imports/import-from-missing-star.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `spam` --> $DIR/import-from-missing-star.rs:1:5 | LL | use spam::*; - | ^^^^ you might be missing crate `spam` + | ^^^^ use of unresolved module or unlinked crate `spam` | -help: consider importing the `spam` crate +help: you might be missing a crate named `spam`, add it to your project and import it in your code | LL + extern crate spam; | diff --git a/tests/ui/imports/import3.stderr b/tests/ui/imports/import3.stderr index 157b5b63566..7f581146781 100644 --- a/tests/ui/imports/import3.stderr +++ b/tests/ui/imports/import3.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `main` --> $DIR/import3.rs:2:5 | LL | use main::bar; - | ^^^^ you might be missing crate `main` + | ^^^^ use of unresolved module or unlinked crate `main` | -help: consider importing the `main` crate +help: you might be missing a crate named `main`, add it to your project and import it in your code | LL + extern crate main; | diff --git a/tests/ui/imports/issue-109343.stderr b/tests/ui/imports/issue-109343.stderr index e66528e8df5..e1071e45b92 100644 --- a/tests/ui/imports/issue-109343.stderr +++ b/tests/ui/imports/issue-109343.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `unresolved` --> $DIR/issue-109343.rs:4:9 | LL | pub use unresolved::f; - | ^^^^^^^^^^ you might be missing crate `unresolved` + | ^^^^^^^^^^ use of unresolved module or unlinked crate `unresolved` | -help: consider importing the `unresolved` crate +help: you might be missing a crate named `unresolved`, add it to your project and import it in your code | LL + extern crate unresolved; | diff --git a/tests/ui/imports/issue-1697.rs b/tests/ui/imports/issue-1697.rs index 019237611df..3d3d4a17d6c 100644 --- a/tests/ui/imports/issue-1697.rs +++ b/tests/ui/imports/issue-1697.rs @@ -2,7 +2,7 @@ use unresolved::*; //~^ ERROR unresolved import `unresolved` [E0432] -//~| NOTE you might be missing crate `unresolved` -//~| HELP consider importing the `unresolved` crate +//~| NOTE use of unresolved module or unlinked crate `unresolved` +//~| HELP you might be missing a crate named `unresolved` fn main() {} diff --git a/tests/ui/imports/issue-1697.stderr b/tests/ui/imports/issue-1697.stderr index ec0d94bd672..96e371c64f9 100644 --- a/tests/ui/imports/issue-1697.stderr +++ b/tests/ui/imports/issue-1697.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `unresolved` --> $DIR/issue-1697.rs:3:5 | LL | use unresolved::*; - | ^^^^^^^^^^ you might be missing crate `unresolved` + | ^^^^^^^^^^ use of unresolved module or unlinked crate `unresolved` | -help: consider importing the `unresolved` crate +help: you might be missing a crate named `unresolved`, add it to your project and import it in your code | LL + extern crate unresolved; | diff --git a/tests/ui/imports/issue-33464.stderr b/tests/ui/imports/issue-33464.stderr index 28fbcee401f..dba45184675 100644 --- a/tests/ui/imports/issue-33464.stderr +++ b/tests/ui/imports/issue-33464.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `abc` --> $DIR/issue-33464.rs:3:5 | LL | use abc::one_el; - | ^^^ you might be missing crate `abc` + | ^^^ use of unresolved module or unlinked crate `abc` | -help: consider importing the `abc` crate +help: you might be missing a crate named `abc`, add it to your project and import it in your code | LL + extern crate abc; | @@ -13,9 +13,9 @@ error[E0432]: unresolved import `abc` --> $DIR/issue-33464.rs:5:5 | LL | use abc::{a, bbb, cccccc}; - | ^^^ you might be missing crate `abc` + | ^^^ use of unresolved module or unlinked crate `abc` | -help: consider importing the `abc` crate +help: you might be missing a crate named `abc`, add it to your project and import it in your code | LL + extern crate abc; | @@ -24,9 +24,9 @@ error[E0432]: unresolved import `a_very_long_name` --> $DIR/issue-33464.rs:7:5 | LL | use a_very_long_name::{el, el2}; - | ^^^^^^^^^^^^^^^^ you might be missing crate `a_very_long_name` + | ^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `a_very_long_name` | -help: consider importing the `a_very_long_name` crate +help: you might be missing a crate named `a_very_long_name`, add it to your project and import it in your code | LL + extern crate a_very_long_name; | diff --git a/tests/ui/imports/issue-36881.stderr b/tests/ui/imports/issue-36881.stderr index 004836e072c..33d628f40da 100644 --- a/tests/ui/imports/issue-36881.stderr +++ b/tests/ui/imports/issue-36881.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `issue_36881_aux` --> $DIR/issue-36881.rs:5:9 | LL | use issue_36881_aux::Foo; - | ^^^^^^^^^^^^^^^ you might be missing crate `issue_36881_aux` + | ^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `issue_36881_aux` | -help: consider importing the `issue_36881_aux` crate +help: you might be missing a crate named `issue_36881_aux`, add it to your project and import it in your code | LL + extern crate issue_36881_aux; | diff --git a/tests/ui/imports/issue-37887.stderr b/tests/ui/imports/issue-37887.stderr index cc191a17c29..b83ba273a01 100644 --- a/tests/ui/imports/issue-37887.stderr +++ b/tests/ui/imports/issue-37887.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `test` --> $DIR/issue-37887.rs:3:9 | LL | use test::*; - | ^^^^ you might be missing crate `test` + | ^^^^ use of unresolved module or unlinked crate `test` | -help: consider importing the `test` crate +help: you might be missing a crate named `test`, add it to your project and import it in your code | LL + extern crate test; | diff --git a/tests/ui/imports/issue-53269.stderr b/tests/ui/imports/issue-53269.stderr index d25d85bf46f..c12fc0f378e 100644 --- a/tests/ui/imports/issue-53269.stderr +++ b/tests/ui/imports/issue-53269.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `nonexistent_module` --> $DIR/issue-53269.rs:6:9 | LL | use nonexistent_module::mac; - | ^^^^^^^^^^^^^^^^^^ you might be missing crate `nonexistent_module` + | ^^^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `nonexistent_module` | -help: consider importing the `nonexistent_module` crate +help: you might be missing a crate named `nonexistent_module`, add it to your project and import it in your code | LL + extern crate nonexistent_module; | diff --git a/tests/ui/imports/issue-55457.stderr b/tests/ui/imports/issue-55457.stderr index 9c99b6a20de..472e46caf31 100644 --- a/tests/ui/imports/issue-55457.stderr +++ b/tests/ui/imports/issue-55457.stderr @@ -11,9 +11,9 @@ error[E0432]: unresolved import `non_existent` --> $DIR/issue-55457.rs:2:5 | LL | use non_existent::non_existent; - | ^^^^^^^^^^^^ you might be missing crate `non_existent` + | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `non_existent` | -help: consider importing the `non_existent` crate +help: you might be missing a crate named `non_existent`, add it to your project and import it in your code | LL + extern crate non_existent; | diff --git a/tests/ui/imports/issue-81413.stderr b/tests/ui/imports/issue-81413.stderr index aa1246c1d2f..257aca4455c 100644 --- a/tests/ui/imports/issue-81413.stderr +++ b/tests/ui/imports/issue-81413.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `doesnt_exist` --> $DIR/issue-81413.rs:7:9 | LL | pub use doesnt_exist::*; - | ^^^^^^^^^^^^ you might be missing crate `doesnt_exist` + | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `doesnt_exist` | -help: consider importing the `doesnt_exist` crate +help: you might be missing a crate named `doesnt_exist`, add it to your project and import it in your code | LL + extern crate doesnt_exist; | diff --git a/tests/ui/imports/tool-mod-child.rs b/tests/ui/imports/tool-mod-child.rs index a8249ab01df..38bcdfb0249 100644 --- a/tests/ui/imports/tool-mod-child.rs +++ b/tests/ui/imports/tool-mod-child.rs @@ -1,7 +1,7 @@ use clippy::a; //~ ERROR unresolved import `clippy` -use clippy::a::b; //~ ERROR failed to resolve: you might be missing crate `clippy` +use clippy::a::b; //~ ERROR failed to resolve: use of unresolved module or unlinked crate `clippy` use rustdoc::a; //~ ERROR unresolved import `rustdoc` -use rustdoc::a::b; //~ ERROR failed to resolve: you might be missing crate `rustdoc` +use rustdoc::a::b; //~ ERROR failed to resolve: use of unresolved module or unlinked crate `rustdoc` fn main() {} diff --git a/tests/ui/imports/tool-mod-child.stderr b/tests/ui/imports/tool-mod-child.stderr index ec110ccd75d..b0e446fcbf6 100644 --- a/tests/ui/imports/tool-mod-child.stderr +++ b/tests/ui/imports/tool-mod-child.stderr @@ -1,10 +1,10 @@ -error[E0433]: failed to resolve: you might be missing crate `clippy` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `clippy` --> $DIR/tool-mod-child.rs:2:5 | LL | use clippy::a::b; - | ^^^^^^ you might be missing crate `clippy` + | ^^^^^^ use of unresolved module or unlinked crate `clippy` | -help: consider importing the `clippy` crate +help: you might be missing a crate named `clippy`, add it to your project and import it in your code | LL + extern crate clippy; | @@ -13,20 +13,20 @@ error[E0432]: unresolved import `clippy` --> $DIR/tool-mod-child.rs:1:5 | LL | use clippy::a; - | ^^^^^^ you might be missing crate `clippy` + | ^^^^^^ use of unresolved module or unlinked crate `clippy` | -help: consider importing the `clippy` crate +help: you might be missing a crate named `clippy`, add it to your project and import it in your code | LL + extern crate clippy; | -error[E0433]: failed to resolve: you might be missing crate `rustdoc` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `rustdoc` --> $DIR/tool-mod-child.rs:5:5 | LL | use rustdoc::a::b; - | ^^^^^^^ you might be missing crate `rustdoc` + | ^^^^^^^ use of unresolved module or unlinked crate `rustdoc` | -help: consider importing the `rustdoc` crate +help: you might be missing a crate named `rustdoc`, add it to your project and import it in your code | LL + extern crate rustdoc; | @@ -35,9 +35,9 @@ error[E0432]: unresolved import `rustdoc` --> $DIR/tool-mod-child.rs:4:5 | LL | use rustdoc::a; - | ^^^^^^^ you might be missing crate `rustdoc` + | ^^^^^^^ use of unresolved module or unlinked crate `rustdoc` | -help: consider importing the `rustdoc` crate +help: you might be missing a crate named `rustdoc`, add it to your project and import it in your code | LL + extern crate rustdoc; | diff --git a/tests/ui/imports/unresolved-imports-used.stderr b/tests/ui/imports/unresolved-imports-used.stderr index 4bf02ff6e3a..d39d2685217 100644 --- a/tests/ui/imports/unresolved-imports-used.stderr +++ b/tests/ui/imports/unresolved-imports-used.stderr @@ -14,9 +14,9 @@ error[E0432]: unresolved import `foo` --> $DIR/unresolved-imports-used.rs:11:5 | LL | use foo::bar; - | ^^^ you might be missing crate `foo` + | ^^^ use of unresolved module or unlinked crate `foo` | -help: consider importing the `foo` crate +help: you might be missing a crate named `foo`, add it to your project and import it in your code | LL + extern crate foo; | @@ -25,9 +25,9 @@ error[E0432]: unresolved import `baz` --> $DIR/unresolved-imports-used.rs:12:5 | LL | use baz::*; - | ^^^ you might be missing crate `baz` + | ^^^ use of unresolved module or unlinked crate `baz` | -help: consider importing the `baz` crate +help: you might be missing a crate named `baz`, add it to your project and import it in your code | LL + extern crate baz; | @@ -36,9 +36,9 @@ error[E0432]: unresolved import `foo2` --> $DIR/unresolved-imports-used.rs:14:5 | LL | use foo2::bar2; - | ^^^^ you might be missing crate `foo2` + | ^^^^ use of unresolved module or unlinked crate `foo2` | -help: consider importing the `foo2` crate +help: you might be missing a crate named `foo2`, add it to your project and import it in your code | LL + extern crate foo2; | @@ -47,9 +47,9 @@ error[E0432]: unresolved import `baz2` --> $DIR/unresolved-imports-used.rs:15:5 | LL | use baz2::*; - | ^^^^ you might be missing crate `baz2` + | ^^^^ use of unresolved module or unlinked crate `baz2` | -help: consider importing the `baz2` crate +help: you might be missing a crate named `baz2`, add it to your project and import it in your code | LL + extern crate baz2; | diff --git a/tests/ui/inference/issue-72616.stderr b/tests/ui/inference/issue-72616.stderr index 02c92c1c11d..a26f9a1ff56 100644 --- a/tests/ui/inference/issue-72616.stderr +++ b/tests/ui/inference/issue-72616.stderr @@ -6,11 +6,14 @@ LL | if String::from("a") == "a".try_into().unwrap() {} | | | type must be known at this point | - = note: multiple `impl`s satisfying `String: PartialEq<_>` found in the `alloc` crate: - - impl PartialEq for String; - - impl<'a, 'b> PartialEq<&'a str> for String; - - impl<'a, 'b> PartialEq<Cow<'a, str>> for String; - - impl<'a, 'b> PartialEq<str> for String; + = note: cannot satisfy `String: PartialEq<_>` + = help: the following types implement trait `PartialEq<Rhs>`: + `String` implements `PartialEq<&str>` + `String` implements `PartialEq<ByteStr>` + `String` implements `PartialEq<ByteString>` + `String` implements `PartialEq<Cow<'_, str>>` + `String` implements `PartialEq<str>` + `String` implements `PartialEq` help: try using a fully qualified path to specify the expected types | LL | if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {} diff --git a/tests/ui/inference/issue-72690.stderr b/tests/ui/inference/issue-72690.stderr index 6391672f861..2d09f667ae2 100644 --- a/tests/ui/inference/issue-72690.stderr +++ b/tests/ui/inference/issue-72690.stderr @@ -15,6 +15,7 @@ LL | String::from("x".as_ref()); | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; @@ -41,6 +42,7 @@ LL | |x| String::from("x".as_ref()); | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; @@ -57,6 +59,7 @@ LL | let _ = "x".as_ref(); | ^ ------ type must be known at this point | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; @@ -83,6 +86,7 @@ LL | String::from("x".as_ref()); | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; @@ -109,6 +113,7 @@ LL | String::from("x".as_ref()); | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; @@ -135,6 +140,7 @@ LL | String::from("x".as_ref()); | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; @@ -161,6 +167,7 @@ LL | String::from("x".as_ref()); | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; @@ -187,6 +194,7 @@ LL | String::from("x".as_ref()); | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; @@ -213,6 +221,7 @@ LL | String::from("x".as_ref()); | ^^^^^^ | = note: multiple `impl`s satisfying `str: AsRef<_>` found in the following crates: `core`, `std`: + - impl AsRef<ByteStr> for str; - impl AsRef<OsStr> for str; - impl AsRef<Path> for str; - impl AsRef<[u8]> for str; diff --git a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs index 410862c5326..e28b8f373da 100644 --- a/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs +++ b/tests/ui/infinite/infinite-instantiation-struct-tail-ice-114484.rs @@ -24,7 +24,7 @@ impl<T, const L: u8> VirtualWrapper<T, L> { impl<T: MyTrait + 'static, const L: u8> MyTrait for VirtualWrapper<T, L> { fn virtualize(&self) -> &dyn MyTrait { unsafe { virtualize_my_trait(L, self) } - // unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem + // unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem } } diff --git a/tests/ui/infinite/infinite-instantiation.polonius.stderr b/tests/ui/infinite/infinite-instantiation.polonius.stderr deleted file mode 100644 index f048c942f1a..00000000000 --- a/tests/ui/infinite/infinite-instantiation.polonius.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: reached the recursion limit while instantiating `function::<Option<Option<Option<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/infinite-instantiation.rs:22:9 - | -LL | function(counter - 1, t.to_option()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: `function` defined here - --> $DIR/infinite-instantiation.rs:20:1 - | -LL | fn function<T:ToOpt + Clone>(counter: usize, t: T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the full type name has been written to '$TEST_BUILD_DIR/infinite/infinite-instantiation.polonius/infinite-instantiation.long-type.txt' - -error: aborting due to 1 previous error - diff --git a/tests/ui/intrinsics/panic-uninitialized-zeroed.rs b/tests/ui/intrinsics/panic-uninitialized-zeroed.rs index 67b9832d601..346a94c37dd 100644 --- a/tests/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/tests/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -1,11 +1,10 @@ +// ignore-tidy-linelength +//! This test checks panic emitted from `mem::{uninitialized,zeroed}`. //@ run-pass //@ revisions: default strict //@ [strict]compile-flags: -Zstrict-init-checks -// ignore-tidy-linelength -//@ ignore-wasm32 spawning processes is not supported -//@ ignore-sgx no processes -// -// This test checks panic emitted from `mem::{uninitialized,zeroed}`. +//@ needs-subprocess + #![allow(deprecated, invalid_value)] #![feature(never_type)] diff --git a/tests/ui/intrinsics/reify-intrinsic.rs b/tests/ui/intrinsics/reify-intrinsic.rs index 0d047ccf4a3..5b2324235c1 100644 --- a/tests/ui/intrinsics/reify-intrinsic.rs +++ b/tests/ui/intrinsics/reify-intrinsic.rs @@ -3,17 +3,17 @@ #![feature(core_intrinsics, intrinsics)] fn a() { - let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; + let _: unsafe fn(isize) -> usize = std::mem::transmute; //~^ ERROR cannot coerce } fn b() { - let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; + let _ = std::mem::transmute as unsafe fn(isize) -> usize; //~^ ERROR casting } fn c() { - let _: [unsafe extern "rust-intrinsic" fn(f32) -> f32; 2] = [ + let _: [unsafe fn(f32) -> f32; 2] = [ std::intrinsics::floorf32, //~ ERROR cannot coerce std::intrinsics::log2f32, ]; diff --git a/tests/ui/intrinsics/reify-intrinsic.stderr b/tests/ui/intrinsics/reify-intrinsic.stderr index aea6d263a72..aea6f838e0d 100644 --- a/tests/ui/intrinsics/reify-intrinsic.stderr +++ b/tests/ui/intrinsics/reify-intrinsic.stderr @@ -1,19 +1,19 @@ error[E0308]: cannot coerce intrinsics to function pointers - --> $DIR/reify-intrinsic.rs:6:64 + --> $DIR/reify-intrinsic.rs:6:40 | -LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute; - | ------------------------------------------------- ^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers +LL | let _: unsafe fn(isize) -> usize = std::mem::transmute; + | ------------------------- ^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | | | expected due to this | - = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize` + = note: expected fn pointer `unsafe fn(isize) -> usize` found fn item `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` -error[E0606]: casting `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid +error[E0606]: casting `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe fn(isize) -> usize` is invalid --> $DIR/reify-intrinsic.rs:11:13 | -LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let _ = std::mem::transmute as unsafe fn(isize) -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0308]: cannot coerce intrinsics to function pointers --> $DIR/reify-intrinsic.rs:17:9 @@ -21,7 +21,7 @@ error[E0308]: cannot coerce intrinsics to function pointers LL | std::intrinsics::floorf32, | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | - = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _` + = note: expected fn pointer `unsafe fn(_) -> _` found fn item `unsafe fn(_) -> _ {floorf32}` error: aborting due to 3 previous errors diff --git a/tests/ui/issues/auxiliary/issue-111011.stderr b/tests/ui/issues/auxiliary/issue-111011.stderr deleted file mode 100644 index c0b48c5842f..00000000000 --- a/tests/ui/issues/auxiliary/issue-111011.stderr +++ /dev/null @@ -1,34 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-111011.rs:10:23 - | -LL | foo(async move || {}); - | ^^ expected `Box<_>`, found `async` closure body - | - = note: expected struct `Box<_>` - found `async` closure body `[async closure body@$DIR/issue-111011.rs:10:23: 10:25]` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html - -error[E0308]: mismatched types - --> $DIR/issue-111011.rs:11:9 - | -LL | bar(async move || {}); - | --- ^^^^^^^^^^^^^^^^ expected `Box<dyn FnOnce() -> _>`, found closure - | | - | arguments to this function are incorrect - | - = note: expected struct `Box<(dyn FnOnce() -> _ + 'static)>` - found closure `{closure@$DIR/issue-111011.rs:11:9: 11:22}` - = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html -note: function defined here - --> $DIR/issue-111011.rs:7:4 - | -LL | fn bar<X>(x: Box<dyn FnOnce() -> X>) {} - | ^^^ ------------------------- -help: store this in the heap by calling `Box::new` - | -LL | bar(Box::new(async move || {})); - | +++++++++ + - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/issues/issue-12920.rs b/tests/ui/issues/issue-12920.rs index 7f453e499d4..f3b1b643c45 100644 --- a/tests/ui/issues/issue-12920.rs +++ b/tests/ui/issues/issue-12920.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess pub fn main() { panic!(); diff --git a/tests/ui/issues/issue-13202.rs b/tests/ui/issues/issue-13202.rs index 89205fc7fd1..99ffba3fba5 100644 --- a/tests/ui/issues/issue-13202.rs +++ b/tests/ui/issues/issue-13202.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:bad input -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { Some("foo").unwrap_or(panic!("bad input")).to_string(); diff --git a/tests/ui/issues/issue-18959.stderr b/tests/ui/issues/issue-18959.stderr index 5bb452250aa..49d501c397f 100644 --- a/tests/ui/issues/issue-18959.stderr +++ b/tests/ui/issues/issue-18959.stderr @@ -1,77 +1,82 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/issue-18959.rs:11:12 | LL | fn foo(b: &dyn Bar) { - | ^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-18959.rs:1:20 | LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); } | ^^^ ...because method `foo` has generic type parameters LL | pub trait Bar: Foo { } - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/issue-18959.rs:13:5 | LL | b.foo(&0) - | ^^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-18959.rs:1:20 | LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); } | ^^^ ...because method `foo` has generic type parameters LL | pub trait Bar: Foo { } - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/issue-18959.rs:19:15 | LL | let test: &dyn Bar = &mut thing; - | ^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-18959.rs:1:20 | LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); } | ^^^ ...because method `foo` has generic type parameters LL | pub trait Bar: Foo { } - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/issue-18959.rs:19:26 | LL | let test: &dyn Bar = &mut thing; - | ^^^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-18959.rs:1:20 | LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); } | ^^^ ...because method `foo` has generic type parameters LL | pub trait Bar: Foo { } - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait = note: required for the cast from `&mut Thing` to `&dyn Bar` -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/issue-18959.rs:22:9 | LL | foo(test); - | ^^^^ `Bar` cannot be made into an object + | ^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-18959.rs:1:20 | LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); } | ^^^ ...because method `foo` has generic type parameters LL | pub trait Bar: Foo { } - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... = help: consider moving `foo` to another trait error: aborting due to 5 previous errors diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/issues/issue-19380.stderr index afbe67befa1..7d4812c3693 100644 --- a/tests/ui/issues/issue-19380.stderr +++ b/tests/ui/issues/issue-19380.stderr @@ -1,17 +1,18 @@ -error[E0038]: the trait `Qiz` cannot be made into an object +error[E0038]: the trait `Qiz` is not dyn compatible --> $DIR/issue-19380.rs:11:29 | LL | foos: &'static [&'static (dyn Qiz + 'static)] - | ^^^^^^^^^^^^^^^^^ `Qiz` cannot be made into an object + | ^^^^^^^^^^^^^^^^^ `Qiz` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-19380.rs:2:6 | LL | trait Qiz { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn qiz(); | ^^^ ...because associated function `qiz` has no `self` parameter - = help: only type `Foo` implements the trait, consider using it directly instead + = help: only type `Foo` implements `Qiz`; consider using it directly instead. help: consider turning `qiz` into a method by giving it a `&self` argument | LL | fn qiz(&self); @@ -21,20 +22,21 @@ help: alternatively, consider constraining `qiz` so it does not apply to trait o LL | fn qiz() where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Qiz` cannot be made into an object +error[E0038]: the trait `Qiz` is not dyn compatible --> $DIR/issue-19380.rs:16:33 | LL | const BAR : Bar = Bar { foos: &[&FOO]}; - | ^^^^ `Qiz` cannot be made into an object + | ^^^^ `Qiz` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-19380.rs:2:6 | LL | trait Qiz { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn qiz(); | ^^^ ...because associated function `qiz` has no `self` parameter - = help: only type `Foo` implements the trait, consider using it directly instead + = help: only type `Foo` implements `Qiz`; consider using it directly instead. = note: required for the cast from `&Foo` to `&'static (dyn Qiz + 'static)` help: consider turning `qiz` into a method by giving it a `&self` argument | @@ -45,20 +47,21 @@ help: alternatively, consider constraining `qiz` so it does not apply to trait o LL | fn qiz() where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Qiz` cannot be made into an object +error[E0038]: the trait `Qiz` is not dyn compatible --> $DIR/issue-19380.rs:16:31 | LL | const BAR : Bar = Bar { foos: &[&FOO]}; - | ^^^^^^^ `Qiz` cannot be made into an object + | ^^^^^^^ `Qiz` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-19380.rs:2:6 | LL | trait Qiz { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn qiz(); | ^^^ ...because associated function `qiz` has no `self` parameter - = help: only type `Foo` implements the trait, consider using it directly instead + = help: only type `Foo` implements `Qiz`; consider using it directly instead. help: consider turning `qiz` into a method by giving it a `&self` argument | LL | fn qiz(&self); diff --git a/tests/ui/issues/issue-20971.rs b/tests/ui/issues/issue-20971.rs index 377a3d9ea30..31dd9101919 100644 --- a/tests/ui/issues/issue-20971.rs +++ b/tests/ui/issues/issue-20971.rs @@ -2,7 +2,7 @@ //@ run-fail //@ error-pattern:Hello, world! -//@ ignore-emscripten no processes +//@ needs-subprocess pub trait Parser { type Input; diff --git a/tests/ui/issues/issue-2190-1.rs b/tests/ui/issues/issue-2190-1.rs index 8db4a84aac8..e4e4bf9dbbe 100644 --- a/tests/ui/issues/issue-2190-1.rs +++ b/tests/ui/issues/issue-2190-1.rs @@ -1,20 +1,16 @@ -//@ run-pass -#![allow(unused_must_use)] -#![allow(non_upper_case_globals)] - -//@ ignore-emscripten no threads +//@ check-pass use std::thread::Builder; -static generations: usize = 1024+256+128+49; +static GENERATIONS: usize = 1024+256+128+49; fn spawn(mut f: Box<dyn FnMut() + 'static + Send>) { - Builder::new().stack_size(32 * 1024).spawn(move|| f()); + Builder::new().stack_size(32 * 1024).spawn(move || f()); } fn child_no(x: usize) -> Box<dyn FnMut() + 'static + Send> { - Box::new(move|| { - if x < generations { + Box::new(move || { + if x < GENERATIONS { spawn(child_no(x+1)); } }) diff --git a/tests/ui/issues/issue-22370.stderr b/tests/ui/issues/issue-22370.stderr index 3dc060963f9..b02d867eb7d 100644 --- a/tests/ui/issues/issue-22370.stderr +++ b/tests/ui/issues/issue-22370.stderr @@ -7,7 +7,7 @@ LL | LL | fn f(a: &dyn A) {} | ^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn f(a: &dyn A<T>) {} diff --git a/tests/ui/issues/issue-22638.polonius.stderr b/tests/ui/issues/issue-22638.polonius.stderr deleted file mode 100644 index 3a94ed7bd3d..00000000000 --- a/tests/ui/issues/issue-22638.polonius.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: reached the recursion limit while instantiating `A::matches::$CLOSURE` - --> $DIR/issue-22638.rs:56:9 - | -LL | a.matches(f) - | ^^^^^^^^^^^^ - | -note: `A::matches` defined here - --> $DIR/issue-22638.rs:15:5 - | -LL | pub fn matches<F: Fn()>(&self, f: &F) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-22638.polonius/issue-22638.long-type.txt' - -error: aborting due to 1 previous error - diff --git a/tests/ui/issues/issue-23354-2.rs b/tests/ui/issues/issue-23354-2.rs index 90de1276cc6..a296477215e 100644 --- a/tests/ui/issues/issue-23354-2.rs +++ b/tests/ui/issues/issue-23354-2.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:panic evaluated -//@ ignore-emscripten no processes +//@ needs-subprocess #[allow(unused_variables)] fn main() { diff --git a/tests/ui/issues/issue-23354.rs b/tests/ui/issues/issue-23354.rs index 31783842dac..eff5f3d2714 100644 --- a/tests/ui/issues/issue-23354.rs +++ b/tests/ui/issues/issue-23354.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:panic evaluated -//@ ignore-emscripten no processes +//@ needs-subprocess #[allow(unused_variables)] fn main() { diff --git a/tests/ui/issues/issue-2470-bounds-check-overflow.rs b/tests/ui/issues/issue-2470-bounds-check-overflow.rs index 241bc8fda9c..4f300454dcb 100644 --- a/tests/ui/issues/issue-2470-bounds-check-overflow.rs +++ b/tests/ui/issues/issue-2470-bounds-check-overflow.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:index out of bounds -//@ ignore-emscripten no processes +//@ needs-subprocess use std::mem; diff --git a/tests/ui/issues/issue-25089.rs b/tests/ui/issues/issue-25089.rs index ea9ab290904..929738c3e79 100644 --- a/tests/ui/issues/issue-25089.rs +++ b/tests/ui/issues/issue-25089.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/issues/issue-26056.stderr b/tests/ui/issues/issue-26056.stderr index be5453ec19d..d1cdf43351e 100644 --- a/tests/ui/issues/issue-26056.stderr +++ b/tests/ui/issues/issue-26056.stderr @@ -1,16 +1,17 @@ -error[E0038]: the trait `Map` cannot be made into an object - --> $DIR/issue-26056.rs:20:13 +error[E0038]: the trait `Map` is not dyn compatible + --> $DIR/issue-26056.rs:20:17 | LL | as &dyn Map<Key=u32,MapValue=u32>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Map` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Map` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-26056.rs:9:12 | LL | trait Map: MapLookup<<Self as Map>::Key> { | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-26655.rs b/tests/ui/issues/issue-26655.rs index 7f1858fdb7d..416472b0b26 100644 --- a/tests/ui/issues/issue-26655.rs +++ b/tests/ui/issues/issue-26655.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads // Check that the destructors of simple enums are run on unwinding diff --git a/tests/ui/issues/issue-2761.rs b/tests/ui/issues/issue-2761.rs index b44a24e09f2..6df7a5118b8 100644 --- a/tests/ui/issues/issue-2761.rs +++ b/tests/ui/issues/issue-2761.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:custom message -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert!(false, "custom message"); diff --git a/tests/ui/issues/issue-29485.rs b/tests/ui/issues/issue-29485.rs index 56865d0e5db..a44bcd49c6a 100644 --- a/tests/ui/issues/issue-29485.rs +++ b/tests/ui/issues/issue-29485.rs @@ -2,7 +2,7 @@ #![allow(unused_attributes)] //@ aux-build:issue-29485.rs //@ needs-unwind -//@ ignore-emscripten no threads +//@ needs-threads #[feature(recover)] diff --git a/tests/ui/issues/issue-30018-panic.rs b/tests/ui/issues/issue-30018-panic.rs index f5482d7c741..591848b6f7b 100644 --- a/tests/ui/issues/issue-30018-panic.rs +++ b/tests/ui/issues/issue-30018-panic.rs @@ -5,7 +5,7 @@ // SIGTRAP injected by the drop-flag consistency checking. //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads struct Foo; diff --git a/tests/ui/issues/issue-3029.rs b/tests/ui/issues/issue-3029.rs index a070578969c..22d0906ccf7 100644 --- a/tests/ui/issues/issue-3029.rs +++ b/tests/ui/issues/issue-3029.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:so long -//@ ignore-emscripten no processes +//@ needs-subprocess #![allow(unreachable_code)] diff --git a/tests/ui/issues/issue-30380.rs b/tests/ui/issues/issue-30380.rs index 534bb3423d0..49fce3d150c 100644 --- a/tests/ui/issues/issue-30380.rs +++ b/tests/ui/issues/issue-30380.rs @@ -3,7 +3,7 @@ //@ run-fail //@ error-pattern:panicking destructors ftw! -//@ ignore-emscripten no processes +//@ needs-subprocess struct Observer<'a>(&'a mut FilledOnDrop); diff --git a/tests/ui/issues/issue-33293.rs b/tests/ui/issues/issue-33293.rs index a6ef007d51f..115ae3aad20 100644 --- a/tests/ui/issues/issue-33293.rs +++ b/tests/ui/issues/issue-33293.rs @@ -1,6 +1,6 @@ fn main() { match 0 { aaa::bbb(_) => () - //~^ ERROR failed to resolve: use of undeclared crate or module `aaa` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `aaa` }; } diff --git a/tests/ui/issues/issue-33293.stderr b/tests/ui/issues/issue-33293.stderr index 5badaa153f2..a82813194d7 100644 --- a/tests/ui/issues/issue-33293.stderr +++ b/tests/ui/issues/issue-33293.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `aaa` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `aaa` --> $DIR/issue-33293.rs:3:9 | LL | aaa::bbb(_) => () - | ^^^ use of undeclared crate or module `aaa` + | ^^^ use of unresolved module or unlinked crate `aaa` + | + = help: you might be missing a crate named `aaa` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-33770.rs b/tests/ui/issues/issue-33770.rs index 0fa91ac91c4..814e8f37176 100644 --- a/tests/ui/issues/issue-33770.rs +++ b/tests/ui/issues/issue-33770.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::process::{Command, Stdio}; use std::env; diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.current.stderr index 9535ea57430..d653bbd3274 100644 --- a/tests/ui/issues/issue-33941.stderr +++ b/tests/ui/issues/issue-33941.current.stderr @@ -1,5 +1,5 @@ error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:6:36 + --> $DIR/issue-33941.rs:9:36 | LL | for _ in HashMap::new().iter().cloned() {} | ^^^^^^ expected `&_`, found `(&_, &_)` @@ -7,7 +7,7 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: expected reference `&_` found tuple `(&_, &_)` note: the method call chain might not have had the expected associated types - --> $DIR/issue-33941.rs:6:29 + --> $DIR/issue-33941.rs:9:29 | LL | for _ in HashMap::new().iter().cloned() {} | -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here @@ -17,7 +17,7 @@ note: required by a bound in `cloned` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:6:14 + --> $DIR/issue-33941.rs:9:14 | LL | for _ in HashMap::new().iter().cloned() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&_`, found `(&_, &_)` diff --git a/tests/ui/issues/issue-33941.next.stderr b/tests/ui/issues/issue-33941.next.stderr new file mode 100644 index 00000000000..a5a6e51545a --- /dev/null +++ b/tests/ui/issues/issue-33941.next.stderr @@ -0,0 +1,25 @@ +error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + --> $DIR/issue-33941.rs:9:36 + | +LL | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^ expected `&_`, found `(&_, &_)` + | + = note: expected reference `&_` + found tuple `(&_, &_)` +note: required by a bound in `cloned` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + --> $DIR/issue-33941.rs:9:14 + | +LL | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&_`, found `(&_, &_)` + | + = note: expected reference `&_` + found tuple `(&_, &_)` + = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator` + = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/issues/issue-33941.rs index 7b5be30834b..b0736204a08 100644 --- a/tests/ui/issues/issue-33941.rs +++ b/tests/ui/issues/issue-33941.rs @@ -1,8 +1,12 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ compile-flags: -Zdeduplicate-diagnostics=yes use std::collections::HashMap; fn main() { - for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + for _ in HashMap::new().iter().cloned() {} //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` + //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` } diff --git a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr b/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr deleted file mode 100644 index 08b4573dd0b..00000000000 --- a/tests/ui/issues/issue-37311-type-length-limit/issue-37311.polonius.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: reached the recursion limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(.....), ...), ...) as Foo>::recurse` - --> $DIR/issue-37311.rs:17:9 - | -LL | (self, self).recurse(); - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: `<T as Foo>::recurse` defined here - --> $DIR/issue-37311.rs:16:5 - | -LL | fn recurse(&self) { - | ^^^^^^^^^^^^^^^^^ - = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-37311-type-length-limit/issue-37311.polonius/issue-37311.long-type.txt' - -error: aborting due to 1 previous error - diff --git a/tests/ui/issues/issue-38763.rs b/tests/ui/issues/issue-38763.rs index 05cd648dcfe..87c758db172 100644 --- a/tests/ui/issues/issue-38763.rs +++ b/tests/ui/issues/issue-38763.rs @@ -1,5 +1,5 @@ //@ run-pass -//@ ignore-emscripten +//@ needs-threads #[repr(C)] pub struct Foo(i128); diff --git a/tests/ui/issues/issue-44216-add-system-time.rs b/tests/ui/issues/issue-44216-add-system-time.rs index 207f72fade8..3838d28e33d 100644 --- a/tests/ui/issues/issue-44216-add-system-time.rs +++ b/tests/ui/issues/issue-44216-add-system-time.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:overflow -//@ ignore-emscripten no processes +//@ needs-subprocess use std::time::{Duration, SystemTime}; diff --git a/tests/ui/issues/issue-44216-sub-instant.rs b/tests/ui/issues/issue-44216-sub-instant.rs index 2457d2aaa04..19cd12e685f 100644 --- a/tests/ui/issues/issue-44216-sub-instant.rs +++ b/tests/ui/issues/issue-44216-sub-instant.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:overflow -//@ ignore-emscripten no processes +//@ needs-subprocess use std::time::{Instant, Duration}; diff --git a/tests/ui/issues/issue-44216-sub-system-time.rs b/tests/ui/issues/issue-44216-sub-system-time.rs index 7e33f227933..bd4f66f3e16 100644 --- a/tests/ui/issues/issue-44216-sub-system-time.rs +++ b/tests/ui/issues/issue-44216-sub-system-time.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:overflow -//@ ignore-emscripten no processes +//@ needs-subprocess use std::time::{Duration, SystemTime}; diff --git a/tests/ui/issues/issue-48728.current.stderr b/tests/ui/issues/issue-48728.current.stderr deleted file mode 100644 index 2a1b4ff7818..00000000000 --- a/tests/ui/issues/issue-48728.current.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0119]: conflicting implementations of trait `Clone` for type `Node<[_]>` - --> $DIR/issue-48728.rs:9:10 - | -LL | #[derive(Clone)] - | ^^^^^ conflicting implementation for `Node<[_]>` -... -LL | impl<T: Clone + ?Sized> Clone for Node<[T]> { - | ------------------------------------------- first implementation here - | - = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `[_]` in future versions - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/issues/issue-50714-1.rs b/tests/ui/issues/issue-50714-1.rs deleted file mode 100644 index a25940ce1cb..00000000000 --- a/tests/ui/issues/issue-50714-1.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Regression test for issue 50714, make sure that this isn't a linker error. - -#![no_std] -#![feature(start)] - -extern crate std; - -#[start] -fn start(_: isize, _: *const *const u8) -> isize where fn(&()): Eq { //~ ERROR [E0647] - 0 -} diff --git a/tests/ui/issues/issue-50714-1.stderr b/tests/ui/issues/issue-50714-1.stderr deleted file mode 100644 index 7593ac38346..00000000000 --- a/tests/ui/issues/issue-50714-1.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0647]: `#[start]` function is not allowed to have a `where` clause - --> $DIR/issue-50714-1.rs:9:50 - | -LL | fn start(_: isize, _: *const *const u8) -> isize where fn(&()): Eq { - | ^^^^^^^^^^^^^^^^^ `#[start]` function cannot have a `where` clause - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0647`. diff --git a/tests/ui/issues/issue-50781.rs b/tests/ui/issues/issue-50781.rs index 32253c3c236..ab90db1cadc 100644 --- a/tests/ui/issues/issue-50781.rs +++ b/tests/ui/issues/issue-50781.rs @@ -9,11 +9,11 @@ impl X for () { } impl Trait for dyn X {} -//~^ ERROR the trait `X` cannot be made into an object +//~^ ERROR the trait `X` is not dyn compatible pub fn main() { // Check that this does not segfault. <dyn X as X>::foo(&()); - //~^ ERROR the trait `X` cannot be made into an object - //~| ERROR the trait `X` cannot be made into an object + //~^ ERROR the trait `X` is not dyn compatible + //~| ERROR the trait `X` is not dyn compatible } diff --git a/tests/ui/issues/issue-50781.stderr b/tests/ui/issues/issue-50781.stderr index 3e54a53aa95..293e9839944 100644 --- a/tests/ui/issues/issue-50781.stderr +++ b/tests/ui/issues/issue-50781.stderr @@ -1,51 +1,54 @@ -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/issue-50781.rs:11:16 | LL | impl Trait for dyn X {} - | ^^^^^ `X` cannot be made into an object + | ^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-50781.rs:4:8 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | fn foo(&self) where Self: Trait; | ^^^ ...because method `foo` references the `Self` type in its `where` clause = help: consider moving `foo` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `X`; consider using it directly instead. -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/issue-50781.rs:16:23 | LL | <dyn X as X>::foo(&()); - | ^^^ `X` cannot be made into an object + | ^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-50781.rs:4:8 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | fn foo(&self) where Self: Trait; | ^^^ ...because method `foo` references the `Self` type in its `where` clause = help: consider moving `foo` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `X`; consider using it directly instead. = note: required for the cast from `&()` to `&dyn X` -error[E0038]: the trait `X` cannot be made into an object +error[E0038]: the trait `X` is not dyn compatible --> $DIR/issue-50781.rs:16:6 | LL | <dyn X as X>::foo(&()); - | ^^^^^ `X` cannot be made into an object + | ^^^^^ `X` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-50781.rs:4:8 | LL | trait X { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | fn foo(&self) where Self: Trait; | ^^^ ...because method `foo` references the `Self` type in its `where` clause = help: consider moving `foo` to another trait - = help: only type `()` implements the trait, consider using it directly instead + = help: only type `()` implements `X`; consider using it directly instead. error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-67552.polonius.stderr b/tests/ui/issues/issue-67552.polonius.stderr deleted file mode 100644 index ca42f87e819..00000000000 --- a/tests/ui/issues/issue-67552.polonius.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &... &mut &mut &mut &mut &mut Empty>` - --> $DIR/issue-67552.rs:28:9 - | -LL | rec(identity(&mut it)) - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: `rec` defined here - --> $DIR/issue-67552.rs:21:1 - | -LL | / fn rec<T>(mut it: T) -LL | | where -LL | | T: Iterator, - | |________________^ - = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-67552.polonius/issue-67552.long-type.txt' - -error: aborting due to 1 previous error - diff --git a/tests/ui/issues/issue-8727.polonius.stderr b/tests/ui/issues/issue-8727.polonius.stderr deleted file mode 100644 index 4fb8c2b3aff..00000000000 --- a/tests/ui/issues/issue-8727.polonius.stderr +++ /dev/null @@ -1,26 +0,0 @@ -warning: function cannot return without recursing - --> $DIR/issue-8727.rs:7:1 - | -LL | fn generic<T>() { - | ^^^^^^^^^^^^^^^ cannot return without recursing -LL | generic::<Option<T>>(); - | ---------------------- recursive call site - | - = note: `#[warn(unconditional_recursion)]` on by default - = help: a `loop` may express intention better if this is on purpose - -error: reached the recursion limit while instantiating `generic::<Option<Option<Option<O...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/issue-8727.rs:8:5 - | -LL | generic::<Option<T>>(); - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: `generic` defined here - --> $DIR/issue-8727.rs:7:1 - | -LL | fn generic<T>() { - | ^^^^^^^^^^^^^^^ - = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-8727.polonius/issue-8727.long-type.txt' - -error: aborting due to 1 previous error; 1 warning emitted - diff --git a/tests/ui/issues/issue-9575.rs b/tests/ui/issues/issue-9575.rs deleted file mode 100644 index 06b252990b6..00000000000 --- a/tests/ui/issues/issue-9575.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(start)] - -#[start] -fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize { - //~^ `#[start]` function has wrong type - 0 -} diff --git a/tests/ui/issues/issue-9575.stderr b/tests/ui/issues/issue-9575.stderr deleted file mode 100644 index 2f6e2687d24..00000000000 --- a/tests/ui/issues/issue-9575.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0308]: `#[start]` function has wrong type - --> $DIR/issue-9575.rs:4:1 - | -LL | fn start(argc: isize, argv: *const *const u8, crate_map: *const u8) -> isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ incorrect number of function parameters - | - = note: expected signature `fn(isize, *const *const u8) -> _` - found signature `fn(isize, *const *const u8, *const u8) -> _` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/json/json-multiple.polonius.stderr b/tests/ui/json/json-multiple.polonius.stderr deleted file mode 100644 index 0e4d442f299..00000000000 --- a/tests/ui/json/json-multiple.polonius.stderr +++ /dev/null @@ -1 +0,0 @@ -{"artifact":"$TEST_BUILD_DIR/json-multiple.polonius/libjson_multiple.rlib","emit":"link"} diff --git a/tests/ui/json/json-options.polonius.stderr b/tests/ui/json/json-options.polonius.stderr deleted file mode 100644 index e21f6f85d16..00000000000 --- a/tests/ui/json/json-options.polonius.stderr +++ /dev/null @@ -1 +0,0 @@ -{"artifact":"$TEST_BUILD_DIR/json-options.polonius/libjson_options.rlib","emit":"link"} diff --git a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr index f23f855c9e8..dab68258a47 100644 --- a/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr +++ b/tests/ui/keyword/extern/keyword-extern-as-identifier-use.stderr @@ -13,9 +13,9 @@ error[E0432]: unresolved import `r#extern` --> $DIR/keyword-extern-as-identifier-use.rs:1:5 | LL | use extern::foo; - | ^^^^^^ you might be missing crate `r#extern` + | ^^^^^^ use of unresolved module or unlinked crate `r#extern` | -help: consider importing the `r#extern` crate +help: you might be missing a crate named `r#extern`, add it to your project and import it in your code | LL + extern crate r#extern; | diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr index c392879db3e..83446fc9ec0 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr @@ -19,33 +19,35 @@ note: required by a bound in `take_param` LL | fn take_param<T:Foo>(foo: &T) { } | ^^^ required by this bound in `take_param` -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/kindck-inherited-copy-bound.rs:28:19 | LL | let z = &x as &dyn Foo; - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/kindck-inherited-copy-bound.rs:10:13 | LL | trait Foo : Copy { | --- ^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/kindck-inherited-copy-bound.rs:28:13 | LL | let z = &x as &dyn Foo; - | ^^ `Foo` cannot be made into an object + | ^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/kindck-inherited-copy-bound.rs:10:13 | LL | trait Foo : Copy { | --- ^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... = note: required for the cast from `&Box<{integer}>` to `&dyn Foo` error: aborting due to 3 previous errors diff --git a/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr index 34dcad13af3..271e5afb9e7 100644 --- a/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/kindck/kindck-inherited-copy-bound.dyn_compatible_for_dispatch.stderr @@ -19,19 +19,20 @@ note: required by a bound in `take_param` LL | fn take_param<T:Foo>(foo: &T) { } | ^^^ required by this bound in `take_param` -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/kindck-inherited-copy-bound.rs:28:13 | LL | let z = &x as &dyn Foo; - | ^^ `Foo` cannot be made into an object + | ^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/kindck-inherited-copy-bound.rs:10:13 | LL | trait Foo : Copy { | --- ^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... = note: required for the cast from `&Box<i32>` to `&dyn Foo` error: aborting due to 2 previous errors diff --git a/tests/ui/lang-items/issue-19660.rs b/tests/ui/lang-items/issue-19660.rs deleted file mode 100644 index aff57df7ece..00000000000 --- a/tests/ui/lang-items/issue-19660.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ error-pattern: requires `copy` lang_item - -#![feature(lang_items, start, no_core)] -#![no_core] - -#[lang = "sized"] -trait Sized { } - -struct S; - -#[start] -fn main(_: isize, _: *const *const u8) -> isize { - let _ = S; - 0 -} diff --git a/tests/ui/lang-items/issue-19660.stderr b/tests/ui/lang-items/issue-19660.stderr deleted file mode 100644 index e5a8a143d03..00000000000 --- a/tests/ui/lang-items/issue-19660.stderr +++ /dev/null @@ -1,4 +0,0 @@ -error: requires `copy` lang_item - -error: aborting due to 1 previous error - diff --git a/tests/ui/lang-items/lang-item-missing.rs b/tests/ui/lang-items/lang-item-missing.rs index 8762594202a..5b832a5bb8f 100644 --- a/tests/ui/lang-items/lang-item-missing.rs +++ b/tests/ui/lang-items/lang-item-missing.rs @@ -3,10 +3,11 @@ //@ error-pattern: requires `sized` lang_item -#![feature(start, no_core)] +#![feature(lang_items, no_core)] #![no_core] +#![no_main] -#[start] -fn start(argc: isize, argv: *const *const u8) -> isize { - 0 +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + loop {} } diff --git a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs new file mode 100644 index 00000000000..9b634ee8ee3 --- /dev/null +++ b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.rs @@ -0,0 +1,15 @@ +//@ error-pattern: requires `copy` lang_item + +#![feature(lang_items, no_core)] +#![no_core] +#![no_main] + +#[lang = "sized"] +trait Sized { } + +struct S; + +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { + argc +} diff --git a/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr new file mode 100644 index 00000000000..3dc7716ecd2 --- /dev/null +++ b/tests/ui/lang-items/missing-copy-lang-item-issue-19660.stderr @@ -0,0 +1,8 @@ +error: requires `copy` lang_item + --> $DIR/missing-copy-lang-item-issue-19660.rs:14:5 + | +LL | argc + | ^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.rs b/tests/ui/layout/base-layout-is-sized-ice-123078.rs index 15f11145f84..b1c33e15075 100644 --- a/tests/ui/layout/base-layout-is-sized-ice-123078.rs +++ b/tests/ui/layout/base-layout-is-sized-ice-123078.rs @@ -8,6 +8,7 @@ struct S { } const C: S = unsafe { std::mem::transmute(()) }; +//~^ ERROR cannot transmute between types of different sizes, or dependently-sized types const _: [(); { C; 0 diff --git a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr index 9181368533a..d8743d4e6d6 100644 --- a/tests/ui/layout/base-layout-is-sized-ice-123078.stderr +++ b/tests/ui/layout/base-layout-is-sized-ice-123078.stderr @@ -16,6 +16,16 @@ help: the `Box` type always has a statically known size and allocates its conten LL | a: Box<[u8]>, | ++++ + -error: aborting due to 1 previous error +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/base-layout-is-sized-ice-123078.rs:10:23 + | +LL | const C: S = unsafe { std::mem::transmute(()) }; + | ^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `()` (0 bits) + = note: target type: `S` (the type `S` has an unknown layout) + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0512. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/invalid-unsized-const-eval.rs b/tests/ui/layout/invalid-unsized-const-eval.rs index 2dec0b0faac..1f664d30055 100644 --- a/tests/ui/layout/invalid-unsized-const-eval.rs +++ b/tests/ui/layout/invalid-unsized-const-eval.rs @@ -10,5 +10,6 @@ struct LazyLock { } static EMPTY_SET: LazyLock = todo!(); +//~^ ERROR could not evaluate static initializer fn main() {} diff --git a/tests/ui/layout/invalid-unsized-const-eval.stderr b/tests/ui/layout/invalid-unsized-const-eval.stderr index bf65782b7a8..a434ca9b2c7 100644 --- a/tests/ui/layout/invalid-unsized-const-eval.stderr +++ b/tests/ui/layout/invalid-unsized-const-eval.stderr @@ -7,6 +7,13 @@ LL | data: (dyn Sync, ()), = help: the trait `Sized` is not implemented for `(dyn Sync + 'static)` = note: only the last element of a tuple may have a dynamically sized type -error: aborting due to 1 previous error +error[E0080]: could not evaluate static initializer + --> $DIR/invalid-unsized-const-eval.rs:12:1 + | +LL | static EMPTY_SET: LazyLock = todo!(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `(dyn Sync, ())` has an unknown layout + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0080, E0277. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr b/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr index 3f565d6ee5b..f54e97e2a5c 100644 --- a/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr +++ b/tests/ui/layout/invalid-unsized-in-always-sized-tail.stderr @@ -18,6 +18,20 @@ LL | struct MySlice<T>(T); | | | this could be changed to `T: ?Sized`... -error: aborting due to 1 previous error +error[E0080]: could not evaluate static initializer + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: the type `MySlice<[bool]>` has an unknown layout + | +note: inside `align_of::<P2>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `CHECK` + --> $DIR/invalid-unsized-in-always-sized-tail.rs:15:28 + | +LL | static CHECK: () = assert!(align_of::<P2>() == 1); + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0080, E0277. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs b/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs index 96c993035ef..f84c10d8e5c 100644 --- a/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs +++ b/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.rs @@ -6,5 +6,6 @@ struct ArenaSet<U: Deref, V: ?Sized = <U as Deref>::Target>(V, U); //~^ ERROR the size for values of type `V` cannot be known at compilation time const DATA: *const ArenaSet<Vec<u8>> = std::ptr::null_mut(); +//~^ ERROR evaluation of constant value failed pub fn main() {} diff --git a/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr b/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr index f39cb29868a..220951fab86 100644 --- a/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr +++ b/tests/ui/layout/issue-unsized-tail-restatic-ice-122488.stderr @@ -22,6 +22,13 @@ help: the `Box` type always has a statically known size and allocates its conten LL | struct ArenaSet<U: Deref, V: ?Sized = <U as Deref>::Target>(Box<V>, U); | ++++ + -error: aborting due to 1 previous error +error[E0080]: evaluation of constant value failed + --> $DIR/issue-unsized-tail-restatic-ice-122488.rs:8:1 + | +LL | const DATA: *const ArenaSet<Vec<u8>> = std::ptr::null_mut(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `ArenaSet<Vec<u8>, [u8]>` has an unknown layout + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0080, E0277. +For more information about an error, try `rustc --explain E0080`. diff --git a/tests/ui/layout/reprc-power-alignment.rs b/tests/ui/layout/reprc-power-alignment.rs new file mode 100644 index 00000000000..f6c1df55988 --- /dev/null +++ b/tests/ui/layout/reprc-power-alignment.rs @@ -0,0 +1,152 @@ +//@ check-pass +//@ compile-flags: --target powerpc64-ibm-aix +//@ needs-llvm-components: powerpc +//@ add-core-stubs +#![feature(no_core)] +#![no_core] +#![no_std] + +extern crate minicore; +use minicore::*; + +#[warn(uses_power_alignment)] + +#[repr(C)] +pub struct Floats { + a: f64, + b: u8, + c: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + d: f32, +} + +pub struct Floats2 { + a: f64, + b: u32, + c: f64, +} + +#[repr(C)] +pub struct Floats3 { + a: f32, + b: f32, + c: i64, +} + +#[repr(C)] +pub struct Floats4 { + a: u64, + b: u32, + c: f32, +} + +#[repr(C)] +pub struct Floats5 { + a: f32, + b: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + c: f32, +} + +#[repr(C)] +pub struct FloatAgg1 { + x: Floats, + y: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} + +#[repr(C)] +pub struct FloatAgg2 { + x: i64, + y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} + +#[repr(C)] +pub struct FloatAgg3 { + x: FloatAgg1, + // NOTE: the "power" alignment rule is infectious to nested struct fields. + y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + z: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} + +#[repr(C)] +pub struct FloatAgg4 { + x: FloatAgg1, + y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} + +#[repr(C)] +pub struct FloatAgg5 { + x: FloatAgg1, + y: FloatAgg2, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + z: FloatAgg3, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} + +#[repr(C)] +pub struct FloatAgg6 { + x: i64, + y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + z: u8, +} + +#[repr(C)] +pub struct FloatAgg7 { + x: i64, + y: Floats, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + z: u8, + zz: f32, +} + +#[repr(C)] +pub struct A { + d: f64, +} +#[repr(C)] +pub struct B { + a: A, + f: f32, + d: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} +#[repr(C)] +pub struct C { + c: u8, + b: B, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} +#[repr(C)] +pub struct D { + x: f64, +} +#[repr(C)] +pub struct E { + x: i32, + d: D, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} +#[repr(C)] +pub struct F { + a: u8, + b: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} +#[repr(C)] +pub struct G { + a: u8, + b: u8, + c: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + d: f32, + e: f64, //~ WARNING repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type +} +// Should not warn on #[repr(packed)]. +#[repr(packed)] +pub struct H { + a: u8, + b: u8, + c: f64, + d: f32, + e: f64, +} +#[repr(C, packed)] +pub struct I { + a: u8, + b: u8, + c: f64, + d: f32, + e: f64, +} + +fn main() { } diff --git a/tests/ui/layout/reprc-power-alignment.stderr b/tests/ui/layout/reprc-power-alignment.stderr new file mode 100644 index 00000000000..18664e4d655 --- /dev/null +++ b/tests/ui/layout/reprc-power-alignment.stderr @@ -0,0 +1,112 @@ +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:18:5 + | +LL | c: f64, + | ^^^^^^ + | +note: the lint level is defined here + --> $DIR/reprc-power-alignment.rs:12:8 + | +LL | #[warn(uses_power_alignment)] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:45:5 + | +LL | b: f64, + | ^^^^^^ + | + = note: `#[warn(uses_power_alignment)]` on by default + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:52:5 + | +LL | y: f64, + | ^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:58:5 + | +LL | y: Floats, + | ^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:65:5 + | +LL | y: FloatAgg2, + | ^^^^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:66:5 + | +LL | z: FloatAgg2, + | ^^^^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:72:5 + | +LL | y: FloatAgg2, + | ^^^^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:78:5 + | +LL | y: FloatAgg2, + | ^^^^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:79:5 + | +LL | z: FloatAgg3, + | ^^^^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:85:5 + | +LL | y: Floats, + | ^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:92:5 + | +LL | y: Floats, + | ^^^^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:105:3 + | +LL | d: f64, + | ^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:110:3 + | +LL | b: B, + | ^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:119:3 + | +LL | d: D, + | ^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:124:3 + | +LL | b: f64, + | ^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:130:5 + | +LL | c: f64, + | ^^^^^^ + +warning: repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type + --> $DIR/reprc-power-alignment.rs:132:5 + | +LL | e: f64, + | ^^^^^^ + +warning: 17 warnings emitted + diff --git a/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.rs b/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.rs new file mode 100644 index 00000000000..91280e49dcd --- /dev/null +++ b/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.rs @@ -0,0 +1,11 @@ +#![feature(trivial_bounds)] + +fn return_str() +where + str: Sized, +{ + [(); { let _a: Option<str> = None; 0 }]; + //~^ ERROR evaluation of constant value failed +} + +fn main() {} diff --git a/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.stderr b/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.stderr new file mode 100644 index 00000000000..6c7c51db8df --- /dev/null +++ b/tests/ui/layout/uncomputable-due-to-trivial-bounds-ice-135138.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/uncomputable-due-to-trivial-bounds-ice-135138.rs:7:16 + | +LL | [(); { let _a: Option<str> = None; 0 }]; + | ^^ the type `Option<str>` has an unknown layout + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/layout/unexpected-unsized-field-issue-135020.rs b/tests/ui/layout/unexpected-unsized-field-issue-135020.rs new file mode 100644 index 00000000000..c81d037e510 --- /dev/null +++ b/tests/ui/layout/unexpected-unsized-field-issue-135020.rs @@ -0,0 +1,7 @@ +//@ check-pass + +fn problem_thingy(items: &mut impl Iterator<Item = str>) { + items.peekable(); +} + +fn main() {} diff --git a/tests/ui/layout/unknown-when-no-type-parameter.rs b/tests/ui/layout/unknown-when-no-type-parameter.rs new file mode 100644 index 00000000000..94c32cf262f --- /dev/null +++ b/tests/ui/layout/unknown-when-no-type-parameter.rs @@ -0,0 +1,14 @@ +#![feature(trivial_bounds)] + +//@ error-pattern: error[E0080]: evaluation of constant value failed +//@ error-pattern: the type `<() as Project>::Assoc` has an unknown layout + +trait Project { + type Assoc; +} + +fn foo() where (): Project { + [(); size_of::<<() as Project>::Assoc>()]; +} + +fn main() {} diff --git a/tests/ui/layout/unknown-when-no-type-parameter.stderr b/tests/ui/layout/unknown-when-no-type-parameter.stderr new file mode 100644 index 00000000000..d0456e2b329 --- /dev/null +++ b/tests/ui/layout/unknown-when-no-type-parameter.stderr @@ -0,0 +1,16 @@ +error[E0080]: evaluation of constant value failed + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + | + = note: the type `<() as Project>::Assoc` has an unknown layout + | +note: inside `std::mem::size_of::<<() as Project>::Assoc>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL +note: inside `foo::{constant#0}` + --> $DIR/unknown-when-no-type-parameter.rs:11:10 + | +LL | [(); size_of::<<() as Project>::Assoc>()]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs new file mode 100644 index 00000000000..973235fe65a --- /dev/null +++ b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.rs @@ -0,0 +1,12 @@ +#![feature(ptr_metadata)] +#![feature(trivial_bounds)] + +fn return_str() +where + str: std::ptr::Pointee<Metadata = str>, +{ + [(); { let _a: Option<&str> = None; 0 }]; + //~^ ERROR evaluation of constant value failed +} + +fn main() {} diff --git a/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr new file mode 100644 index 00000000000..68bba2e9678 --- /dev/null +++ b/tests/ui/layout/unknown-when-ptr-metadata-is-DST.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of constant value failed + --> $DIR/unknown-when-ptr-metadata-is-DST.rs:8:16 + | +LL | [(); { let _a: Option<&str> = None; 0 }]; + | ^^ the type `str` has an unknown layout + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/layout/valid_range_oob.stderr b/tests/ui/layout/valid_range_oob.stderr index 9c360b2cd6e..1a0c3841250 100644 --- a/tests/ui/layout/valid_range_oob.stderr +++ b/tests/ui/layout/valid_range_oob.stderr @@ -5,4 +5,4 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: #0 [layout_of] computing layout of `Foo` #1 [eval_to_allocation_raw] const-evaluating + checking `FOO` -end of query stack +... and 2 other queries... use `env RUST_BACKTRACE=1` to see the full query stack diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.classic.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.classic.stderr deleted file mode 100644 index 2f00a877142..00000000000 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.classic.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error[E0275]: overflow normalizing the type alias `Loop` - --> $DIR/inherent-impls-overflow.rs:7:13 - | -LL | type Loop = Loop; - | ^^^^ - | - = note: in case this is a recursive type alias, consider using a struct, enum, or union instead - -error[E0275]: overflow normalizing the type alias `Loop` - --> $DIR/inherent-impls-overflow.rs:9:1 - | -LL | impl Loop {} - | ^^^^^^^^^^^^ - | - = note: in case this is a recursive type alias, consider using a struct, enum, or union instead - -error[E0275]: overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:13:17 - | -LL | type Poly0<T> = Poly1<(T,)>; - | ^^^^^^^^^^^ - | - = note: in case this is a recursive type alias, consider using a struct, enum, or union instead - -error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:16:17 - | -LL | type Poly1<T> = Poly0<(T,)>; - | ^^^^^^^^^^^ - | - = note: in case this is a recursive type alias, consider using a struct, enum, or union instead - -error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>` - --> $DIR/inherent-impls-overflow.rs:20:1 - | -LL | impl Poly0<()> {} - | ^^^^^^^^^^^^^^^^^ - | - = note: in case this is a recursive type alias, consider using a struct, enum, or union instead - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs index 6af6655149b..d7c7b2e2414 100644 --- a/tests/ui/lifetimes/tail-expr-lock-poisoning.rs +++ b/tests/ui/lifetimes/tail-expr-lock-poisoning.rs @@ -1,5 +1,6 @@ //@ revisions: edition2021 edition2024 -//@ ignore-wasm no panic or subprocess support +//@ ignore-wasm no panic support +//@ needs-subprocess //@ [edition2024] edition: 2024 //@ run-pass //@ needs-unwind diff --git a/tests/ui/lint/clashing-extern-fn.rs b/tests/ui/lint/clashing-extern-fn.rs index a12fe81eecd..9bbb20246df 100644 --- a/tests/ui/lint/clashing-extern-fn.rs +++ b/tests/ui/lint/clashing-extern-fn.rs @@ -248,6 +248,7 @@ mod sameish_members { mod same_sized_members_clash { mod a { + #[allow(uses_power_alignment)] #[repr(C)] struct Point3 { x: f32, diff --git a/tests/ui/lint/clashing-extern-fn.stderr b/tests/ui/lint/clashing-extern-fn.stderr index b30dd476a1d..48dd1adbc1f 100644 --- a/tests/ui/lint/clashing-extern-fn.stderr +++ b/tests/ui/lint/clashing-extern-fn.stderr @@ -1,5 +1,5 @@ warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe - --> $DIR/clashing-extern-fn.rs:482:55 + --> $DIR/clashing-extern-fn.rs:483:55 | LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -9,7 +9,7 @@ LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN = note: `#[warn(improper_ctypes)]` on by default warning: `extern` block uses type `Option<UnsafeCell<NonZero<usize>>>`, which is not FFI-safe - --> $DIR/clashing-extern-fn.rs:486:46 + --> $DIR/clashing-extern-fn.rs:487:46 | LL | fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZero<usize>>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe @@ -151,7 +151,7 @@ LL | fn draw_point(p: Point); found `unsafe extern "C" fn(sameish_members::b::Point)` warning: `origin` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:269:13 + --> $DIR/clashing-extern-fn.rs:270:13 | LL | fn origin() -> Point3; | ---------------------- `origin` previously declared here @@ -163,7 +163,7 @@ LL | fn origin() -> Point3; found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3` warning: `transparent_incorrect` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:292:13 + --> $DIR/clashing-extern-fn.rs:293:13 | LL | fn transparent_incorrect() -> T; | -------------------------------- `transparent_incorrect` previously declared here @@ -175,7 +175,7 @@ LL | fn transparent_incorrect() -> isize; found `unsafe extern "C" fn() -> isize` warning: `missing_return_type` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:310:13 + --> $DIR/clashing-extern-fn.rs:311:13 | LL | fn missing_return_type() -> usize; | ---------------------------------- `missing_return_type` previously declared here @@ -187,7 +187,7 @@ LL | fn missing_return_type(); found `unsafe extern "C" fn()` warning: `non_zero_usize` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:328:13 + --> $DIR/clashing-extern-fn.rs:329:13 | LL | fn non_zero_usize() -> core::num::NonZero<usize>; | ------------------------------------------------- `non_zero_usize` previously declared here @@ -199,7 +199,7 @@ LL | fn non_zero_usize() -> usize; found `unsafe extern "C" fn() -> usize` warning: `non_null_ptr` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:330:13 + --> $DIR/clashing-extern-fn.rs:331:13 | LL | fn non_null_ptr() -> core::ptr::NonNull<usize>; | ----------------------------------------------- `non_null_ptr` previously declared here @@ -211,7 +211,7 @@ LL | fn non_null_ptr() -> *const usize; found `unsafe extern "C" fn() -> *const usize` warning: `option_non_zero_usize_incorrect` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:424:13 + --> $DIR/clashing-extern-fn.rs:425:13 | LL | fn option_non_zero_usize_incorrect() -> usize; | ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here @@ -223,7 +223,7 @@ LL | fn option_non_zero_usize_incorrect() -> isize; found `unsafe extern "C" fn() -> isize` warning: `option_non_null_ptr_incorrect` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:426:13 + --> $DIR/clashing-extern-fn.rs:427:13 | LL | fn option_non_null_ptr_incorrect() -> *const usize; | --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here @@ -235,7 +235,7 @@ LL | fn option_non_null_ptr_incorrect() -> *const isize; found `unsafe extern "C" fn() -> *const isize` warning: `hidden_niche_transparent_no_niche` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:482:13 + --> $DIR/clashing-extern-fn.rs:483:13 | LL | fn hidden_niche_transparent_no_niche() -> usize; | ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here @@ -247,7 +247,7 @@ LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN found `unsafe extern "C" fn() -> Option<TransparentNoNiche>` warning: `hidden_niche_unsafe_cell` redeclared with a different signature - --> $DIR/clashing-extern-fn.rs:486:13 + --> $DIR/clashing-extern-fn.rs:487:13 | LL | fn hidden_niche_unsafe_cell() -> usize; | --------------------------------------- `hidden_niche_unsafe_cell` previously declared here diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/allow.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/allow.stderr index fd434eacf3d..e1c12cfd1a5 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/allow.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/allow.stderr @@ -7,6 +7,8 @@ LL | dbg!(String::new().as_ptr()); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/allow.rs:7:12 @@ -23,6 +25,8 @@ LL | dbg!(String::new().as_ptr()); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/allow.rs:18:12 diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/calls.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/calls.stderr index d1615b76d82..41c6cdd0e3e 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/calls.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/calls.stderr @@ -7,6 +7,8 @@ LL | let ptr = cstring().as_ptr(); | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/calls.rs:1:9 @@ -23,6 +25,8 @@ LL | let ptr = cstring().as_ptr(); | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `CString` will be dropped @@ -34,6 +38,8 @@ LL | let _ptr: *const u8 = cstring().as_ptr().cast(); | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `CString` will be dropped @@ -45,6 +51,8 @@ LL | let _ptr: *const u8 = { cstring() }.as_ptr().cast(); | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `CString` will be dropped @@ -56,6 +64,8 @@ LL | let _ptr: *const u8 = { cstring().as_ptr() }.cast(); | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: aborting due to 5 previous errors diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/cstring-as-ptr.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/cstring-as-ptr.stderr index 5289fbb8723..d4126ba231f 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/cstring-as-ptr.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/cstring-as-ptr.stderr @@ -15,6 +15,8 @@ LL | let s = CString::new("some text").unwrap().as_ptr(); | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/cstring-as-ptr.rs:2:9 @@ -34,6 +36,8 @@ LL | mymacro!(); | ---------- in this macro invocation | = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> = note: this error originates in the macro `mymacro` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/example-from-issue123613.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/example-from-issue123613.stderr index 0de794f6ae2..aace55e92cf 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/example-from-issue123613.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/example-from-issue123613.stderr @@ -7,6 +7,8 @@ LL | let str1 = String::with_capacity(MAX_PATH).as_mut_ptr(); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_mut_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_mut_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/example-from-issue123613.rs:1:9 @@ -23,6 +25,8 @@ LL | let str2 = String::from("TotototototototototototototototototoT").as_ptr | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: aborting due to 2 previous errors diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/ext.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/ext.stderr index 5d401c89c0c..976334ddef9 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/ext.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/ext.stderr @@ -7,6 +7,8 @@ LL | let _ptr1 = Vec::<u32>::new().as_ptr().dbg(); | this `Vec<u32>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u32>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Vec<u32>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Vec<u32>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/ext.rs:1:9 @@ -23,6 +25,8 @@ LL | let _ptr2 = vec![0].as_ptr().foo(); | this `Vec<u32>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u32>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Vec<u32>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Vec<u32>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: aborting due to 2 previous errors diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/methods.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/methods.stderr index 11c052c158e..a86a69bc39a 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/methods.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/methods.stderr @@ -7,6 +7,8 @@ LL | vec![0u8].as_ptr(); | this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Vec<u8>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Vec<u8>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/methods.rs:1:9 @@ -23,6 +25,8 @@ LL | vec![0u8].as_mut_ptr(); | this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_mut_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Vec<u8>` to lives at least as long as the pointer returned by the call to `as_mut_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Vec<u8>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: aborting due to 2 previous errors diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/temporaries.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/temporaries.stderr index d2e9ac8c4e9..e8994703cab 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/temporaries.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/temporaries.stderr @@ -7,6 +7,8 @@ LL | string().as_ptr(); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/temporaries.rs:2:9 @@ -23,6 +25,8 @@ LL | "hello".to_string().as_ptr(); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `String` will be dropped @@ -34,6 +38,8 @@ LL | (string() + "hello").as_ptr(); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `String` will be dropped @@ -45,6 +51,8 @@ LL | (if true { String::new() } else { "hello".into() }).as_ptr(); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `String` will be dropped @@ -58,6 +66,8 @@ LL | .as_ptr(); | ^^^^^^ this pointer will immediately be invalid | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `String` will be dropped @@ -71,6 +81,8 @@ LL | .as_ptr(); | ^^^^^^ this pointer will immediately be invalid | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `String` will be dropped @@ -82,6 +94,8 @@ LL | { string() }.as_ptr(); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Vec<u8>` will be dropped @@ -93,6 +107,8 @@ LL | vec![0u8].as_ptr(); | this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Vec<u8>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Vec<u8>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: aborting due to 8 previous errors diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/types.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/types.stderr index 250ed6dc9e3..fab2459b53f 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/types.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/types.stderr @@ -7,6 +7,8 @@ LL | declval::<CString>().as_ptr(); | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `CString` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `CString` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> note: the lint level is defined here --> $DIR/types.rs:1:9 @@ -23,6 +25,8 @@ LL | declval::<String>().as_ptr(); | this `String` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `String` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `String` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `String` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Vec<u8>` will be dropped @@ -34,6 +38,8 @@ LL | declval::<Vec<u8>>().as_ptr(); | this `Vec<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Vec<u8>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Vec<u8>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Box<CString>` will be dropped @@ -45,6 +51,8 @@ LL | declval::<Box<CString>>().as_ptr(); | this `Box<CString>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Box<CString>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Box<CString>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Box<CString>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Box<[u8]>` will be dropped @@ -56,6 +64,8 @@ LL | declval::<Box<[u8]>>().as_ptr(); | this `Box<[u8]>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Box<[u8]>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Box<[u8]>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Box<[u8]>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Box<str>` will be dropped @@ -67,6 +77,8 @@ LL | declval::<Box<str>>().as_ptr(); | this `Box<str>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Box<str>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Box<str>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Box<str>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Box<CStr>` will be dropped @@ -78,6 +90,8 @@ LL | declval::<Box<CStr>>().as_ptr(); | this `Box<CStr>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Box<CStr>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Box<CStr>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Box<CStr>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `[u8; 10]` will be dropped @@ -89,6 +103,8 @@ LL | declval::<[u8; 10]>().as_ptr(); | this `[u8; 10]` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `[u8; 10]` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `[u8; 10]` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `[u8; 10]` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Box<[u8; 10]>` will be dropped @@ -100,6 +116,8 @@ LL | declval::<Box<[u8; 10]>>().as_ptr(); | this `Box<[u8; 10]>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Box<[u8; 10]>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Box<[u8; 10]>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Box<[u8; 10]>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Box<Vec<u8>>` will be dropped @@ -111,6 +129,8 @@ LL | declval::<Box<Vec<u8>>>().as_ptr(); | this `Box<Vec<u8>>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Box<Vec<u8>>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Box<Vec<u8>>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Box<Vec<u8>>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Box<String>` will be dropped @@ -122,6 +142,8 @@ LL | declval::<Box<String>>().as_ptr(); | this `Box<String>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Box<String>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Box<String>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Box<String>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Box<Box<Box<Box<[u8]>>>>` will be dropped @@ -133,6 +155,8 @@ LL | declval::<Box<Box<Box<Box<[u8]>>>>>().as_ptr(); | this `Box<Box<Box<Box<[u8]>>>>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Box<Box<Box<Box<[u8]>>>>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Box<Box<Box<Box<[u8]>>>>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Box<Box<Box<Box<[u8]>>>>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Cell<u8>` will be dropped @@ -144,6 +168,8 @@ LL | declval::<Cell<u8>>().as_ptr(); | this `Cell<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Cell<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Cell<u8>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Cell<u8>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `MaybeUninit<u8>` will be dropped @@ -155,6 +181,8 @@ LL | declval::<MaybeUninit<u8>>().as_ptr(); | this `MaybeUninit<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `MaybeUninit<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `MaybeUninit<u8>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `MaybeUninit<u8>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `Vec<AsPtrFake>` will be dropped @@ -166,6 +194,8 @@ LL | declval::<Vec<AsPtrFake>>().as_ptr(); | this `Vec<AsPtrFake>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `as_ptr` the `Vec<AsPtrFake>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `Vec<AsPtrFake>` to lives at least as long as the pointer returned by the call to `as_ptr` + = help: in particular, if this pointer is returned from the current function, binding the `Vec<AsPtrFake>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `UnsafeCell<u8>` will be dropped @@ -177,6 +207,8 @@ LL | declval::<UnsafeCell<u8>>().get(); | this `UnsafeCell<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `get` the `UnsafeCell<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `UnsafeCell<u8>` to lives at least as long as the pointer returned by the call to `get` + = help: in particular, if this pointer is returned from the current function, binding the `UnsafeCell<u8>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: a dangling pointer will be produced because the temporary `SyncUnsafeCell<u8>` will be dropped @@ -188,6 +220,8 @@ LL | declval::<SyncUnsafeCell<u8>>().get(); | this `SyncUnsafeCell<u8>` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | = note: pointers do not have a lifetime; when calling `get` the `SyncUnsafeCell<u8>` will be deallocated at the end of the statement because nothing is referencing it as far as the type system is concerned + = help: you must make sure that the variable you bind the `SyncUnsafeCell<u8>` to lives at least as long as the pointer returned by the call to `get` + = help: in particular, if this pointer is returned from the current function, binding the `SyncUnsafeCell<u8>` inside the function will not suffice = help: for more information, see <https://doc.rust-lang.org/reference/destructors.html> error: aborting due to 17 previous errors diff --git a/tests/ui/lint/dead-code/lint-dead-code-2.rs b/tests/ui/lint/dead-code/lint-dead-code-2.rs index 6bfa4d96f71..c82088ec54b 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-2.rs +++ b/tests/ui/lint/dead-code/lint-dead-code-2.rs @@ -1,6 +1,6 @@ #![allow(unused_variables)] #![deny(dead_code)] -#![feature(rustc_attrs, start)] +#![feature(rustc_attrs)] struct Foo; @@ -21,21 +21,16 @@ fn live_fn() {} fn dead_fn() {} //~ ERROR: function `dead_fn` is never used -#[rustc_main] -fn dead_fn2() {} //~ ERROR: function `dead_fn2` is never used - fn used_fn() {} -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +#[rustc_main] +fn actual_main() { used_fn(); let foo = Foo; foo.bar2(); - 0 } // this is not main fn main() { //~ ERROR: function `main` is never used dead_fn(); - dead_fn2(); } diff --git a/tests/ui/lint/dead-code/lint-dead-code-2.stderr b/tests/ui/lint/dead-code/lint-dead-code-2.stderr index 85af553c986..4a5f3b8a687 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-2.stderr +++ b/tests/ui/lint/dead-code/lint-dead-code-2.stderr @@ -10,17 +10,11 @@ note: the lint level is defined here LL | #![deny(dead_code)] | ^^^^^^^^^ -error: function `dead_fn2` is never used - --> $DIR/lint-dead-code-2.rs:25:4 - | -LL | fn dead_fn2() {} - | ^^^^^^^^ - error: function `main` is never used - --> $DIR/lint-dead-code-2.rs:38:4 + --> $DIR/lint-dead-code-2.rs:34:4 | LL | fn main() { | ^^^^ -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/lint/linker-warning-bin.rs b/tests/ui/lint/linker-warning-bin.rs new file mode 100644 index 00000000000..ead0aa002bf --- /dev/null +++ b/tests/ui/lint/linker-warning-bin.rs @@ -0,0 +1,6 @@ +//@ build-pass +#![crate_type = "bin"] +#![warn(unused_attributes)] +#![allow(linker_messages)] + +fn main() {} diff --git a/tests/ui/lint/linker-warning.rs b/tests/ui/lint/linker-warning.rs new file mode 100644 index 00000000000..10e3f56ab95 --- /dev/null +++ b/tests/ui/lint/linker-warning.rs @@ -0,0 +1,9 @@ +//@ check-pass +#![crate_type = "lib"] +#![warn(unused_attributes)] +#![allow(linker_messages)] +//~^ WARNING unused attribute + +#[allow(linker_messages)] +//~^ WARNING should be an inner attribute +fn foo() {} diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr new file mode 100644 index 00000000000..3a2c392fd03 --- /dev/null +++ b/tests/ui/lint/linker-warning.stderr @@ -0,0 +1,22 @@ +warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]` + --> $DIR/linker-warning.rs:7:1 + | +LL | #[allow(linker_messages)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/linker-warning.rs:3:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/linker-warning.rs:4:1 + | +LL | #![allow(linker_messages)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: the `linker_warnings` lint can only be controlled at the root of a crate that needs to be linked + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/lint-double-negations.rs b/tests/ui/lint/lint-double-negations.rs new file mode 100644 index 00000000000..43e61dd7c13 --- /dev/null +++ b/tests/ui/lint/lint-double-negations.rs @@ -0,0 +1,9 @@ +//@ check-pass +fn main() { + let x = 1; + -x; + -(-x); + --x; //~ WARN use of a double negation + ---x; //~ WARN use of a double negation + let _y = --(-x); //~ WARN use of a double negation +} diff --git a/tests/ui/lint/lint-double-negations.stderr b/tests/ui/lint/lint-double-negations.stderr new file mode 100644 index 00000000000..9367f74be54 --- /dev/null +++ b/tests/ui/lint/lint-double-negations.stderr @@ -0,0 +1,42 @@ +warning: use of a double negation + --> $DIR/lint-double-negations.rs:6:5 + | +LL | --x; + | ^^^ + | + = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages + = note: use `-= 1` if you meant to decrement the value + = note: `#[warn(double_negations)]` on by default +help: add parentheses for clarity + | +LL | -(-x); + | + + + +warning: use of a double negation + --> $DIR/lint-double-negations.rs:7:6 + | +LL | ---x; + | ^^^ + | + = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages + = note: use `-= 1` if you meant to decrement the value +help: add parentheses for clarity + | +LL | --(-x); + | + + + +warning: use of a double negation + --> $DIR/lint-double-negations.rs:8:14 + | +LL | let _y = --(-x); + | ^^^^^^ + | + = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages + = note: use `-= 1` if you meant to decrement the value +help: add parentheses for clarity + | +LL | let _y = -(-(-x)); + | + + + +warning: 3 warnings emitted + diff --git a/tests/ui/lint/lint-type-overflow2.rs b/tests/ui/lint/lint-type-overflow2.rs index f007b45b847..ac7420326c8 100644 --- a/tests/ui/lint/lint-type-overflow2.rs +++ b/tests/ui/lint/lint-type-overflow2.rs @@ -4,6 +4,7 @@ fn main() { let x2: i8 = --128; //~ ERROR literal out of range for `i8` + //~| WARN use of a double negation let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32` let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32` diff --git a/tests/ui/lint/lint-type-overflow2.stderr b/tests/ui/lint/lint-type-overflow2.stderr index eb593d062f2..2cfb18e9fe9 100644 --- a/tests/ui/lint/lint-type-overflow2.stderr +++ b/tests/ui/lint/lint-type-overflow2.stderr @@ -1,3 +1,17 @@ +warning: use of a double negation + --> $DIR/lint-type-overflow2.rs:6:18 + | +LL | let x2: i8 = --128; + | ^^^^^ + | + = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages + = note: use `-= 1` if you meant to decrement the value + = note: `#[warn(double_negations)]` on by default +help: add parentheses for clarity + | +LL | let x2: i8 = -(-128); + | + + + error: literal out of range for `i8` --> $DIR/lint-type-overflow2.rs:6:20 | @@ -13,7 +27,7 @@ LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ error: literal out of range for `f32` - --> $DIR/lint-type-overflow2.rs:8:14 + --> $DIR/lint-type-overflow2.rs:9:14 | LL | let x = -3.40282357e+38_f32; | ^^^^^^^^^^^^^^^^^^ @@ -21,7 +35,7 @@ LL | let x = -3.40282357e+38_f32; = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY` error: literal out of range for `f32` - --> $DIR/lint-type-overflow2.rs:9:14 + --> $DIR/lint-type-overflow2.rs:10:14 | LL | let x = 3.40282357e+38_f32; | ^^^^^^^^^^^^^^^^^^ @@ -29,7 +43,7 @@ LL | let x = 3.40282357e+38_f32; = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY` error: literal out of range for `f64` - --> $DIR/lint-type-overflow2.rs:10:14 + --> $DIR/lint-type-overflow2.rs:11:14 | LL | let x = -1.7976931348623159e+308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,12 +51,12 @@ LL | let x = -1.7976931348623159e+308_f64; = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY` error: literal out of range for `f64` - --> $DIR/lint-type-overflow2.rs:11:14 + --> $DIR/lint-type-overflow2.rs:12:14 | LL | let x = 1.7976931348623159e+308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY` -error: aborting due to 5 previous errors +error: aborting due to 5 previous errors; 1 warning emitted diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr index 7fe382393d7..78548e308ed 100644 --- a/tests/ui/lint/wide_pointer_comparisons.stderr +++ b/tests/ui/lint/wide_pointer_comparisons.stderr @@ -615,7 +615,7 @@ warning: ambiguous wide pointer comparison, the comparison includes metadata whi --> $DIR/wide_pointer_comparisons.rs:169:37 | LL | ($a:expr, $b:expr) => { $a == $b } - | ^^ + | ^^^^^^^^ ... LL | cmp!(&a, &b); | ------------ in this macro invocation diff --git a/tests/ui/loops/for-each-loop-panic.rs b/tests/ui/loops/for-each-loop-panic.rs index 04784cac8f2..79cfca93e0e 100644 --- a/tests/ui/loops/for-each-loop-panic.rs +++ b/tests/ui/loops/for-each-loop-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:moop -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { for _ in 0_usize..10_usize { diff --git a/tests/ui/macros/assert-as-macro.rs b/tests/ui/macros/assert-as-macro.rs index 391b056292f..c18a3d89fb6 100644 --- a/tests/ui/macros/assert-as-macro.rs +++ b/tests/ui/macros/assert-as-macro.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:assertion failed: 1 == 2 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert!(1 == 2); diff --git a/tests/ui/macros/assert-eq-macro-msg.rs b/tests/ui/macros/assert-eq-macro-msg.rs index 39eeefeeef9..9ef7552cc7b 100644 --- a/tests/ui/macros/assert-eq-macro-msg.rs +++ b/tests/ui/macros/assert-eq-macro-msg.rs @@ -2,7 +2,7 @@ //@ error-pattern:assertion `left == right` failed: 1 + 1 definitely should be 3 //@ error-pattern: left: 2 //@ error-pattern: right: 3 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert_eq!(1 + 1, 3, "1 + 1 definitely should be 3"); diff --git a/tests/ui/macros/assert-eq-macro-panic.rs b/tests/ui/macros/assert-eq-macro-panic.rs index 22c3a8a634f..3c46e2798d1 100644 --- a/tests/ui/macros/assert-eq-macro-panic.rs +++ b/tests/ui/macros/assert-eq-macro-panic.rs @@ -2,7 +2,7 @@ //@ error-pattern:assertion `left == right` failed //@ error-pattern: left: 14 //@ error-pattern: right: 15 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert_eq!(14, 15); diff --git a/tests/ui/macros/assert-macro-explicit.rs b/tests/ui/macros/assert-macro-explicit.rs index 167581d2525..b14a182a876 100644 --- a/tests/ui/macros/assert-macro-explicit.rs +++ b/tests/ui/macros/assert-macro-explicit.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:assertion failed: false -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert!(false); diff --git a/tests/ui/macros/assert-macro-fmt.rs b/tests/ui/macros/assert-macro-fmt.rs index 47554430379..3fd0f472d16 100644 --- a/tests/ui/macros/assert-macro-fmt.rs +++ b/tests/ui/macros/assert-macro-fmt.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern: panicked //@ error-pattern: test-assert-fmt 42 rust -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert!(false, "test-assert-fmt {} {}", 42, "rust"); diff --git a/tests/ui/macros/assert-macro-owned.rs b/tests/ui/macros/assert-macro-owned.rs index 46a59db1390..f9b6f5f5180 100644 --- a/tests/ui/macros/assert-macro-owned.rs +++ b/tests/ui/macros/assert-macro-owned.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:panicked //@ error-pattern:test-assert-owned -//@ ignore-emscripten no processes +//@ needs-subprocess #![allow(non_fmt_panics)] diff --git a/tests/ui/macros/assert-macro-static.rs b/tests/ui/macros/assert-macro-static.rs index 7d9e345d516..8c91d7722fc 100644 --- a/tests/ui/macros/assert-macro-static.rs +++ b/tests/ui/macros/assert-macro-static.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:panicked //@ error-pattern:test-assert-static -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert!(false, "test-assert-static"); diff --git a/tests/ui/macros/assert-matches-macro-msg.rs b/tests/ui/macros/assert-matches-macro-msg.rs index efa4121da92..956bc9cf0f4 100644 --- a/tests/ui/macros/assert-matches-macro-msg.rs +++ b/tests/ui/macros/assert-matches-macro-msg.rs @@ -2,7 +2,7 @@ //@ error-pattern:assertion `left matches right` failed: 1 + 1 definitely should be 3 //@ error-pattern: left: 2 //@ error-pattern: right: 3 -//@ ignore-emscripten no processes +//@ needs-subprocess #![feature(assert_matches)] diff --git a/tests/ui/macros/assert-ne-macro-msg.rs b/tests/ui/macros/assert-ne-macro-msg.rs index 0a578e1baf9..24bc4dbea47 100644 --- a/tests/ui/macros/assert-ne-macro-msg.rs +++ b/tests/ui/macros/assert-ne-macro-msg.rs @@ -2,7 +2,7 @@ //@ error-pattern:assertion `left != right` failed: 1 + 1 definitely should not be 2 //@ error-pattern: left: 2 //@ error-pattern: right: 2 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert_ne!(1 + 1, 2, "1 + 1 definitely should not be 2"); diff --git a/tests/ui/macros/assert-ne-macro-panic.rs b/tests/ui/macros/assert-ne-macro-panic.rs index 9cf5f05e9f1..c349825baf3 100644 --- a/tests/ui/macros/assert-ne-macro-panic.rs +++ b/tests/ui/macros/assert-ne-macro-panic.rs @@ -2,7 +2,7 @@ //@ error-pattern:assertion `left != right` failed //@ error-pattern: left: 14 //@ error-pattern: right: 14 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert_ne!(14, 14); diff --git a/tests/ui/macros/builtin-prelude-no-accidents.rs b/tests/ui/macros/builtin-prelude-no-accidents.rs index 01691a82dd7..9bebcb75526 100644 --- a/tests/ui/macros/builtin-prelude-no-accidents.rs +++ b/tests/ui/macros/builtin-prelude-no-accidents.rs @@ -2,7 +2,7 @@ // because macros with the same names are in prelude. fn main() { - env::current_dir; //~ ERROR use of undeclared crate or module `env` - type A = panic::PanicInfo; //~ ERROR use of undeclared crate or module `panic` - type B = vec::Vec<u8>; //~ ERROR use of undeclared crate or module `vec` + env::current_dir; //~ ERROR use of unresolved module or unlinked crate `env` + type A = panic::PanicInfo; //~ ERROR use of unresolved module or unlinked crate `panic` + type B = vec::Vec<u8>; //~ ERROR use of unresolved module or unlinked crate `vec` } diff --git a/tests/ui/macros/builtin-prelude-no-accidents.stderr b/tests/ui/macros/builtin-prelude-no-accidents.stderr index c1054230bc9..8c7095a6aed 100644 --- a/tests/ui/macros/builtin-prelude-no-accidents.stderr +++ b/tests/ui/macros/builtin-prelude-no-accidents.stderr @@ -1,31 +1,34 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `env` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `env` --> $DIR/builtin-prelude-no-accidents.rs:5:5 | LL | env::current_dir; - | ^^^ use of undeclared crate or module `env` + | ^^^ use of unresolved module or unlinked crate `env` | + = help: you might be missing a crate named `env` help: consider importing this module | LL + use std::env; | -error[E0433]: failed to resolve: use of undeclared crate or module `panic` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `panic` --> $DIR/builtin-prelude-no-accidents.rs:6:14 | LL | type A = panic::PanicInfo; - | ^^^^^ use of undeclared crate or module `panic` + | ^^^^^ use of unresolved module or unlinked crate `panic` | + = help: you might be missing a crate named `panic` help: consider importing this module | LL + use std::panic; | -error[E0433]: failed to resolve: use of undeclared crate or module `vec` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `vec` --> $DIR/builtin-prelude-no-accidents.rs:7:14 | LL | type B = vec::Vec<u8>; - | ^^^ use of undeclared crate or module `vec` + | ^^^ use of unresolved module or unlinked crate `vec` | + = help: you might be missing a crate named `vec` help: consider importing this module | LL + use std::vec; diff --git a/tests/ui/macros/die-macro-2.rs b/tests/ui/macros/die-macro-2.rs index e5456bdfca0..d802f189ce1 100644 --- a/tests/ui/macros/die-macro-2.rs +++ b/tests/ui/macros/die-macro-2.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:test -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!("test"); diff --git a/tests/ui/macros/die-macro-expr.rs b/tests/ui/macros/die-macro-expr.rs index fb92dd66e3d..f4fefb0ca37 100644 --- a/tests/ui/macros/die-macro-expr.rs +++ b/tests/ui/macros/die-macro-expr.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:test -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let __isize: isize = panic!("test"); diff --git a/tests/ui/macros/die-macro-pure.rs b/tests/ui/macros/die-macro-pure.rs index 484eed3d720..d84787705a1 100644 --- a/tests/ui/macros/die-macro-pure.rs +++ b/tests/ui/macros/die-macro-pure.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:test -//@ ignore-emscripten no processes +//@ needs-subprocess fn f() { panic!("test"); diff --git a/tests/ui/macros/macro-inner-attributes.rs b/tests/ui/macros/macro-inner-attributes.rs index 6dbfce21359..a1eb7cd15c4 100644 --- a/tests/ui/macros/macro-inner-attributes.rs +++ b/tests/ui/macros/macro-inner-attributes.rs @@ -15,6 +15,6 @@ test!(b, #[rustc_dummy] fn main() { a::bar(); - //~^ ERROR failed to resolve: use of undeclared crate or module `a` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `a` b::bar(); } diff --git a/tests/ui/macros/macro-inner-attributes.stderr b/tests/ui/macros/macro-inner-attributes.stderr index b6e10f45e38..947e33b08f4 100644 --- a/tests/ui/macros/macro-inner-attributes.stderr +++ b/tests/ui/macros/macro-inner-attributes.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `a` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `a` --> $DIR/macro-inner-attributes.rs:17:5 | LL | a::bar(); - | ^ use of undeclared crate or module `a` + | ^ use of unresolved module or unlinked crate `a` | help: there is a crate or module with a similar name | diff --git a/tests/ui/macros/macro-span-issue-116502.stderr b/tests/ui/macros/macro-span-issue-116502.stderr index da02855660a..2a581f7031b 100644 --- a/tests/ui/macros/macro-span-issue-116502.stderr +++ b/tests/ui/macros/macro-span-issue-116502.stderr @@ -17,13 +17,6 @@ LL | T: Trait<m!()>; | ---- in this macro invocation | = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use type parameters instead - | -LL ~ U -LL | }; -LL | } -LL ~ struct S<U>(m!(), T) - | error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro_path_as_generic_bound.stderr b/tests/ui/macros/macro_path_as_generic_bound.stderr index e25ff57e57f..9fe4ad27aa0 100644 --- a/tests/ui/macros/macro_path_as_generic_bound.stderr +++ b/tests/ui/macros/macro_path_as_generic_bound.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `m` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `m` --> $DIR/macro_path_as_generic_bound.rs:7:6 | LL | foo!(m::m2::A); - | ^ use of undeclared crate or module `m` + | ^ use of unresolved module or unlinked crate `m` + | + = help: you might be missing a crate named `m` error: aborting due to 1 previous error diff --git a/tests/ui/macros/meta-item-absolute-path.stderr b/tests/ui/macros/meta-item-absolute-path.stderr index af56d935284..8fa5e97899c 100644 --- a/tests/ui/macros/meta-item-absolute-path.stderr +++ b/tests/ui/macros/meta-item-absolute-path.stderr @@ -1,14 +1,14 @@ -error[E0433]: failed to resolve: you might be missing crate `Absolute` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `Absolute` --> $DIR/meta-item-absolute-path.rs:1:12 | LL | #[derive(::Absolute)] - | ^^^^^^^^ you might be missing crate `Absolute` + | ^^^^^^^^ use of unresolved module or unlinked crate `Absolute` -error[E0433]: failed to resolve: you might be missing crate `Absolute` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `Absolute` --> $DIR/meta-item-absolute-path.rs:1:12 | LL | #[derive(::Absolute)] - | ^^^^^^^^ you might be missing crate `Absolute` + | ^^^^^^^^ use of unresolved module or unlinked crate `Absolute` | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/macros/not-utf8.rs b/tests/ui/macros/not-utf8.rs index 8100d65a9f8..ad8ac39d230 100644 --- a/tests/ui/macros/not-utf8.rs +++ b/tests/ui/macros/not-utf8.rs @@ -3,5 +3,5 @@ //@ reference: input.encoding.invalid fn foo() { - include!("not-utf8.bin") + include!("not-utf8.bin"); } diff --git a/tests/ui/macros/not-utf8.stderr b/tests/ui/macros/not-utf8.stderr index 0d587cab5f3..17ee8197ac8 100644 --- a/tests/ui/macros/not-utf8.stderr +++ b/tests/ui/macros/not-utf8.stderr @@ -1,9 +1,14 @@ -error: couldn't read $DIR/not-utf8.bin: stream did not contain valid UTF-8 +error: couldn't read `$DIR/not-utf8.bin`: stream did not contain valid UTF-8 --> $DIR/not-utf8.rs:6:5 | -LL | include!("not-utf8.bin") +LL | include!("not-utf8.bin"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | +note: byte `193` is not valid utf-8 + --> $DIR/not-utf8.bin:1:1 + | +LL | �|�␂!5�cc␕␂�Ӻi��WWj�ȥ�'�}�␒�J�ȉ��W�␞O�@����␜w�V���LO����␔[ ␃_�'���SQ�~ذ��ų&��- ��lN~��!@␌ _#���kQ��h�␝�:�... + | ^ = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs index 37d94830db2..2a27164f9cb 100644 --- a/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs @@ -1,4 +1,6 @@ -//@ compile-flags: --test +// -Zpanic_abort_tests makes this test work on panic=abort targets and +// it's a no-op on panic=unwind targets +//@ compile-flags: --test -Zpanic_abort_tests //@ run-pass #![feature(core_intrinsics, generic_assert)] diff --git a/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs b/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs index 86cc7adb90d..254d59076e5 100644 --- a/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs +++ b/tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs @@ -1,4 +1,6 @@ -//@ compile-flags: --test +// -Zpanic_abort_tests makes this test work on panic=abort targets and +// it's a no-op on panic=unwind targets +//@ compile-flags: --test -Zpanic_abort_tests // ignore-tidy-linelength //@ run-pass diff --git a/tests/ui/macros/unimplemented-macro-panic.rs b/tests/ui/macros/unimplemented-macro-panic.rs index d3bff8ca10b..804bd61270e 100644 --- a/tests/ui/macros/unimplemented-macro-panic.rs +++ b/tests/ui/macros/unimplemented-macro-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:not implemented -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { unimplemented!() diff --git a/tests/ui/macros/unreachable-arg.rs b/tests/ui/macros/unreachable-arg.rs index 1f0d0073486..702bd053ab0 100644 --- a/tests/ui/macros/unreachable-arg.rs +++ b/tests/ui/macros/unreachable-arg.rs @@ -1,4 +1,4 @@ -//@ ignore-emscripten no processes +//@ needs-subprocess //@ revisions: edition_2015 edition_2021 //@ [edition_2015]edition:2015 diff --git a/tests/ui/macros/unreachable-fmt-msg.rs b/tests/ui/macros/unreachable-fmt-msg.rs index b16394a1920..928e0a427ae 100644 --- a/tests/ui/macros/unreachable-fmt-msg.rs +++ b/tests/ui/macros/unreachable-fmt-msg.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:internal error: entered unreachable code: 6 is not prime -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { unreachable!("{} is not {}", 6u32, "prime"); diff --git a/tests/ui/macros/unreachable-format-arg.rs b/tests/ui/macros/unreachable-format-arg.rs index 449c6bca16b..e1fdab25a43 100644 --- a/tests/ui/macros/unreachable-format-arg.rs +++ b/tests/ui/macros/unreachable-format-arg.rs @@ -1,5 +1,5 @@ //@ run-fail -//@ ignore-emscripten no processes +//@ needs-subprocess //@ revisions: edition_2015 edition_2021 //@ [edition_2015]edition:2015 diff --git a/tests/ui/macros/unreachable-format-args.rs b/tests/ui/macros/unreachable-format-args.rs index 5f8a0e9cdff..856fc992685 100644 --- a/tests/ui/macros/unreachable-format-args.rs +++ b/tests/ui/macros/unreachable-format-args.rs @@ -1,4 +1,4 @@ -//@ ignore-emscripten no processes +//@ needs-subprocess //@ revisions: edition_2015 edition_2021 //@ [edition_2015]edition:2015 diff --git a/tests/ui/macros/unreachable-macro-panic.rs b/tests/ui/macros/unreachable-macro-panic.rs index 7909bcb7624..c5cea5551cf 100644 --- a/tests/ui/macros/unreachable-macro-panic.rs +++ b/tests/ui/macros/unreachable-macro-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:internal error: entered unreachable code -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { unreachable!() diff --git a/tests/ui/macros/unreachable-static-msg.rs b/tests/ui/macros/unreachable-static-msg.rs index 3e917897da4..a85f8962e7d 100644 --- a/tests/ui/macros/unreachable-static-msg.rs +++ b/tests/ui/macros/unreachable-static-msg.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:internal error: entered unreachable code: uhoh -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { unreachable!("uhoh") diff --git a/tests/ui/macros/unreachable.rs b/tests/ui/macros/unreachable.rs index 7909bcb7624..c5cea5551cf 100644 --- a/tests/ui/macros/unreachable.rs +++ b/tests/ui/macros/unreachable.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:internal error: entered unreachable code -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { unreachable!() diff --git a/tests/ui/match/expr-match-panic-fn.rs b/tests/ui/match/expr-match-panic-fn.rs index 82991d20df8..a07c2c6af8f 100644 --- a/tests/ui/match/expr-match-panic-fn.rs +++ b/tests/ui/match/expr-match-panic-fn.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn f() -> ! { panic!() diff --git a/tests/ui/match/expr-match-panic.rs b/tests/ui/match/expr-match-panic.rs index e332ba83b91..d15b0a9cd72 100644 --- a/tests/ui/match/expr-match-panic.rs +++ b/tests/ui/match/expr-match-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let _x = match true { diff --git a/tests/ui/match/match-bot-panic.rs b/tests/ui/match/match-bot-panic.rs index a155b5fb3f2..7ec07ae290d 100644 --- a/tests/ui/match/match-bot-panic.rs +++ b/tests/ui/match/match-bot-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess #![allow(unreachable_code)] #![allow(unused_variables)] diff --git a/tests/ui/match/match-disc-bot.rs b/tests/ui/match/match-disc-bot.rs index fdb98a0accb..d65dc5aea07 100644 --- a/tests/ui/match/match-disc-bot.rs +++ b/tests/ui/match/match-disc-bot.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:quux -//@ ignore-emscripten no processes +//@ needs-subprocess fn f() -> ! { panic!("quux") diff --git a/tests/ui/match/match-wildcards.rs b/tests/ui/match/match-wildcards.rs index 4fddee6666e..1cc81a7c415 100644 --- a/tests/ui/match/match-wildcards.rs +++ b/tests/ui/match/match-wildcards.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:squirrelcupcake -//@ ignore-emscripten no processes +//@ needs-subprocess fn cmp() -> isize { match (Some('a'), None::<char>) { diff --git a/tests/ui/meta/revision-ok.rs b/tests/ui/meta/revision-ok.rs index c1387f7d18e..430d3d0a239 100644 --- a/tests/ui/meta/revision-ok.rs +++ b/tests/ui/meta/revision-ok.rs @@ -5,7 +5,7 @@ //@ revisions: foo bar //@[foo] error-pattern:foo //@[bar] error-pattern:bar -//@ ignore-emscripten no processes +//@ needs-subprocess #[cfg(foo)] fn die() { diff --git a/tests/ui/mir/issue-121103.rs b/tests/ui/mir/issue-121103.rs index e06361a6964..247c644c5bb 100644 --- a/tests/ui/mir/issue-121103.rs +++ b/tests/ui/mir/issue-121103.rs @@ -1,3 +1,3 @@ fn main(_: <lib2::GenericType<42> as lib2::TypeFn>::Output) {} -//~^ ERROR failed to resolve: use of undeclared crate or module `lib2` -//~| ERROR failed to resolve: use of undeclared crate or module `lib2` +//~^ ERROR failed to resolve: use of unresolved module or unlinked crate `lib2` +//~| ERROR failed to resolve: use of unresolved module or unlinked crate `lib2` diff --git a/tests/ui/mir/issue-121103.stderr b/tests/ui/mir/issue-121103.stderr index 913eee9e0c5..3565f6f0cde 100644 --- a/tests/ui/mir/issue-121103.stderr +++ b/tests/ui/mir/issue-121103.stderr @@ -1,14 +1,18 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `lib2` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `lib2` --> $DIR/issue-121103.rs:1:38 | LL | fn main(_: <lib2::GenericType<42> as lib2::TypeFn>::Output) {} - | ^^^^ use of undeclared crate or module `lib2` + | ^^^^ use of unresolved module or unlinked crate `lib2` + | + = help: you might be missing a crate named `lib2` -error[E0433]: failed to resolve: use of undeclared crate or module `lib2` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `lib2` --> $DIR/issue-121103.rs:1:13 | LL | fn main(_: <lib2::GenericType<42> as lib2::TypeFn>::Output) {} - | ^^^^ use of undeclared crate or module `lib2` + | ^^^^ use of unresolved module or unlinked crate `lib2` + | + = help: you might be missing a crate named `lib2` error: aborting due to 2 previous errors diff --git a/tests/ui/mir/mir_codegen_calls_converging_drops.rs b/tests/ui/mir/mir_codegen_calls_converging_drops.rs index 5c3c8b999b2..8a6d3926de2 100644 --- a/tests/ui/mir/mir_codegen_calls_converging_drops.rs +++ b/tests/ui/mir/mir_codegen_calls_converging_drops.rs @@ -2,7 +2,7 @@ //@ error-pattern:converging_fn called //@ error-pattern:0 dropped //@ error-pattern:exit -//@ ignore-emscripten no processes +//@ needs-subprocess struct Droppable(u8); impl Drop for Droppable { diff --git a/tests/ui/mir/mir_codegen_calls_converging_drops_2.rs b/tests/ui/mir/mir_codegen_calls_converging_drops_2.rs index e3cb9a96de0..e89fbc58a0d 100644 --- a/tests/ui/mir/mir_codegen_calls_converging_drops_2.rs +++ b/tests/ui/mir/mir_codegen_calls_converging_drops_2.rs @@ -2,7 +2,7 @@ //@ error-pattern:complex called //@ error-pattern:dropped //@ error-pattern:exit -//@ ignore-emscripten no processes +//@ needs-subprocess struct Droppable; impl Drop for Droppable { diff --git a/tests/ui/mir/mir_codegen_calls_diverging.rs b/tests/ui/mir/mir_codegen_calls_diverging.rs index c62527f01d3..ce2d7140b07 100644 --- a/tests/ui/mir/mir_codegen_calls_diverging.rs +++ b/tests/ui/mir/mir_codegen_calls_diverging.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:diverging_fn called -//@ ignore-emscripten no processes +//@ needs-subprocess fn diverging_fn() -> ! { panic!("diverging_fn called") diff --git a/tests/ui/mir/mir_dynamic_drops_1.rs b/tests/ui/mir/mir_dynamic_drops_1.rs index ffb8cc26100..0b0a3960574 100644 --- a/tests/ui/mir/mir_dynamic_drops_1.rs +++ b/tests/ui/mir/mir_dynamic_drops_1.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:drop 1 //@ error-pattern:drop 2 -//@ ignore-emscripten no processes +//@ needs-subprocess /// Structure which will not allow to be dropped twice. struct Droppable<'a>(&'a mut bool, u32); diff --git a/tests/ui/mir/mir_dynamic_drops_2.rs b/tests/ui/mir/mir_dynamic_drops_2.rs index dc71f414673..f625f19be26 100644 --- a/tests/ui/mir/mir_dynamic_drops_2.rs +++ b/tests/ui/mir/mir_dynamic_drops_2.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:drop 1 -//@ ignore-emscripten no processes +//@ needs-subprocess /// Structure which will not allow to be dropped twice. struct Droppable<'a>(&'a mut bool, u32); diff --git a/tests/ui/mir/mir_dynamic_drops_3.rs b/tests/ui/mir/mir_dynamic_drops_3.rs index fe84502ef1d..2a8af4ce1fb 100644 --- a/tests/ui/mir/mir_dynamic_drops_3.rs +++ b/tests/ui/mir/mir_dynamic_drops_3.rs @@ -4,7 +4,7 @@ //@ error-pattern:drop 3 //@ error-pattern:drop 2 //@ error-pattern:drop 1 -//@ ignore-emscripten no processes +//@ needs-subprocess /// Structure which will not allow to be dropped twice. struct Droppable<'a>(&'a mut bool, u32); diff --git a/tests/ui/mir/mir_indexing_oob_1.rs b/tests/ui/mir/mir_indexing_oob_1.rs index 3afc2f0b32e..936484b0c1e 100644 --- a/tests/ui/mir/mir_indexing_oob_1.rs +++ b/tests/ui/mir/mir_indexing_oob_1.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:index out of bounds: the len is 5 but the index is 10 -//@ ignore-emscripten no processes +//@ needs-subprocess const C: [u32; 5] = [0; 5]; diff --git a/tests/ui/mir/mir_indexing_oob_2.rs b/tests/ui/mir/mir_indexing_oob_2.rs index 6e7c1c83536..310a7f8f2b7 100644 --- a/tests/ui/mir/mir_indexing_oob_2.rs +++ b/tests/ui/mir/mir_indexing_oob_2.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:index out of bounds: the len is 5 but the index is 10 -//@ ignore-emscripten no processes +//@ needs-subprocess const C: &'static [u8; 5] = b"hello"; diff --git a/tests/ui/mir/mir_indexing_oob_3.rs b/tests/ui/mir/mir_indexing_oob_3.rs index 4012864c6ce..44b3a2c5a6d 100644 --- a/tests/ui/mir/mir_indexing_oob_3.rs +++ b/tests/ui/mir/mir_indexing_oob_3.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:index out of bounds: the len is 5 but the index is 10 -//@ ignore-emscripten no processes +//@ needs-subprocess const C: &'static [u8; 5] = b"hello"; diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed new file mode 100644 index 00000000000..7383ab177dc --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed @@ -0,0 +1,12 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[current] run-rustfix +fn main() { + let _ = (-10..=10).find(|x: &i32| x.signum() == 0); + //[current]~^ ERROR type mismatch in closure arguments + //[next]~^^ ERROR expected a `FnMut(&<RangeInclusive<{integer}> as Iterator>::Item)` closure, found + let _ = (-10..=10).find(|x: &i32| x.signum() == 0); + //[current]~^ ERROR type mismatch in closure arguments + //[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}` +} diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr index e52e095e9f7..c35d70a635c 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.stderr @@ -1,5 +1,5 @@ error[E0631]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:3:24 + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:24 | LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); | ^^^^ -------- found signature defined here @@ -16,7 +16,7 @@ LL | let _ = (-10..=10).find(|x: &i32| x.signum() == 0); | + error[E0631]: type mismatch in closure arguments - --> $DIR/closure-arg-type-mismatch-issue-45727.rs:4:24 + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:24 | LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); | ^^^^ ----------- found signature defined here diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed deleted file mode 100644 index e6e3e1551e9..00000000000 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.fixed +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-rustfix -fn main() { - let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments - let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments -} diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr new file mode 100644 index 00000000000..6104a089337 --- /dev/null +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr @@ -0,0 +1,24 @@ +error[E0277]: expected a `FnMut(&<RangeInclusive<{integer}> as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}` + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:29 + | +LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&<RangeInclusive<{integer}> as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}` + | | + | required by a bound introduced by this call + | + = help: the trait `for<'a> FnMut(&'a <RangeInclusive<{integer}> as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}` + = note: expected a closure with arguments `(i32,)` + found a closure with arguments `(&<RangeInclusive<{integer}> as Iterator>::Item,)` +note: required by a bound in `find` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + +error[E0271]: expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}` + --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:33 + | +LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); + | ^^^^^^ expected `&&i32`, found integer + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs index 64e815606d4..668a1a7a29c 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs @@ -1,5 +1,12 @@ -//@ run-rustfix +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[current] run-rustfix fn main() { - let _ = (-10..=10).find(|x: i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments - let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments + let _ = (-10..=10).find(|x: i32| x.signum() == 0); + //[current]~^ ERROR type mismatch in closure arguments + //[next]~^^ ERROR expected a `FnMut(&<RangeInclusive<{integer}> as Iterator>::Item)` closure, found + let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); + //[current]~^ ERROR type mismatch in closure arguments + //[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}` } diff --git a/tests/ui/modules/path-no-file-name.rs b/tests/ui/modules/path-no-file-name.rs index 23127346e02..753a0950123 100644 --- a/tests/ui/modules/path-no-file-name.rs +++ b/tests/ui/modules/path-no-file-name.rs @@ -1,4 +1,4 @@ -//@ normalize-stderr: "\.:.*\(" -> ".: $$ACCESS_DENIED_MSG (" +//@ normalize-stderr: "\.`:.*\(" -> ".`: $$ACCESS_DENIED_MSG (" //@ normalize-stderr: "os error \d+" -> "os error $$ACCESS_DENIED_CODE" #[path = "."] diff --git a/tests/ui/modules/path-no-file-name.stderr b/tests/ui/modules/path-no-file-name.stderr index 834e8ea6b03..6274ecfed13 100644 --- a/tests/ui/modules/path-no-file-name.stderr +++ b/tests/ui/modules/path-no-file-name.stderr @@ -1,4 +1,4 @@ -error: couldn't read $DIR/.: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) +error: couldn't read `$DIR/.`: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) --> $DIR/path-no-file-name.rs:5:1 | LL | mod m; diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig.rs b/tests/ui/modules_and_files_visibility/mod_file_disambig.rs index e5958af173b..1483e3e4630 100644 --- a/tests/ui/modules_and_files_visibility/mod_file_disambig.rs +++ b/tests/ui/modules_and_files_visibility/mod_file_disambig.rs @@ -2,5 +2,5 @@ mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` fou fn main() { assert_eq!(mod_file_aux::bar(), 10); - //~^ ERROR failed to resolve: use of undeclared crate or module `mod_file_aux` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `mod_file_aux` } diff --git a/tests/ui/modules_and_files_visibility/mod_file_disambig.stderr b/tests/ui/modules_and_files_visibility/mod_file_disambig.stderr index a2c99396987..f82d613015f 100644 --- a/tests/ui/modules_and_files_visibility/mod_file_disambig.stderr +++ b/tests/ui/modules_and_files_visibility/mod_file_disambig.stderr @@ -6,11 +6,13 @@ LL | mod mod_file_disambig_aux; | = help: delete or rename one of them to remove the ambiguity -error[E0433]: failed to resolve: use of undeclared crate or module `mod_file_aux` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `mod_file_aux` --> $DIR/mod_file_disambig.rs:4:16 | LL | assert_eq!(mod_file_aux::bar(), 10); - | ^^^^^^^^^^^^ use of undeclared crate or module `mod_file_aux` + | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `mod_file_aux` + | + = help: you might be missing a crate named `mod_file_aux` error: aborting due to 2 previous errors diff --git a/tests/ui/never_type/return-never-coerce.rs b/tests/ui/never_type/return-never-coerce.rs index 559b7d0e985..14f07dfeb76 100644 --- a/tests/ui/never_type/return-never-coerce.rs +++ b/tests/ui/never_type/return-never-coerce.rs @@ -2,7 +2,7 @@ //@ run-fail //@ error-pattern:aah! -//@ ignore-emscripten no processes +//@ needs-subprocess fn call_another_fn<T, F: FnOnce() -> T>(f: F) -> T { f() diff --git a/tests/ui/nll/get_default.polonius.stderr b/tests/ui/nll/get_default.polonius.stderr deleted file mode 100644 index 613d06cce91..00000000000 --- a/tests/ui/nll/get_default.polonius.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable - --> $DIR/get_default.rs:32:17 - | -LL | fn err(map: &mut Map) -> &String { - | - let's call the lifetime of this reference `'1` -LL | loop { -LL | match map.get() { - | --- immutable borrow occurs here -LL | Some(v) => { -LL | map.set(String::new()); // Both AST and MIR error here - | ^^^ mutable borrow occurs here -LL | -LL | return v; - | - returning this value requires that `*map` is borrowed for `'1` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0502`. diff --git a/tests/ui/nll/issue-51345-2.rs b/tests/ui/nll/issue-51345-2.rs index f2501fdbab4..39871d56a9a 100644 --- a/tests/ui/nll/issue-51345-2.rs +++ b/tests/ui/nll/issue-51345-2.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'main' panicked //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let mut vec = vec![]; diff --git a/tests/ui/nll/outlives-suggestion-simple.polonius.stderr b/tests/ui/nll/outlives-suggestion-simple.polonius.stderr deleted file mode 100644 index c00288f2e3c..00000000000 --- a/tests/ui/nll/outlives-suggestion-simple.polonius.stderr +++ /dev/null @@ -1,124 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:6:5 - | -LL | fn foo1<'a, 'b>(x: &'a usize) -> &'b usize { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | x - | ^ returning this value requires that `'a` must outlive `'b` - | - = help: consider adding the following bound: `'a: 'b` - -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:10:5 - | -LL | fn foo2<'a>(x: &'a usize) -> &'static usize { - | -- lifetime `'a` defined here -LL | x - | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` - -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:14:5 - | -LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | (x, y) - | ^^^^^^ function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` - | - = help: consider adding the following bound: `'a: 'b` - -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:14:5 - | -LL | fn foo3<'a, 'b>(x: &'a usize, y: &'b usize) -> (&'b usize, &'a usize) { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -LL | (x, y) - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` - | - = help: consider adding the following bound: `'b: 'a` - -help: `'a` and `'b` must be the same: replace one with the other - -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:22:5 - | -LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | (x, x) - | ^^^^^^ returning this value requires that `'a` must outlive `'b` - | - = help: consider adding the following bound: `'a: 'b` - -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:22:5 - | -LL | fn foo4<'a, 'b, 'c>(x: &'a usize) -> (&'b usize, &'c usize) { - | -- -- lifetime `'c` defined here - | | - | lifetime `'a` defined here -... -LL | (x, x) - | ^^^^^^ returning this value requires that `'a` must outlive `'c` - | - = help: consider adding the following bound: `'a: 'c` - -help: add bound `'a: 'b + 'c` - -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:31:9 - | -LL | pub fn foo<'a>(x: &'a usize) -> Self { - | -- lifetime `'a` defined here -LL | Foo { x } - | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` - -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:41:9 - | -LL | impl<'a> Bar<'a> { - | -- lifetime `'a` defined here -LL | pub fn get<'b>(&self) -> &'b usize { - | -- lifetime `'b` defined here -LL | self.x - | ^^^^^^ returning this value requires that `'a` must outlive `'b` - | - = help: consider adding the following bound: `'a: 'b` - -error: lifetime may not live long enough - --> $DIR/outlives-suggestion-simple.rs:52:9 - | -LL | impl<'a> Baz<'a> { - | -- lifetime `'a` defined here -LL | fn get<'b>(&'b self) -> &'a i32 { - | -- lifetime `'b` defined here -LL | self.x - | ^^^^^^ returning this value requires that `'b` must outlive `'a` - | - = help: consider adding the following bound: `'b: 'a` - -error[E0521]: borrowed data escapes outside of associated function - --> $DIR/outlives-suggestion-simple.rs:73:9 - | -LL | fn get_bar(&self) -> Bar2 { - | ----- - | | - | `self` declared here, outside of the associated function body - | `self` is a reference that is only valid in the associated function body -LL | Bar2::new(&self) - | ^^^^^^^^^^^^^^^^ `self` escapes the associated function body here - -error: aborting due to 10 previous errors - -For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/user-annotations/closure-substs.polonius.stderr b/tests/ui/nll/user-annotations/closure-substs.polonius.stderr deleted file mode 100644 index af159a6cd1b..00000000000 --- a/tests/ui/nll/user-annotations/closure-substs.polonius.stderr +++ /dev/null @@ -1,61 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/closure-substs.rs:8:16 - | -LL | fn foo<'a>() { - | -- lifetime `'a` defined here -... -LL | return x; - | ^ returning this value requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` - -error: lifetime may not live long enough - --> $DIR/closure-substs.rs:15:16 - | -LL | |x: &i32| -> &'static i32 { - | - let's call the lifetime of this reference `'1` -LL | return x; - | ^ returning this value requires that `'1` must outlive `'static` - -error: lifetime may not live long enough - --> $DIR/closure-substs.rs:15:16 - | -LL | |x: &i32| -> &'static i32 { - | - - let's call the lifetime of this reference `'2` - | | - | let's call the lifetime of this reference `'1` -LL | return x; - | ^ returning this value requires that `'1` must outlive `'2` - -error: lifetime may not live long enough - --> $DIR/closure-substs.rs:22:9 - | -LL | fn bar<'a>() { - | -- lifetime `'a` defined here -... -LL | b(x); - | ^^^^ argument requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` - -error[E0521]: borrowed data escapes outside of closure - --> $DIR/closure-substs.rs:29:9 - | -LL | |x: &i32, b: fn(&'static i32)| { - | - `x` is a reference that is only valid in the closure body -LL | b(x); - | ^^^^ `x` escapes the closure body here - -error[E0521]: borrowed data escapes outside of closure - --> $DIR/closure-substs.rs:29:9 - | -LL | |x: &i32, b: fn(&'static i32)| { - | - - `b` declared here, outside of the closure body - | | - | `x` is a reference that is only valid in the closure body -LL | b(x); - | ^^^^ `x` escapes the closure body here - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/numbers-arithmetic/divide-by-zero.rs b/tests/ui/numbers-arithmetic/divide-by-zero.rs index 626daf9771d..a05abadf4bb 100644 --- a/tests/ui/numbers-arithmetic/divide-by-zero.rs +++ b/tests/ui/numbers-arithmetic/divide-by-zero.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:attempt to divide by zero -//@ ignore-emscripten no processes +//@ needs-subprocess #[allow(unconditional_panic)] fn main() { diff --git a/tests/ui/numbers-arithmetic/int-abs-overflow.rs b/tests/ui/numbers-arithmetic/int-abs-overflow.rs index e9114138048..6397f62d065 100644 --- a/tests/ui/numbers-arithmetic/int-abs-overflow.rs +++ b/tests/ui/numbers-arithmetic/int-abs-overflow.rs @@ -1,6 +1,6 @@ //@ run-pass //@ compile-flags: -C overflow-checks=on -//@ ignore-emscripten no threads support +//@ needs-threads //@ needs-unwind use std::thread; diff --git a/tests/ui/numbers-arithmetic/issue-8460.rs b/tests/ui/numbers-arithmetic/issue-8460.rs index 9d3044a7ca0..87867fdc93e 100644 --- a/tests/ui/numbers-arithmetic/issue-8460.rs +++ b/tests/ui/numbers-arithmetic/issue-8460.rs @@ -1,6 +1,6 @@ //@ run-pass #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads //@ needs-unwind #![feature(rustc_attrs)] diff --git a/tests/ui/numbers-arithmetic/mod-zero.rs b/tests/ui/numbers-arithmetic/mod-zero.rs index f3cc7c9fc88..300bd765c40 100644 --- a/tests/ui/numbers-arithmetic/mod-zero.rs +++ b/tests/ui/numbers-arithmetic/mod-zero.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:attempt to calculate the remainder with a divisor of zero -//@ ignore-emscripten no processes +//@ needs-subprocess #[allow(unconditional_panic)] fn main() { diff --git a/tests/ui/numbers-arithmetic/overflowing-add.rs b/tests/ui/numbers-arithmetic/overflowing-add.rs index 16583f6eb74..c1f498c802b 100644 --- a/tests/ui/numbers-arithmetic/overflowing-add.rs +++ b/tests/ui/numbers-arithmetic/overflowing-add.rs @@ -2,7 +2,7 @@ //@ error-pattern:thread 'main' panicked //@ error-pattern:attempt to add with overflow //@ compile-flags: -C debug-assertions -//@ ignore-emscripten no processes +//@ needs-subprocess #![allow(arithmetic_overflow)] diff --git a/tests/ui/numbers-arithmetic/overflowing-mul.rs b/tests/ui/numbers-arithmetic/overflowing-mul.rs index 59575d2e86e..0eece536929 100644 --- a/tests/ui/numbers-arithmetic/overflowing-mul.rs +++ b/tests/ui/numbers-arithmetic/overflowing-mul.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'main' panicked //@ error-pattern:attempt to multiply with overflow -//@ ignore-emscripten no processes +//@ needs-subprocess //@ compile-flags: -C debug-assertions #![allow(arithmetic_overflow)] diff --git a/tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs b/tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs index 8aa0d04e500..c5059c002b4 100644 --- a/tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs +++ b/tests/ui/numbers-arithmetic/overflowing-neg-nonzero.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:attempt to negate with overflow -//@ ignore-emscripten no processes +//@ needs-subprocess //@ compile-flags: -C debug-assertions #![allow(arithmetic_overflow)] diff --git a/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs b/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs index 69e22c2262a..28deb7cf6ba 100644 --- a/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs +++ b/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'main' panicked //@ error-pattern:attempt to multiply with overflow -//@ ignore-emscripten no processes +//@ needs-subprocess //@ compile-flags: -C debug-assertions fn main() { diff --git a/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs b/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs index f980033c480..dea9a4d5428 100644 --- a/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs +++ b/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'main' panicked //@ error-pattern:attempt to multiply with overflow -//@ ignore-emscripten no processes +//@ needs-subprocess //@ compile-flags: -C debug-assertions fn main() { diff --git a/tests/ui/numbers-arithmetic/overflowing-sub.rs b/tests/ui/numbers-arithmetic/overflowing-sub.rs index 44aadf6b3e7..88b1b693f63 100644 --- a/tests/ui/numbers-arithmetic/overflowing-sub.rs +++ b/tests/ui/numbers-arithmetic/overflowing-sub.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'main' panicked //@ error-pattern:attempt to subtract with overflow -//@ ignore-emscripten no processes +//@ needs-subprocess //@ compile-flags: -C debug-assertions #![allow(arithmetic_overflow)] diff --git a/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs b/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs index ce6644e6758..0566d2319df 100644 --- a/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs +++ b/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs @@ -1,10 +1,8 @@ //@ run-pass -#![allow(unused_variables)] //@ compile-flags:-C panic=abort //@ aux-build:exit-success-if-unwind.rs //@ no-prefer-dynamic -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess extern crate exit_success_if_unwind; @@ -13,7 +11,7 @@ use std::process::Command; fn main() { let mut args = env::args_os(); - let me = args.next().unwrap(); + let _ = args.next().unwrap(); if let Some(s) = args.next() { if &*s == "foo" { diff --git a/tests/ui/panic-runtime/abort.rs b/tests/ui/panic-runtime/abort.rs index caf0243ebdb..8cdfd018a92 100644 --- a/tests/ui/panic-runtime/abort.rs +++ b/tests/ui/panic-runtime/abort.rs @@ -1,9 +1,7 @@ //@ run-pass -#![allow(unused_variables)] //@ compile-flags:-C panic=abort //@ no-prefer-dynamic -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; use std::process::Command; @@ -18,7 +16,7 @@ impl Drop for Bomb { fn main() { let mut args = env::args_os(); - let me = args.next().unwrap(); + let _ = args.next().unwrap(); if let Some(s) = args.next() { if &*s == "foo" { diff --git a/tests/ui/panic-runtime/lto-abort.rs b/tests/ui/panic-runtime/lto-abort.rs index c66b6a60c73..cf15ae6435b 100644 --- a/tests/ui/panic-runtime/lto-abort.rs +++ b/tests/ui/panic-runtime/lto-abort.rs @@ -1,9 +1,7 @@ //@ run-pass -#![allow(unused_variables)] //@ compile-flags:-C lto -C panic=abort //@ no-prefer-dynamic -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::process::Command; use std::env; @@ -18,7 +16,7 @@ impl Drop for Bomb { fn main() { let mut args = env::args_os(); - let me = args.next().unwrap(); + let _ = args.next().unwrap(); if let Some(s) = args.next() { if &*s == "foo" { diff --git a/tests/ui/panic-runtime/lto-unwind.rs b/tests/ui/panic-runtime/lto-unwind.rs index 5eab2bd56ed..93275052f85 100644 --- a/tests/ui/panic-runtime/lto-unwind.rs +++ b/tests/ui/panic-runtime/lto-unwind.rs @@ -1,11 +1,8 @@ //@ run-pass -#![allow(unused_variables)] - //@ compile-flags:-C lto -C panic=unwind //@ needs-unwind //@ no-prefer-dynamic -//@ ignore-emscripten no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::process::Command; use std::env; @@ -20,7 +17,7 @@ impl Drop for Bomb { fn main() { let mut args = env::args_os(); - let me = args.next().unwrap(); + let _ = args.next().unwrap(); if let Some(s) = args.next() { if &*s == "foo" { diff --git a/tests/ui/panic-runtime/unwind-interleaved.rs b/tests/ui/panic-runtime/unwind-interleaved.rs index e5505cd893a..83eb6365097 100644 --- a/tests/ui/panic-runtime/unwind-interleaved.rs +++ b/tests/ui/panic-runtime/unwind-interleaved.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn a() {} diff --git a/tests/ui/panic-runtime/unwind-rec.rs b/tests/ui/panic-runtime/unwind-rec.rs index d4b53c88768..a855a4de280 100644 --- a/tests/ui/panic-runtime/unwind-rec.rs +++ b/tests/ui/panic-runtime/unwind-rec.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn build() -> Vec<isize> { panic!(); diff --git a/tests/ui/panic-runtime/unwind-rec2.rs b/tests/ui/panic-runtime/unwind-rec2.rs index 6ac9a5a5805..ed02b117fff 100644 --- a/tests/ui/panic-runtime/unwind-rec2.rs +++ b/tests/ui/panic-runtime/unwind-rec2.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn build1() -> Vec<isize> { vec![0, 0, 0, 0, 0, 0, 0] diff --git a/tests/ui/panic-runtime/unwind-unique.rs b/tests/ui/panic-runtime/unwind-unique.rs index a6cd59690ca..b57d81842c4 100644 --- a/tests/ui/panic-runtime/unwind-unique.rs +++ b/tests/ui/panic-runtime/unwind-unique.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn failfn() { panic!(); diff --git a/tests/ui/panics/abort-on-panic.rs b/tests/ui/panics/abort-on-panic.rs index feccefb2537..d3bf087bd3e 100644 --- a/tests/ui/panics/abort-on-panic.rs +++ b/tests/ui/panics/abort-on-panic.rs @@ -8,8 +8,7 @@ // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that // we never unwind through them. -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::io; use std::io::prelude::*; diff --git a/tests/ui/panics/args-panic.rs b/tests/ui/panics/args-panic.rs index 091ced9b479..9675c99dcb6 100644 --- a/tests/ui/panics/args-panic.rs +++ b/tests/ui/panics/args-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:meep -//@ ignore-emscripten no processes +//@ needs-subprocess fn f(_a: isize, _b: isize, _c: Box<isize>) { panic!("moop"); diff --git a/tests/ui/panics/doublepanic.rs b/tests/ui/panics/doublepanic.rs index 51945ea708c..6fddde82a27 100644 --- a/tests/ui/panics/doublepanic.rs +++ b/tests/ui/panics/doublepanic.rs @@ -2,7 +2,7 @@ //@ run-fail //@ error-pattern:One -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!("One"); diff --git a/tests/ui/panics/explicit-panic-msg.rs b/tests/ui/panics/explicit-panic-msg.rs index ef0c5b39f09..e5728ef1e20 100644 --- a/tests/ui/panics/explicit-panic-msg.rs +++ b/tests/ui/panics/explicit-panic-msg.rs @@ -4,7 +4,7 @@ //@ run-fail //@ error-pattern:wooooo -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let mut a = 1; diff --git a/tests/ui/panics/explicit-panic.rs b/tests/ui/panics/explicit-panic.rs index 34e952ef68f..7c69289940e 100644 --- a/tests/ui/panics/explicit-panic.rs +++ b/tests/ui/panics/explicit-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:explicit -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!(); diff --git a/tests/ui/panics/fmt-panic.rs b/tests/ui/panics/fmt-panic.rs index 032f65cb2e4..c6cb039684d 100644 --- a/tests/ui/panics/fmt-panic.rs +++ b/tests/ui/panics/fmt-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:meh -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let str_var: String = "meh".to_string(); diff --git a/tests/ui/panics/issue-47429-short-backtraces.rs b/tests/ui/panics/issue-47429-short-backtraces.rs index dff885af1b8..4a73ebe8712 100644 --- a/tests/ui/panics/issue-47429-short-backtraces.rs +++ b/tests/ui/panics/issue-47429-short-backtraces.rs @@ -17,10 +17,10 @@ //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test //@ ignore-android FIXME #17520 //@ ignore-openbsd no support for libbacktrace without filename -//@ ignore-wasm no panic or subprocess support -//@ ignore-emscripten no panic or subprocess support -//@ ignore-sgx no subprocess support +//@ ignore-wasm no panic support +//@ ignore-emscripten no panic support //@ ignore-fuchsia Backtraces not symbolized +//@ needs-subprocess fn main() { panic!() diff --git a/tests/ui/panics/main-panic.rs b/tests/ui/panics/main-panic.rs index b69f1656ca4..0b3d5c3aaec 100644 --- a/tests/ui/panics/main-panic.rs +++ b/tests/ui/panics/main-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:thread 'main' panicked at -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!() diff --git a/tests/ui/panics/panic-arg.rs b/tests/ui/panics/panic-arg.rs index 10be6d5ff6c..037cfda3689 100644 --- a/tests/ui/panics/panic-arg.rs +++ b/tests/ui/panics/panic-arg.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:woe -//@ ignore-emscripten no processes +//@ needs-subprocess fn f(a: isize) { println!("{}", a); diff --git a/tests/ui/panics/panic-handler-chain-update-hook.rs b/tests/ui/panics/panic-handler-chain-update-hook.rs index 1f8fe30cfd8..662ea9e978f 100644 --- a/tests/ui/panics/panic-handler-chain-update-hook.rs +++ b/tests/ui/panics/panic-handler-chain-update-hook.rs @@ -2,7 +2,7 @@ //@ needs-unwind #![allow(stable_features)] -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(std_panic)] #![feature(panic_update_hook)] diff --git a/tests/ui/panics/panic-handler-flail-wildly.rs b/tests/ui/panics/panic-handler-flail-wildly.rs index 768c9d4c4c5..d42dfd68d9c 100644 --- a/tests/ui/panics/panic-handler-flail-wildly.rs +++ b/tests/ui/panics/panic-handler-flail-wildly.rs @@ -4,7 +4,7 @@ #![allow(stable_features)] #![allow(unused_must_use)] -//@ ignore-emscripten no threads support +//@ needs-threads #![feature(std_panic)] diff --git a/tests/ui/panics/panic-handler-set-twice.rs b/tests/ui/panics/panic-handler-set-twice.rs index 902e48b6541..5f670d5f492 100644 --- a/tests/ui/panics/panic-handler-set-twice.rs +++ b/tests/ui/panics/panic-handler-set-twice.rs @@ -5,7 +5,7 @@ #![feature(std_panic)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::atomic::{AtomicUsize, Ordering}; use std::panic; diff --git a/tests/ui/panics/panic-in-dtor-drops-fields.rs b/tests/ui/panics/panic-in-dtor-drops-fields.rs index 4d18dc0e059..38eb6d0acfb 100644 --- a/tests/ui/panics/panic-in-dtor-drops-fields.rs +++ b/tests/ui/panics/panic-in-dtor-drops-fields.rs @@ -3,7 +3,7 @@ #![allow(dead_code)] #![allow(non_upper_case_globals)] -//@ ignore-emscripten no threads support +//@ needs-threads use std::thread; diff --git a/tests/ui/panics/panic-macro-any-wrapped.rs b/tests/ui/panics/panic-macro-any-wrapped.rs index 7c6790e35fd..e3a2dc6eed4 100644 --- a/tests/ui/panics/panic-macro-any-wrapped.rs +++ b/tests/ui/panics/panic-macro-any-wrapped.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:panicked //@ error-pattern:Box<dyn Any> -//@ ignore-emscripten no processes +//@ needs-subprocess #![allow(non_fmt_panics)] diff --git a/tests/ui/panics/panic-macro-any.rs b/tests/ui/panics/panic-macro-any.rs index 75397333fa4..1392929b65c 100644 --- a/tests/ui/panics/panic-macro-any.rs +++ b/tests/ui/panics/panic-macro-any.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:panicked //@ error-pattern:Box<dyn Any> -//@ ignore-emscripten no processes +//@ needs-subprocess #![allow(non_fmt_panics)] diff --git a/tests/ui/panics/panic-macro-explicit.rs b/tests/ui/panics/panic-macro-explicit.rs index 2c7b84d99fe..b9195e3b0fc 100644 --- a/tests/ui/panics/panic-macro-explicit.rs +++ b/tests/ui/panics/panic-macro-explicit.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:panicked //@ error-pattern:explicit panic -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!(); diff --git a/tests/ui/panics/panic-macro-fmt.rs b/tests/ui/panics/panic-macro-fmt.rs index 1a63a06c75a..550cd5c1ee3 100644 --- a/tests/ui/panics/panic-macro-fmt.rs +++ b/tests/ui/panics/panic-macro-fmt.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:panicked //@ error-pattern:test-fail-fmt 42 rust -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!("test-fail-fmt {} {}", 42, "rust"); diff --git a/tests/ui/panics/panic-macro-owned.rs b/tests/ui/panics/panic-macro-owned.rs index 1878f3d52ab..4df04c50bc3 100644 --- a/tests/ui/panics/panic-macro-owned.rs +++ b/tests/ui/panics/panic-macro-owned.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:panicked //@ error-pattern:test-fail-owned -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!("test-fail-owned"); diff --git a/tests/ui/panics/panic-macro-static.rs b/tests/ui/panics/panic-macro-static.rs index 018166e60cf..1c6258ebed2 100644 --- a/tests/ui/panics/panic-macro-static.rs +++ b/tests/ui/panics/panic-macro-static.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:panicked //@ error-pattern:test-fail-static -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!("test-fail-static"); diff --git a/tests/ui/panics/panic-main.rs b/tests/ui/panics/panic-main.rs index d71fca0754e..3876dbb37c3 100644 --- a/tests/ui/panics/panic-main.rs +++ b/tests/ui/panics/panic-main.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:moop -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!("moop"); diff --git a/tests/ui/panics/panic-parens.rs b/tests/ui/panics/panic-parens.rs index 271d0363cab..5440bf18f25 100644 --- a/tests/ui/panics/panic-parens.rs +++ b/tests/ui/panics/panic-parens.rs @@ -3,7 +3,7 @@ //@ run-fail //@ error-pattern:oops -//@ ignore-emscripten no processes +//@ needs-subprocess fn bigpanic() { while (panic!("oops")) { diff --git a/tests/ui/panics/panic-recover-propagate.rs b/tests/ui/panics/panic-recover-propagate.rs index f8be86be19d..ef6ae4fd788 100644 --- a/tests/ui/panics/panic-recover-propagate.rs +++ b/tests/ui/panics/panic-recover-propagate.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads use std::sync::atomic::{AtomicUsize, Ordering}; use std::panic; diff --git a/tests/ui/panics/panic-set-handler.rs b/tests/ui/panics/panic-set-handler.rs index 39286ca865b..41e513e0bd6 100644 --- a/tests/ui/panics/panic-set-handler.rs +++ b/tests/ui/panics/panic-set-handler.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:greetings from the panic handler -//@ ignore-emscripten no processes +//@ needs-subprocess use std::panic; diff --git a/tests/ui/panics/panic-set-unset-handler.rs b/tests/ui/panics/panic-set-unset-handler.rs index 02f1599338b..66d5003d0f1 100644 --- a/tests/ui/panics/panic-set-unset-handler.rs +++ b/tests/ui/panics/panic-set-unset-handler.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'main' panicked //@ error-pattern:foobar -//@ ignore-emscripten no processes +//@ needs-subprocess use std::panic; diff --git a/tests/ui/panics/panic-take-handler-nop.rs b/tests/ui/panics/panic-take-handler-nop.rs index 89e1d234df1..f10582872df 100644 --- a/tests/ui/panics/panic-take-handler-nop.rs +++ b/tests/ui/panics/panic-take-handler-nop.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:thread 'main' panicked //@ error-pattern:foobar -//@ ignore-emscripten no processes +//@ needs-subprocess use std::panic; diff --git a/tests/ui/panics/panic.rs b/tests/ui/panics/panic.rs index b9721ac8230..068f187524d 100644 --- a/tests/ui/panics/panic.rs +++ b/tests/ui/panics/panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:1 == 2 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { assert!(1 == 2); diff --git a/tests/ui/panics/result-get-panic.rs b/tests/ui/panics/result-get-panic.rs index d7f6dfe8406..b8dc49f9aca 100644 --- a/tests/ui/panics/result-get-panic.rs +++ b/tests/ui/panics/result-get-panic.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:called `Result::unwrap()` on an `Err` value -//@ ignore-emscripten no processes +//@ needs-subprocess use std::result::Result::Err; diff --git a/tests/ui/panics/runtime-switch.rs b/tests/ui/panics/runtime-switch.rs index ffd038f9535..9f0be8c7ddf 100644 --- a/tests/ui/panics/runtime-switch.rs +++ b/tests/ui/panics/runtime-switch.rs @@ -18,9 +18,9 @@ //@ ignore-android FIXME #17520 //@ ignore-openbsd no support for libbacktrace without filename //@ ignore-wasm no backtrace support -//@ ignore-emscripten no panic or subprocess support -//@ ignore-sgx no subprocess support +//@ ignore-emscripten no panic support //@ ignore-fuchsia Backtrace not symbolized +//@ needs-subprocess #![feature(panic_backtrace_config)] diff --git a/tests/ui/panics/test-panic.rs b/tests/ui/panics/test-panic.rs index 29a3c4e9c9f..c7af47524cf 100644 --- a/tests/ui/panics/test-panic.rs +++ b/tests/ui/panics/test-panic.rs @@ -1,7 +1,7 @@ //@ run-fail //@ check-stdout //@ compile-flags: --test -//@ ignore-emscripten +//@ needs-subprocess #[test] fn test_foo() { diff --git a/tests/ui/panics/test-should-panic-no-message.rs b/tests/ui/panics/test-should-panic-no-message.rs index b6ed6b19dd0..05fc927d876 100644 --- a/tests/ui/panics/test-should-panic-no-message.rs +++ b/tests/ui/panics/test-should-panic-no-message.rs @@ -1,7 +1,7 @@ //@ run-fail //@ compile-flags: --test //@ check-stdout -//@ ignore-wasm32 no processes +//@ needs-subprocess #[test] #[should_panic(expected = "foo")] diff --git a/tests/ui/panics/while-body-panics.rs b/tests/ui/panics/while-body-panics.rs index bddcd5d50ce..8459a8d63bf 100644 --- a/tests/ui/panics/while-body-panics.rs +++ b/tests/ui/panics/while-body-panics.rs @@ -2,7 +2,7 @@ //@ run-fail //@ error-pattern:quux -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let _x: isize = { diff --git a/tests/ui/panics/while-panic.rs b/tests/ui/panics/while-panic.rs index 2961e8599c3..4c8431c71d1 100644 --- a/tests/ui/panics/while-panic.rs +++ b/tests/ui/panics/while-panic.rs @@ -2,7 +2,7 @@ //@ run-fail //@ error-pattern:giraffe -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { panic!("{}", { diff --git a/tests/ui/parallel-rustc/cycle_crash.rs b/tests/ui/parallel-rustc/cycle_crash.rs new file mode 100644 index 00000000000..94ae11aef39 --- /dev/null +++ b/tests/ui/parallel-rustc/cycle_crash.rs @@ -0,0 +1,5 @@ +//@ compile-flags: -Z threads=2 + +const FOO: usize = FOO; //~ERROR cycle detected when simplifying constant for the type system `FOO` + +fn main() {} diff --git a/tests/ui/parallel-rustc/cycle_crash.stderr b/tests/ui/parallel-rustc/cycle_crash.stderr new file mode 100644 index 00000000000..7af3b8ee532 --- /dev/null +++ b/tests/ui/parallel-rustc/cycle_crash.stderr @@ -0,0 +1,18 @@ +error[E0391]: cycle detected when simplifying constant for the type system `FOO` + --> $DIR/cycle_crash.rs:3:1 + | +LL | const FOO: usize = FOO; + | ^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `FOO`... + --> $DIR/cycle_crash.rs:3:20 + | +LL | const FOO: usize = FOO; + | ^^^ + = note: ...which again requires simplifying constant for the type system `FOO`, completing the cycle + = note: cycle used when running analysis passes on this crate + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.rs b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.rs index 53e3c6f9605..3876fb41d23 100644 --- a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.rs +++ b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.rs @@ -11,5 +11,5 @@ fn banana(a: <T<const N: usize>>::BAR) {} fn chaenomeles() { path::path::Struct::<const N: usize>() //~^ ERROR unexpected `const` parameter declaration - //~| ERROR failed to resolve: use of undeclared crate or module `path` + //~| ERROR failed to resolve: use of unresolved module or unlinked crate `path` } diff --git a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr index 96885d11ee0..104dbd02685 100644 --- a/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr +++ b/tests/ui/parser/const-param-decl-on-type-instead-of-impl.stderr @@ -21,11 +21,13 @@ error: unexpected `const` parameter declaration LL | path::path::Struct::<const N: usize>() | ^^^^^^^^^^^^^^ expected a `const` expression, not a parameter declaration -error[E0433]: failed to resolve: use of undeclared crate or module `path` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `path` --> $DIR/const-param-decl-on-type-instead-of-impl.rs:12:5 | LL | path::path::Struct::<const N: usize>() - | ^^^^ use of undeclared crate or module `path` + | ^^^^ use of unresolved module or unlinked crate `path` + | + = help: you might be missing a crate named `path` error[E0412]: cannot find type `T` in this scope --> $DIR/const-param-decl-on-type-instead-of-impl.rs:8:15 diff --git a/tests/ui/parser/dyn-trait-compatibility.rs b/tests/ui/parser/dyn-trait-compatibility.rs index 6341e053277..717b14c5941 100644 --- a/tests/ui/parser/dyn-trait-compatibility.rs +++ b/tests/ui/parser/dyn-trait-compatibility.rs @@ -1,7 +1,7 @@ type A0 = dyn; //~^ ERROR cannot find type `dyn` in this scope type A1 = dyn::dyn; -//~^ ERROR use of undeclared crate or module `dyn` +//~^ ERROR use of unresolved module or unlinked crate `dyn` type A2 = dyn<dyn, dyn>; //~^ ERROR cannot find type `dyn` in this scope //~| ERROR cannot find type `dyn` in this scope diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr index e34d855a9d4..08e0a50010a 100644 --- a/tests/ui/parser/dyn-trait-compatibility.stderr +++ b/tests/ui/parser/dyn-trait-compatibility.stderr @@ -40,11 +40,13 @@ error[E0412]: cannot find type `dyn` in this scope LL | type A3 = dyn<<dyn as dyn>::dyn>; | ^^^ not found in this scope -error[E0433]: failed to resolve: use of undeclared crate or module `dyn` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `dyn` --> $DIR/dyn-trait-compatibility.rs:3:11 | LL | type A1 = dyn::dyn; - | ^^^ use of undeclared crate or module `dyn` + | ^^^ use of unresolved module or unlinked crate `dyn` + | + = help: you might be missing a crate named `dyn` error: aborting due to 8 previous errors diff --git a/tests/ui/parser/issues/issue-14303-fncall.full.stderr b/tests/ui/parser/issues/issue-14303-fncall.full.stderr index 1986f70bf67..5a017c85c16 100644 --- a/tests/ui/parser/issues/issue-14303-fncall.full.stderr +++ b/tests/ui/parser/issues/issue-14303-fncall.full.stderr @@ -1,8 +1,8 @@ -error[E0747]: type provided when a lifetime was expected - --> $DIR/issue-14303-fncall.rs:15:26 +error[E0747]: placeholder provided when a lifetime was expected + --> $DIR/issue-14303-fncall.rs:12:77 | -LL | .collect::<Vec<S<_, 'a>>>(); - | ^ +LL | let _x = (*start..*end).map(|x| S { a: start, b: end }).collect::<Vec<S<_, 'a>>>(); + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr b/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr index 2de59b8c746..5a017c85c16 100644 --- a/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr +++ b/tests/ui/parser/issues/issue-14303-fncall.generic_arg.stderr @@ -1,8 +1,8 @@ -error[E0747]: inferred provided when a lifetime was expected - --> $DIR/issue-14303-fncall.rs:15:26 +error[E0747]: placeholder provided when a lifetime was expected + --> $DIR/issue-14303-fncall.rs:12:77 | -LL | .collect::<Vec<S<_, 'a>>>(); - | ^ +LL | let _x = (*start..*end).map(|x| S { a: start, b: end }).collect::<Vec<S<_, 'a>>>(); + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-14303-fncall.rs b/tests/ui/parser/issues/issue-14303-fncall.rs index 59d4eab06d6..8f7fbec9470 100644 --- a/tests/ui/parser/issues/issue-14303-fncall.rs +++ b/tests/ui/parser/issues/issue-14303-fncall.rs @@ -3,18 +3,15 @@ // we need the above to avoid ast borrowck failure in recovered code #![cfg_attr(generic_arg, feature(generic_arg_infer))] - struct S<'a, T> { a: &'a T, b: &'a T, } fn foo<'a, 'b>(start: &'a usize, end: &'a usize) { - let _x = (*start..*end) - .map(|x| S { a: start, b: end }) - .collect::<Vec<S<_, 'a>>>(); - //[generic_arg]~^ ERROR inferred provided when a lifetime was expected - //[full]~^^ ERROR type provided when a lifetime was expected + let _x = (*start..*end).map(|x| S { a: start, b: end }).collect::<Vec<S<_, 'a>>>(); + //[generic_arg]~^ ERROR placeholder provided when a lifetime was expected + //[full]~^^ ERROR placeholder provided when a lifetime was expected } fn main() {} diff --git a/tests/ui/parser/issues/issue-5806.rs b/tests/ui/parser/issues/issue-5806.rs index dbd53a7adc4..1a819e22197 100644 --- a/tests/ui/parser/issues/issue-5806.rs +++ b/tests/ui/parser/issues/issue-5806.rs @@ -1,4 +1,4 @@ -//@ normalize-stderr: "parser:.*\(" -> "parser: $$ACCESS_DENIED_MSG (" +//@ normalize-stderr: "parser`:.*\(" -> "parser`: $$ACCESS_DENIED_MSG (" //@ normalize-stderr: "os error \d+" -> "os error $$ACCESS_DENIED_CODE" #[path = "../parser"] diff --git a/tests/ui/parser/issues/issue-5806.stderr b/tests/ui/parser/issues/issue-5806.stderr index 4b025bd19a0..88cc982baf2 100644 --- a/tests/ui/parser/issues/issue-5806.stderr +++ b/tests/ui/parser/issues/issue-5806.stderr @@ -1,4 +1,4 @@ -error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) +error: couldn't read `$DIR/../parser`: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) --> $DIR/issue-5806.rs:5:1 | LL | mod foo; diff --git a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr index 76259b40a93..dda37d83282 100644 --- a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr +++ b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr @@ -30,7 +30,7 @@ error: `mut` must be followed by a named binding --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:13 | LL | let mut $eval = (); - | ^^^ + | ^^^^ ... LL | mac2! { does_not_exist!() } | --------------------------- in this macro invocation @@ -40,7 +40,7 @@ LL | mac2! { does_not_exist!() } help: remove the `mut` prefix | LL - let mut $eval = (); -LL + let $eval = (); +LL + let $eval = (); | error: cannot find macro `does_not_exist` in this scope diff --git a/tests/ui/parser/mod_file_not_exist.rs b/tests/ui/parser/mod_file_not_exist.rs index 80a17163087..e7727944147 100644 --- a/tests/ui/parser/mod_file_not_exist.rs +++ b/tests/ui/parser/mod_file_not_exist.rs @@ -5,5 +5,6 @@ mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` fn main() { assert_eq!(mod_file_aux::bar(), 10); - //~^ ERROR failed to resolve: use of undeclared crate or module `mod_file_aux` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `mod_file_aux` + //~| HELP you might be missing a crate named `mod_file_aux` } diff --git a/tests/ui/parser/mod_file_not_exist.stderr b/tests/ui/parser/mod_file_not_exist.stderr index c2f9d30d9ec..40041b11c8b 100644 --- a/tests/ui/parser/mod_file_not_exist.stderr +++ b/tests/ui/parser/mod_file_not_exist.stderr @@ -7,11 +7,13 @@ LL | mod not_a_real_file; = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" or "$DIR/not_a_real_file/mod.rs" = note: if there is a `mod not_a_real_file` elsewhere in the crate already, import it with `use crate::...` instead -error[E0433]: failed to resolve: use of undeclared crate or module `mod_file_aux` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `mod_file_aux` --> $DIR/mod_file_not_exist.rs:7:16 | LL | assert_eq!(mod_file_aux::bar(), 10); - | ^^^^^^^^^^^^ use of undeclared crate or module `mod_file_aux` + | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `mod_file_aux` + | + = help: you might be missing a crate named `mod_file_aux` error: aborting due to 2 previous errors diff --git a/tests/ui/parser/mod_file_not_exist_windows.rs b/tests/ui/parser/mod_file_not_exist_windows.rs index 88780c0c24e..bb74684d994 100644 --- a/tests/ui/parser/mod_file_not_exist_windows.rs +++ b/tests/ui/parser/mod_file_not_exist_windows.rs @@ -5,5 +5,6 @@ mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` fn main() { assert_eq!(mod_file_aux::bar(), 10); - //~^ ERROR failed to resolve: use of undeclared crate or module `mod_file_aux` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `mod_file_aux` + //~| HELP you might be missing a crate named `mod_file_aux` } diff --git a/tests/ui/parser/mod_file_not_exist_windows.stderr b/tests/ui/parser/mod_file_not_exist_windows.stderr index 53b09d8ca53..03c762d0ef2 100644 --- a/tests/ui/parser/mod_file_not_exist_windows.stderr +++ b/tests/ui/parser/mod_file_not_exist_windows.stderr @@ -7,11 +7,13 @@ LL | mod not_a_real_file; = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" or "$DIR/not_a_real_file/mod.rs" = note: if there is a `mod not_a_real_file` elsewhere in the crate already, import it with `use crate::...` instead -error[E0433]: failed to resolve: use of undeclared crate or module `mod_file_aux` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `mod_file_aux` --> $DIR/mod_file_not_exist_windows.rs:7:16 | LL | assert_eq!(mod_file_aux::bar(), 10); - | ^^^^^^^^^^^^ use of undeclared crate or module `mod_file_aux` + | ^^^^^^^^^^^^ use of unresolved module or unlinked crate `mod_file_aux` + | + = help: you might be missing a crate named `mod_file_aux` error: aborting due to 2 previous errors diff --git a/tests/ui/parser/mod_file_with_path_attr.rs b/tests/ui/parser/mod_file_with_path_attr.rs index ff964f750e2..b7f4a9c6ae0 100644 --- a/tests/ui/parser/mod_file_with_path_attr.rs +++ b/tests/ui/parser/mod_file_with_path_attr.rs @@ -1,4 +1,4 @@ -//@ normalize-stderr: "not_a_real_file.rs:.*\(" -> "not_a_real_file.rs: $$FILE_NOT_FOUND_MSG (" +//@ normalize-stderr: "not_a_real_file.rs`:.*\(" -> "not_a_real_file.rs`: $$FILE_NOT_FOUND_MSG (" #[path = "not_a_real_file.rs"] mod m; //~ ERROR not_a_real_file.rs diff --git a/tests/ui/parser/mod_file_with_path_attr.stderr b/tests/ui/parser/mod_file_with_path_attr.stderr index 9ccb775daab..ef8a715712b 100644 --- a/tests/ui/parser/mod_file_with_path_attr.stderr +++ b/tests/ui/parser/mod_file_with_path_attr.stderr @@ -1,4 +1,4 @@ -error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2) +error: couldn't read `$DIR/not_a_real_file.rs`: $FILE_NOT_FOUND_MSG (os error 2) --> $DIR/mod_file_with_path_attr.rs:4:1 | LL | mod m; diff --git a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr b/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr deleted file mode 100644 index cf37bf67e86..00000000000 --- a/tests/ui/pattern/usefulness/empty-types.min_exh_pats.stderr +++ /dev/null @@ -1,727 +0,0 @@ -error: unreachable pattern - --> $DIR/empty-types.rs:51:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited -note: the lint level is defined here - --> $DIR/empty-types.rs:17:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/empty-types.rs:54:9 - | -LL | _x => {} - | ^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error[E0004]: non-exhaustive patterns: type `&!` is non-empty - --> $DIR/empty-types.rs:58:11 - | -LL | match ref_never {} - | ^^^^^^^^^ - | - = note: the matched value is of type `&!` - = note: references are always considered inhabited -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match ref_never { -LL + _ => todo!(), -LL + } - | - -error: unreachable pattern - --> $DIR/empty-types.rs:73:9 - | -LL | (_, _) => {} - | ^^^^^^ - | - = note: this pattern matches no values because `(u32, !)` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:80:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `(!, !)` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:83:9 - | -LL | (_, _) => {} - | ^^^^^^ - | - = note: this pattern matches no values because `(!, !)` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:87:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:91:11 - | -LL | match res_u32_never {} - | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered - | -note: `Result<u32, !>` defined here - --> $SRC_DIR/core/src/result.rs:LL:COL - ::: $SRC_DIR/core/src/result.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Result<u32, !>` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ match res_u32_never { -LL + Ok(_) => todo!(), -LL + } - | - -error: unreachable pattern - --> $DIR/empty-types.rs:99:9 - | -LL | Err(_) => {} - | ^^^^^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:104:9 - | -LL | Err(_) => {} - | ^^^^^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered - --> $DIR/empty-types.rs:101:11 - | -LL | match res_u32_never { - | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered - | -note: `Result<u32, !>` defined here - --> $SRC_DIR/core/src/result.rs:LL:COL - ::: $SRC_DIR/core/src/result.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Result<u32, !>` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ Err(_) => {}, -LL ~ Ok(1_u32..=u32::MAX) => todo!() - | - -error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:108:9 - | -LL | let Ok(_x) = res_u32_never.as_ref(); - | ^^^^^^ pattern `Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html - = note: the matched value is of type `Result<&u32, &!>` -help: you might want to use `let else` to handle the variant that isn't matched - | -LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; - | ++++++++++++++++ - -error[E0005]: refutable pattern in local binding - --> $DIR/empty-types.rs:112:9 - | -LL | let Ok(_x) = &res_u32_never; - | ^^^^^^ pattern `&Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html - = note: the matched value is of type `&Result<u32, !>` -help: you might want to use `let else` to handle the variant that isn't matched - | -LL | let Ok(_x) = &res_u32_never else { todo!() }; - | ++++++++++++++++ - -error: unreachable pattern - --> $DIR/empty-types.rs:119:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `Result<!, !>` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:123:9 - | -LL | Ok(_) => {} - | ^^^^^ - | - = note: this pattern matches no values because `Result<!, !>` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:126:9 - | -LL | Ok(_) => {} - | ^^^^^ - | - = note: this pattern matches no values because `Result<!, !>` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:127:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `Result<!, !>` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:130:9 - | -LL | Ok(_) => {} - | ^^^^^ - | - = note: this pattern matches no values because `Result<!, !>` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:131:9 - | -LL | Err(_) => {} - | ^^^^^^ - | - = note: this pattern matches no values because `Result<!, !>` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:140:13 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `Void` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:143:13 - | -LL | _ if false => {} - | ^ - | - = note: this pattern matches no values because `Void` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:152:13 - | -LL | Some(_) => {} - | ^^^^^^^ - | - = note: this pattern matches no values because `Void` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:156:13 - | -LL | None => {} - | ---- matches all the values already -LL | _ => {} - | ^ unreachable pattern - -error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:165:15 - | -LL | match *ref_opt_void { - | ^^^^^^^^^^^^^ pattern `Some(_)` not covered - | -note: `Option<Void>` defined here - --> $SRC_DIR/core/src/option.rs:LL:COL - ::: $SRC_DIR/core/src/option.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Option<Void>` - = note: `Void` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ None => {}, -LL + Some(_) => todo!() - | - -error: unreachable pattern - --> $DIR/empty-types.rs:208:13 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:213:13 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:218:13 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:223:13 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:229:13 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:288:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:291:9 - | -LL | (_, _) => {} - | ^^^^^^ - | - = note: this pattern matches no values because `(!, !)` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:294:9 - | -LL | Ok(_) => {} - | ^^^^^ - | - = note: this pattern matches no values because `Result<!, !>` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:295:9 - | -LL | Err(_) => {} - | ^^^^^^ - | - = note: this pattern matches no values because `Result<!, !>` is uninhabited - -error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:316:11 - | -LL | match *x {} - | ^^ - | - = note: the matched value is of type `(u32, !)` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match *x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty - --> $DIR/empty-types.rs:318:11 - | -LL | match *x {} - | ^^ - | - = note: the matched value is of type `(!, !)` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match *x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered - --> $DIR/empty-types.rs:320:11 - | -LL | match *x {} - | ^^ patterns `Ok(_)` and `Err(_)` not covered - | -note: `Result<!, !>` defined here - --> $SRC_DIR/core/src/result.rs:LL:COL - ::: $SRC_DIR/core/src/result.rs:LL:COL - | - = note: not covered - ::: $SRC_DIR/core/src/result.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Result<!, !>` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms - | -LL ~ match *x { -LL + Ok(_) | Err(_) => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty - --> $DIR/empty-types.rs:322:11 - | -LL | match *x {} - | ^^ - | - = note: the matched value is of type `[!; 3]` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match *x { -LL + _ => todo!(), -LL ~ } - | - -error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty - --> $DIR/empty-types.rs:327:11 - | -LL | match slice_never {} - | ^^^^^^^^^^^ - | - = note: the matched value is of type `&[!]` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match slice_never { -LL + _ => todo!(), -LL + } - | - -error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered - --> $DIR/empty-types.rs:329:11 - | -LL | match slice_never { - | ^^^^^^^^^^^ pattern `&[_, ..]` not covered - | - = note: the matched value is of type `&[!]` - = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ [] => {}, -LL + &[_, ..] => todo!() - | - -error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered - --> $DIR/empty-types.rs:338:11 - | -LL | match slice_never { - | ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered - | - = note: the matched value is of type `&[!]` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms - | -LL ~ [_, _, _, ..] => {}, -LL + &[] | &[_] | &[_, _] => todo!() - | - -error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered - --> $DIR/empty-types.rs:352:11 - | -LL | match slice_never { - | ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered - | - = note: the matched value is of type `&[!]` - = note: match arms with guards don't count towards exhaustivity -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms - | -LL ~ &[..] if false => {}, -LL + &[] | &[_, ..] => todo!() - | - -error[E0004]: non-exhaustive patterns: type `[!]` is non-empty - --> $DIR/empty-types.rs:359:11 - | -LL | match *slice_never {} - | ^^^^^^^^^^^^ - | - = note: the matched value is of type `[!]` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match *slice_never { -LL + _ => todo!(), -LL + } - | - -error: unreachable pattern - --> $DIR/empty-types.rs:369:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `[!; 3]` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:372:9 - | -LL | [_, _, _] => {} - | ^^^^^^^^^ - | - = note: this pattern matches no values because `[!; 3]` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:375:9 - | -LL | [_, ..] => {} - | ^^^^^^^ - | - = note: this pattern matches no values because `[!; 3]` is uninhabited - -error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty - --> $DIR/empty-types.rs:389:11 - | -LL | match array_0_never {} - | ^^^^^^^^^^^^^ - | - = note: the matched value is of type `[!; 0]` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match array_0_never { -LL + _ => todo!(), -LL + } - | - -error: unreachable pattern - --> $DIR/empty-types.rs:396:9 - | -LL | [] => {} - | -- matches all the values already -LL | _ => {} - | ^ unreachable pattern - -error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/empty-types.rs:398:11 - | -LL | match array_0_never { - | ^^^^^^^^^^^^^ pattern `[]` not covered - | - = note: the matched value is of type `[!; 0]` - = note: match arms with guards don't count towards exhaustivity -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ [..] if false => {}, -LL + [] => todo!() - | - -error: unreachable pattern - --> $DIR/empty-types.rs:417:9 - | -LL | Some(_) => {} - | ^^^^^^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:422:9 - | -LL | Some(_a) => {} - | ^^^^^^^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:427:9 - | -LL | None => {} - | ---- matches all the values already -LL | // !useful, !reachable -LL | _ => {} - | ^ unreachable pattern - -error: unreachable pattern - --> $DIR/empty-types.rs:432:9 - | -LL | None => {} - | ---- matches all the values already -LL | // !useful, !reachable -LL | _a => {} - | ^^ unreachable pattern - -error[E0004]: non-exhaustive patterns: `&Some(_)` not covered - --> $DIR/empty-types.rs:452:11 - | -LL | match ref_opt_never { - | ^^^^^^^^^^^^^ pattern `&Some(_)` not covered - | -note: `Option<!>` defined here - --> $SRC_DIR/core/src/option.rs:LL:COL - ::: $SRC_DIR/core/src/option.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `&Option<!>` - = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ &None => {}, -LL + &Some(_) => todo!() - | - -error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:493:11 - | -LL | match *ref_opt_never { - | ^^^^^^^^^^^^^^ pattern `Some(_)` not covered - | -note: `Option<!>` defined here - --> $SRC_DIR/core/src/option.rs:LL:COL - ::: $SRC_DIR/core/src/option.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Option<!>` - = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ None => {}, -LL + Some(_) => todo!() - | - -error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:541:11 - | -LL | match *ref_res_never { - | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered - | -note: `Result<!, !>` defined here - --> $SRC_DIR/core/src/result.rs:LL:COL - ::: $SRC_DIR/core/src/result.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Result<!, !>` - = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ Ok(_) => {}, -LL + Err(_) => todo!() - | - -error[E0004]: non-exhaustive patterns: `Err(_)` not covered - --> $DIR/empty-types.rs:552:11 - | -LL | match *ref_res_never { - | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered - | -note: `Result<!, !>` defined here - --> $SRC_DIR/core/src/result.rs:LL:COL - ::: $SRC_DIR/core/src/result.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Result<!, !>` - = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ Ok(_a) => {}, -LL + Err(_) => todo!() - | - -error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty - --> $DIR/empty-types.rs:571:11 - | -LL | match *ref_tuple_half_never {} - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: the matched value is of type `(u32, !)` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match *ref_tuple_half_never { -LL + _ => todo!(), -LL + } - | - -error: unreachable pattern - --> $DIR/empty-types.rs:604:9 - | -LL | _ => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:607:9 - | -LL | _x => {} - | ^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:610:9 - | -LL | _ if false => {} - | ^ - | - = note: this pattern matches no values because `!` is uninhabited - -error: unreachable pattern - --> $DIR/empty-types.rs:613:9 - | -LL | _x if false => {} - | ^^ - | - = note: this pattern matches no values because `!` is uninhabited - -error[E0004]: non-exhaustive patterns: `&_` not covered - --> $DIR/empty-types.rs:638:11 - | -LL | match ref_never { - | ^^^^^^^^^ pattern `&_` not covered - | - = note: the matched value is of type `&!` - = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required - = note: references are always considered inhabited - = note: match arms with guards don't count towards exhaustivity -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ &_a if false => {}, -LL + &_ => todo!() - | - -error[E0004]: non-exhaustive patterns: `Ok(_)` not covered - --> $DIR/empty-types.rs:654:11 - | -LL | match *ref_result_never { - | ^^^^^^^^^^^^^^^^^ pattern `Ok(_)` not covered - | -note: `Result<!, !>` defined here - --> $SRC_DIR/core/src/result.rs:LL:COL - ::: $SRC_DIR/core/src/result.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Result<!, !>` - = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ Err(_) => {}, -LL + Ok(_) => todo!() - | - -error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/empty-types.rs:674:11 - | -LL | match *x { - | ^^ pattern `Some(_)` not covered - | -note: `Option<Result<!, !>>` defined here - --> $SRC_DIR/core/src/option.rs:LL:COL - ::: $SRC_DIR/core/src/option.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Option<Result<!, !>>` - = note: `Result<!, !>` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ None => {}, -LL + Some(_) => todo!() - | - -error: aborting due to 64 previous errors - -Some errors have detailed explanations: E0004, E0005. -For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr index ba7573839ed..ee21b4c8d46 100644 --- a/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr +++ b/tests/ui/pattern/usefulness/issue-82772-match-box-as-struct.stderr @@ -2,7 +2,7 @@ error[E0451]: field `1` of struct `Box` is private --> $DIR/issue-82772-match-box-as-struct.rs:4:15 | LL | let Box { 1: _, .. }: Box<()>; - | ^^^^ private field + | ^ private field error: aborting due to 1 previous error diff --git a/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr deleted file mode 100644 index 261a4b3353f..00000000000 --- a/tests/ui/pattern/usefulness/match-privately-empty.min_exhaustive_patterns.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0004]: non-exhaustive patterns: `Some(Private { misc: true, .. })` not covered - --> $DIR/match-privately-empty.rs:15:11 - | -LL | match private::DATA { - | ^^^^^^^^^^^^^ pattern `Some(Private { misc: true, .. })` not covered - | -note: `Option<Private>` defined here - --> $SRC_DIR/core/src/option.rs:LL:COL - ::: $SRC_DIR/core/src/option.rs:LL:COL - | - = note: not covered - = note: the matched value is of type `Option<Private>` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ Some(private::Private { misc: false, .. }) => {}, -LL + Some(Private { misc: true, .. }) => todo!() - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr deleted file mode 100644 index f24ce154d14..00000000000 --- a/tests/ui/pattern/usefulness/slice_of_empty.min_exhaustive_patterns.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered - --> $DIR/slice_of_empty.rs:10:11 - | -LL | match nevers { - | ^^^^^^ pattern `&[_, ..]` not covered - | - = note: the matched value is of type `&[!]` - = note: `!` is uninhabited but is not being matched by value, so a wildcard `_` is required -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown - | -LL ~ &[] => (), -LL ~ &[_, ..] => todo!(), - | - -error[E0004]: non-exhaustive patterns: `&[]` and `&[_, _, ..]` not covered - --> $DIR/slice_of_empty.rs:21:11 - | -LL | match nevers { - | ^^^^^^ patterns `&[]` and `&[_, _, ..]` not covered - | - = note: the matched value is of type `&[!]` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms - | -LL ~ &[_] => (), -LL ~ &[] | &[_, _, ..] => todo!(), - | - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/print-stdout-eprint-stderr.rs b/tests/ui/print-stdout-eprint-stderr.rs index e84a9bebc49..4b356e2fe61 100644 --- a/tests/ui/print-stdout-eprint-stderr.rs +++ b/tests/ui/print-stdout-eprint-stderr.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 spawning processes is not supported -//@ ignore-sgx no processes +//@ needs-subprocess use std::{env, process}; diff --git a/tests/ui/print_type_sizes/anonymous.rs b/tests/ui/print_type_sizes/anonymous.rs index a3a32228088..7819e5ea767 100644 --- a/tests/ui/print_type_sizes/anonymous.rs +++ b/tests/ui/print_type_sizes/anonymous.rs @@ -1,14 +1,13 @@ -//@ compile-flags: -Z print-type-sizes +//@ compile-flags: -Z print-type-sizes --crate-type=lib //@ build-pass // All of the types that occur in this function are uninteresting, in // that one cannot control the sizes of these types with the same sort // of enum-variant manipulation tricks. -#![feature(start)] +#![no_std] -#[start] -fn start(_: isize, _: *const *const u8) -> isize { +pub fn main() -> isize { let _byte: u8 = 0; let _word: usize = 0; let _tuple: (u8, usize)= (0, 0); diff --git a/tests/ui/privacy/privacy1.rs b/tests/ui/privacy/privacy1.rs index 31f39601003..9436441ecc6 100644 --- a/tests/ui/privacy/privacy1.rs +++ b/tests/ui/privacy/privacy1.rs @@ -1,4 +1,4 @@ -#![feature(lang_items, start, no_core)] +#![feature(lang_items, no_core)] #![no_core] // makes debugging this test *a lot* easier (during resolve) #[lang="sized"] @@ -173,4 +173,4 @@ pub mod mytest { } } -#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } +fn main() {} diff --git a/tests/ui/privacy/privacy2.rs b/tests/ui/privacy/privacy2.rs index 33292a65c5d..ab6d805544e 100644 --- a/tests/ui/privacy/privacy2.rs +++ b/tests/ui/privacy/privacy2.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes -#![feature(start, no_core)] +#![feature(no_core)] #![no_core] // makes debugging this test *a lot* easier (during resolve) // Test to make sure that globs don't leak in regular `use` statements. @@ -26,4 +26,4 @@ fn test2() { //~^ ERROR `foo` is private } -#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } +fn main() {} diff --git a/tests/ui/privacy/privacy3.rs b/tests/ui/privacy/privacy3.rs index fb1f432410d..6298a6bc8cf 100644 --- a/tests/ui/privacy/privacy3.rs +++ b/tests/ui/privacy/privacy3.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Zdeduplicate-diagnostics=yes -#![feature(start, no_core)] +#![feature( no_core)] #![no_core] // makes debugging this test *a lot* easier (during resolve) // Test to make sure that private items imported through globs remain private @@ -26,4 +26,4 @@ fn test1() { gpriv(); } -#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } +fn main() {} diff --git a/tests/ui/privacy/privacy4.rs b/tests/ui/privacy/privacy4.rs index fa257b80039..7341c7752bb 100644 --- a/tests/ui/privacy/privacy4.rs +++ b/tests/ui/privacy/privacy4.rs @@ -1,4 +1,4 @@ -#![feature(lang_items, start, no_core)] +#![feature(lang_items, no_core)] #![no_core] // makes debugging this test *a lot* easier (during resolve) #[lang = "sized"] pub trait Sized {} @@ -22,4 +22,4 @@ fn test2() { gpriv(); } -#[start] fn main(_: isize, _: *const *const u8) -> isize { 3 } +fn main() {} diff --git a/tests/ui/privacy/private-struct-field-ctor.stderr b/tests/ui/privacy/private-struct-field-ctor.stderr index 2a35537237a..8eb1bf7990b 100644 --- a/tests/ui/privacy/private-struct-field-ctor.stderr +++ b/tests/ui/privacy/private-struct-field-ctor.stderr @@ -2,7 +2,7 @@ error[E0451]: field `x` of struct `Foo` is private --> $DIR/private-struct-field-ctor.rs:8:22 | LL | let s = a::Foo { x: 1 }; - | ^^^^ private field + | ^ private field error: aborting due to 1 previous error diff --git a/tests/ui/privacy/private-struct-field-pattern.stderr b/tests/ui/privacy/private-struct-field-pattern.stderr index de24d1e0962..5609596721d 100644 --- a/tests/ui/privacy/private-struct-field-pattern.stderr +++ b/tests/ui/privacy/private-struct-field-pattern.stderr @@ -2,7 +2,7 @@ error[E0451]: field `x` of struct `Foo` is private --> $DIR/private-struct-field-pattern.rs:15:15 | LL | Foo { x: _ } => {} - | ^^^^ private field + | ^ private field error: aborting due to 1 previous error diff --git a/tests/ui/privacy/restricted/struct-literal-field.stderr b/tests/ui/privacy/restricted/struct-literal-field.stderr index dcdadf1da4b..e1cf7c2fadb 100644 --- a/tests/ui/privacy/restricted/struct-literal-field.stderr +++ b/tests/ui/privacy/restricted/struct-literal-field.stderr @@ -2,7 +2,7 @@ error[E0451]: field `x` of struct `S` is private --> $DIR/struct-literal-field.rs:18:9 | LL | S { x: 0 }; - | ^^^^ private field + | ^ private field error: aborting due to 1 previous error diff --git a/tests/ui/privacy/restricted/test.rs b/tests/ui/privacy/restricted/test.rs index 3fdfd191b36..b32b9327f07 100644 --- a/tests/ui/privacy/restricted/test.rs +++ b/tests/ui/privacy/restricted/test.rs @@ -47,6 +47,6 @@ fn main() { } mod pathological { - pub(in bad::path) mod m1 {} //~ ERROR failed to resolve: you might be missing crate `bad` + pub(in bad::path) mod m1 {} //~ ERROR failed to resolve: use of unresolved module or unlinked crate `bad` pub(in foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules } diff --git a/tests/ui/privacy/restricted/test.stderr b/tests/ui/privacy/restricted/test.stderr index 5deaffbdbf3..2744b3708a8 100644 --- a/tests/ui/privacy/restricted/test.stderr +++ b/tests/ui/privacy/restricted/test.stderr @@ -1,10 +1,10 @@ -error[E0433]: failed to resolve: you might be missing crate `bad` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `bad` --> $DIR/test.rs:50:12 | LL | pub(in bad::path) mod m1 {} - | ^^^ you might be missing crate `bad` + | ^^^ use of unresolved module or unlinked crate `bad` | -help: consider importing the `bad` crate +help: you might be missing a crate named `bad`, add it to your project and import it in your code | LL + extern crate bad; | diff --git a/tests/ui/privacy/union-field-privacy-1.stderr b/tests/ui/privacy/union-field-privacy-1.stderr index b1f0b785ea7..6f883b16d02 100644 --- a/tests/ui/privacy/union-field-privacy-1.stderr +++ b/tests/ui/privacy/union-field-privacy-1.stderr @@ -2,7 +2,7 @@ error[E0451]: field `c` of union `U` is private --> $DIR/union-field-privacy-1.rs:12:20 | LL | let u = m::U { c: 0 }; - | ^^^^ private field + | ^ private field error[E0451]: field `c` of union `U` is private --> $DIR/union-field-privacy-1.rs:16:16 diff --git a/tests/ui/process/core-run-destroy.rs b/tests/ui/process/core-run-destroy.rs index 3f2ea0e8441..b4815c9dfbb 100644 --- a/tests/ui/process/core-run-destroy.rs +++ b/tests/ui/process/core-run-destroy.rs @@ -1,12 +1,11 @@ //@ run-pass #![allow(unused_must_use)] -#![allow(stable_features)] #![allow(deprecated)] #![allow(unused_imports)] + //@ compile-flags:--test -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-vxworks no 'cat' and 'sleep' //@ ignore-fuchsia no 'cat' diff --git a/tests/ui/process/env-args-reverse-iterator.rs b/tests/ui/process/env-args-reverse-iterator.rs index 830e9535466..f0afeeb22eb 100644 --- a/tests/ui/process/env-args-reverse-iterator.rs +++ b/tests/ui/process/env-args-reverse-iterator.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env::args; use std::process::Command; diff --git a/tests/ui/process/fds-are-cloexec.rs b/tests/ui/process/fds-are-cloexec.rs index e7b000b2c49..f6678379dd6 100644 --- a/tests/ui/process/fds-are-cloexec.rs +++ b/tests/ui/process/fds-are-cloexec.rs @@ -1,9 +1,8 @@ //@ run-pass -//@ ignore-windows +//@ only-unix //@ ignore-android -//@ ignore-wasm32 no processes +//@ needs-subprocess //@ ignore-haiku -//@ ignore-sgx no processes #![feature(rustc_private)] diff --git a/tests/ui/process/inherit-env.rs b/tests/ui/process/inherit-env.rs index 0eb61fcdd53..09d5b76141e 100644 --- a/tests/ui/process/inherit-env.rs +++ b/tests/ui/process/inherit-env.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no subprocess support -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; use std::process::Command; diff --git a/tests/ui/process/issue-13304.rs b/tests/ui/process/issue-13304.rs index 6dbf0caaaec..621c54300d3 100644 --- a/tests/ui/process/issue-13304.rs +++ b/tests/ui/process/issue-13304.rs @@ -1,7 +1,5 @@ //@ run-pass -#![allow(unused_mut)] -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; use std::io::prelude::*; @@ -32,7 +30,7 @@ fn parent() { } fn child() { - let mut stdin = io::stdin(); + let stdin = io::stdin(); for line in stdin.lock().lines() { println!("{}", line.unwrap()); } diff --git a/tests/ui/process/issue-14456.rs b/tests/ui/process/issue-14456.rs index fd6da8a5fc4..e67a9d8bad5 100644 --- a/tests/ui/process/issue-14456.rs +++ b/tests/ui/process/issue-14456.rs @@ -1,7 +1,5 @@ //@ run-pass -#![allow(unused_mut)] -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; use std::io::prelude::*; @@ -20,7 +18,7 @@ fn main() { fn child() { writeln!(&mut io::stdout(), "foo").unwrap(); writeln!(&mut io::stderr(), "bar").unwrap(); - let mut stdin = io::stdin(); + let stdin = io::stdin(); let mut s = String::new(); stdin.lock().read_line(&mut s).unwrap(); assert_eq!(s.len(), 0); diff --git a/tests/ui/process/issue-14940.rs b/tests/ui/process/issue-14940.rs index 13fb18154a0..cfbc743250f 100644 --- a/tests/ui/process/issue-14940.rs +++ b/tests/ui/process/issue-14940.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; use std::process::Command; diff --git a/tests/ui/process/issue-16272.rs b/tests/ui/process/issue-16272.rs index bf26769d494..72708554753 100644 --- a/tests/ui/process/issue-16272.rs +++ b/tests/ui/process/issue-16272.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::process::Command; use std::env; diff --git a/tests/ui/process/issue-20091.rs b/tests/ui/process/issue-20091.rs index b6d94661b75..72bf4c0e71e 100644 --- a/tests/ui/process/issue-20091.rs +++ b/tests/ui/process/issue-20091.rs @@ -1,9 +1,5 @@ //@ run-pass -#![allow(stable_features)] -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes - -#![feature(os)] +//@ needs-subprocess #[cfg(unix)] fn main() { diff --git a/tests/ui/process/issue-30490.rs b/tests/ui/process/issue-30490.rs index 0d918bc3dd5..75b36e7c20b 100644 --- a/tests/ui/process/issue-30490.rs +++ b/tests/ui/process/issue-30490.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-emscripten no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia Child I/O swaps not privileged // Previously libstd would set stdio descriptors of a child process diff --git a/tests/ui/process/multi-panic.rs b/tests/ui/process/multi-panic.rs index ad47925a149..481fe75c731 100644 --- a/tests/ui/process/multi-panic.rs +++ b/tests/ui/process/multi-panic.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ needs-unwind fn check_for_no_backtrace(test: std::process::Output) { diff --git a/tests/ui/process/no-stdio.rs b/tests/ui/process/no-stdio.rs index 8eebf6dbc7d..5cc7cacbb22 100644 --- a/tests/ui/process/no-stdio.rs +++ b/tests/ui/process/no-stdio.rs @@ -1,7 +1,6 @@ //@ run-pass //@ ignore-android -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess #![feature(rustc_private)] diff --git a/tests/ui/process/println-with-broken-pipe.rs b/tests/ui/process/println-with-broken-pipe.rs index d88c6dcc12b..fbac9b6cd95 100644 --- a/tests/ui/process/println-with-broken-pipe.rs +++ b/tests/ui/process/println-with-broken-pipe.rs @@ -1,7 +1,7 @@ //@ run-pass //@ check-run-results +//@ needs-subprocess //@ ignore-windows -//@ ignore-wasm32 //@ ignore-fuchsia //@ ignore-horizon //@ ignore-android diff --git a/tests/ui/process/process-envs.rs b/tests/ui/process/process-envs.rs index 15285960d16..98052f1d3a5 100644 --- a/tests/ui/process/process-envs.rs +++ b/tests/ui/process/process-envs.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-vxworks no 'env' //@ ignore-fuchsia no 'env' diff --git a/tests/ui/process/process-exit.rs b/tests/ui/process/process-exit.rs index a75a7306cbc..a1ed243b62b 100644 --- a/tests/ui/process/process-exit.rs +++ b/tests/ui/process/process-exit.rs @@ -1,10 +1,8 @@ //@ run-pass -#![allow(unused_imports)] -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; -use std::process::{self, Command, Stdio}; +use std::process::{self, Command}; fn main() { let args: Vec<String> = env::args().collect(); diff --git a/tests/ui/process/process-panic-after-fork.rs b/tests/ui/process/process-panic-after-fork.rs index afb1b721182..6e0267e0a54 100644 --- a/tests/ui/process/process-panic-after-fork.rs +++ b/tests/ui/process/process-panic-after-fork.rs @@ -1,8 +1,7 @@ //@ run-pass //@ no-prefer-dynamic -//@ ignore-windows -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ only-unix +//@ needs-subprocess //@ ignore-fuchsia no fork #![feature(rustc_private)] diff --git a/tests/ui/process/process-remove-from-env.rs b/tests/ui/process/process-remove-from-env.rs index 21fff4fd45d..c1a2b2daf5b 100644 --- a/tests/ui/process/process-remove-from-env.rs +++ b/tests/ui/process/process-remove-from-env.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-vxworks no 'env' //@ ignore-fuchsia no 'env' diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs index 9db130c26bd..453e53379fc 100644 --- a/tests/ui/process/process-sigpipe.rs +++ b/tests/ui/process/process-sigpipe.rs @@ -15,7 +15,7 @@ //@ ignore-vxworks no 'sh' //@ ignore-fuchsia no 'sh' -//@ ignore-emscripten No threads +//@ needs-threads //@ only-unix SIGPIPE is a unix feature use std::process; diff --git a/tests/ui/process/process-spawn-nonexistent.rs b/tests/ui/process/process-spawn-nonexistent.rs index 1cd32866299..3db670624fb 100644 --- a/tests/ui/process/process-spawn-nonexistent.rs +++ b/tests/ui/process/process-spawn-nonexistent.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia ErrorKind not translated use std::io::ErrorKind; diff --git a/tests/ui/process/process-spawn-with-unicode-params.rs b/tests/ui/process/process-spawn-with-unicode-params.rs index 4d2ba49eeac..65f835c1345 100644 --- a/tests/ui/process/process-spawn-with-unicode-params.rs +++ b/tests/ui/process/process-spawn-with-unicode-params.rs @@ -7,8 +7,7 @@ // non-ASCII characters. The child process ensures all the strings are // intact. -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia Filesystem manipulation privileged use std::io::prelude::*; diff --git a/tests/ui/process/process-status-inherits-stdin.rs b/tests/ui/process/process-status-inherits-stdin.rs index 39eef34c5f8..d5dd0e55fa3 100644 --- a/tests/ui/process/process-status-inherits-stdin.rs +++ b/tests/ui/process/process-status-inherits-stdin.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; use std::io; diff --git a/tests/ui/process/signal-exit-status.rs b/tests/ui/process/signal-exit-status.rs index a6acea47636..33aa83abfc3 100644 --- a/tests/ui/process/signal-exit-status.rs +++ b/tests/ui/process/signal-exit-status.rs @@ -1,7 +1,6 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes -//@ ignore-windows +//@ needs-subprocess +//@ only-unix (`code()` returns `None` if terminated by a signal on Unix) //@ ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#58590) #![feature(core_intrinsics)] diff --git a/tests/ui/process/sigpipe-should-be-ignored.rs b/tests/ui/process/sigpipe-should-be-ignored.rs index 44785bee7f8..3dcf0117ae9 100644 --- a/tests/ui/process/sigpipe-should-be-ignored.rs +++ b/tests/ui/process/sigpipe-should-be-ignored.rs @@ -1,12 +1,9 @@ //@ run-pass +//@ needs-subprocess -#![allow(unused_must_use)] // Be sure that when a SIGPIPE would have been received that the entire process // doesn't die in a ball of fire, but rather it's gracefully handled. -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes - use std::env; use std::io::prelude::*; use std::io; @@ -14,7 +11,7 @@ use std::process::{Command, Stdio}; fn test() { let _ = io::stdin().read_line(&mut String::new()); - io::stdout().write(&[1]); + io::stdout().write(&[1]).unwrap(); assert!(io::stdout().flush().is_err()); } diff --git a/tests/ui/process/tls-exit-status.rs b/tests/ui/process/tls-exit-status.rs index cddcf369da0..6dd0d71ef35 100644 --- a/tests/ui/process/tls-exit-status.rs +++ b/tests/ui/process/tls-exit-status.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:nonzero //@ exec-env:RUST_NEWRT=1 -//@ ignore-wasm32 no processes +//@ needs-subprocess use std::env; diff --git a/tests/ui/process/try-wait.rs b/tests/ui/process/try-wait.rs index b6d026d802f..dcef43ad348 100644 --- a/tests/ui/process/try-wait.rs +++ b/tests/ui/process/try-wait.rs @@ -1,9 +1,5 @@ //@ run-pass - -#![allow(stable_features)] -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes -#![feature(process_try_wait)] +//@ needs-subprocess use std::env; use std::process::Command; diff --git a/tests/ui/reachable/issue-948.rs b/tests/ui/reachable/issue-948.rs index 8e239a1115e..6181e547acc 100644 --- a/tests/ui/reachable/issue-948.rs +++ b/tests/ui/reachable/issue-948.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:beep boop -//@ ignore-emscripten no processes +//@ needs-subprocess #![allow(unused_variables)] diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr deleted file mode 100644 index ff1a127e63e..00000000000 --- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.polonius.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: reached the recursion limit while instantiating `std::ptr::drop_in_place::<S<fn(f...)))))))))))))))))))))))))))))>))` - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | -LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: `std::ptr::drop_in_place` defined here - --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL - | -LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-38591-non-regular-dropck-recursion.polonius/issue-38591-non-regular-dropck-recursion.long-type.txt' - -error: aborting due to 1 previous error - diff --git a/tests/ui/recursion/recursion.polonius.stderr b/tests/ui/recursion/recursion.polonius.stderr deleted file mode 100644 index 737e71e8845..00000000000 --- a/tests/ui/recursion/recursion.polonius.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: reached the recursion limit while instantiating `test::<Cons<Cons<Cons<Cons<Cons<...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/recursion.rs:18:11 - | -LL | _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: `test` defined here - --> $DIR/recursion.rs:16:1 - | -LL | fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/recursion.polonius/recursion.long-type.txt' - -error: aborting due to 1 previous error - diff --git a/tests/ui/resolve/112590-2.stderr b/tests/ui/resolve/112590-2.stderr index 0db20249d27..b39b44396d7 100644 --- a/tests/ui/resolve/112590-2.stderr +++ b/tests/ui/resolve/112590-2.stderr @@ -14,12 +14,13 @@ LL - let _: Vec<i32> = super::foo::baf::baz::MyVec::new(); LL + let _: Vec<i32> = MyVec::new(); | -error[E0433]: failed to resolve: use of undeclared crate or module `fox` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `fox` --> $DIR/112590-2.rs:18:27 | LL | let _: Vec<i32> = fox::bar::baz::MyVec::new(); - | ^^^ use of undeclared crate or module `fox` + | ^^^ use of unresolved module or unlinked crate `fox` | + = help: you might be missing a crate named `fox` help: consider importing this struct through its public re-export | LL + use foo::bar::baz::MyVec; @@ -30,12 +31,13 @@ LL - let _: Vec<i32> = fox::bar::baz::MyVec::new(); LL + let _: Vec<i32> = MyVec::new(); | -error[E0433]: failed to resolve: use of undeclared crate or module `vec` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `vec` --> $DIR/112590-2.rs:24:15 | LL | type _B = vec::Vec::<u8>; - | ^^^ use of undeclared crate or module `vec` + | ^^^ use of unresolved module or unlinked crate `vec` | + = help: you might be missing a crate named `vec` help: consider importing this module | LL + use std::vec; @@ -57,14 +59,16 @@ LL - let _t = std::sync_error::atomic::AtomicBool::new(true); LL + let _t = AtomicBool::new(true); | -error[E0433]: failed to resolve: use of undeclared crate or module `vec` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `vec` --> $DIR/112590-2.rs:23:24 | LL | let _t: Vec<i32> = vec::new(); | ^^^ | | - | use of undeclared crate or module `vec` + | use of unresolved module or unlinked crate `vec` | help: a struct with a similar name exists (notice the capitalization): `Vec` + | + = help: you might be missing a crate named `vec` error: aborting due to 5 previous errors diff --git a/tests/ui/resolve/auxiliary/fake_matches.rs b/tests/ui/resolve/auxiliary/fake_matches.rs new file mode 100644 index 00000000000..6d42972cbac --- /dev/null +++ b/tests/ui/resolve/auxiliary/fake_matches.rs @@ -0,0 +1,13 @@ +// Helper for test tests/ui/resolve/const-with-typo-in-pattern-binding-ice-135289.rs + +//@ edition: 2018 + +#[macro_export] +macro_rules! assert_matches { + ( $e:expr , $($pat:pat)|+ ) => { + match $e { + $($pat)|+ => (), + _ => (), + } + }; +} diff --git a/tests/ui/resolve/bad-module.rs b/tests/ui/resolve/bad-module.rs index b23e97c2cf6..9fe06ab0f52 100644 --- a/tests/ui/resolve/bad-module.rs +++ b/tests/ui/resolve/bad-module.rs @@ -1,7 +1,7 @@ fn main() { let foo = thing::len(Vec::new()); - //~^ ERROR failed to resolve: use of undeclared crate or module `thing` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `thing` let foo = foo::bar::baz(); - //~^ ERROR failed to resolve: use of undeclared crate or module `foo` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `foo` } diff --git a/tests/ui/resolve/bad-module.stderr b/tests/ui/resolve/bad-module.stderr index 558760c6793..0f597e126fd 100644 --- a/tests/ui/resolve/bad-module.stderr +++ b/tests/ui/resolve/bad-module.stderr @@ -1,14 +1,18 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `foo` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `foo` --> $DIR/bad-module.rs:5:15 | LL | let foo = foo::bar::baz(); - | ^^^ use of undeclared crate or module `foo` + | ^^^ use of unresolved module or unlinked crate `foo` + | + = help: you might be missing a crate named `foo` -error[E0433]: failed to resolve: use of undeclared crate or module `thing` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `thing` --> $DIR/bad-module.rs:2:15 | LL | let foo = thing::len(Vec::new()); - | ^^^^^ use of undeclared crate or module `thing` + | ^^^^^ use of unresolved module or unlinked crate `thing` + | + = help: you might be missing a crate named `thing` error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/const-with-typo-in-pattern-binding-ice-135289.rs b/tests/ui/resolve/const-with-typo-in-pattern-binding-ice-135289.rs new file mode 100644 index 00000000000..8267a9250ec --- /dev/null +++ b/tests/ui/resolve/const-with-typo-in-pattern-binding-ice-135289.rs @@ -0,0 +1,17 @@ +// This is a non-regression test for issue 135289, where the "const with typo in pattern" diagnostic +// caused an ICE when unexpectedly pretty printing a type for unreachable arms via a macro defined +// in a dependency. + +#![warn(unreachable_patterns)] // needed to reproduce the ICE described in #135289 + +//@ check-pass +//@ aux-build: fake_matches.rs +extern crate fake_matches; + +const _A: u64 = 0; +pub fn f() -> u64 { + 0 +} +fn main() { + fake_matches::assert_matches!(f(), _non_existent); +} diff --git a/tests/ui/resolve/editions-crate-root-2015.rs b/tests/ui/resolve/editions-crate-root-2015.rs index 869f4c82c8b..a2e19bfdf1c 100644 --- a/tests/ui/resolve/editions-crate-root-2015.rs +++ b/tests/ui/resolve/editions-crate-root-2015.rs @@ -2,10 +2,10 @@ mod inner { fn global_inner(_: ::nonexistant::Foo) { - //~^ ERROR failed to resolve: you might be missing crate `nonexistant` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `nonexistant` } fn crate_inner(_: crate::nonexistant::Foo) { - //~^ ERROR failed to resolve: you might be missing crate `nonexistant` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `nonexistant` } fn bare_global(_: ::nonexistant) { diff --git a/tests/ui/resolve/editions-crate-root-2015.stderr b/tests/ui/resolve/editions-crate-root-2015.stderr index 7a842aca0fd..3d203c8ed96 100644 --- a/tests/ui/resolve/editions-crate-root-2015.stderr +++ b/tests/ui/resolve/editions-crate-root-2015.stderr @@ -1,21 +1,21 @@ -error[E0433]: failed to resolve: you might be missing crate `nonexistant` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `nonexistant` --> $DIR/editions-crate-root-2015.rs:4:26 | LL | fn global_inner(_: ::nonexistant::Foo) { - | ^^^^^^^^^^^ you might be missing crate `nonexistant` + | ^^^^^^^^^^^ use of unresolved module or unlinked crate `nonexistant` | -help: consider importing the `nonexistant` crate +help: you might be missing a crate named `nonexistant`, add it to your project and import it in your code | LL + extern crate nonexistant; | -error[E0433]: failed to resolve: you might be missing crate `nonexistant` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `nonexistant` --> $DIR/editions-crate-root-2015.rs:7:30 | LL | fn crate_inner(_: crate::nonexistant::Foo) { - | ^^^^^^^^^^^ you might be missing crate `nonexistant` + | ^^^^^^^^^^^ use of unresolved module or unlinked crate `nonexistant` | -help: consider importing the `nonexistant` crate +help: you might be missing a crate named `nonexistant`, add it to your project and import it in your code | LL + extern crate nonexistant; | diff --git a/tests/ui/resolve/export-fully-qualified-2018.rs b/tests/ui/resolve/export-fully-qualified-2018.rs index 26e3044d8df..ce78b64bf25 100644 --- a/tests/ui/resolve/export-fully-qualified-2018.rs +++ b/tests/ui/resolve/export-fully-qualified-2018.rs @@ -5,7 +5,7 @@ // want to change eventually. mod foo { - pub fn bar() { foo::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `foo` + pub fn bar() { foo::baz(); } //~ ERROR failed to resolve: use of unresolved module or unlinked crate `foo` fn baz() { } } diff --git a/tests/ui/resolve/export-fully-qualified-2018.stderr b/tests/ui/resolve/export-fully-qualified-2018.stderr index 378d9832a65..a985669b8b4 100644 --- a/tests/ui/resolve/export-fully-qualified-2018.stderr +++ b/tests/ui/resolve/export-fully-qualified-2018.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `foo` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `foo` --> $DIR/export-fully-qualified-2018.rs:8:20 | LL | pub fn bar() { foo::baz(); } - | ^^^ use of undeclared crate or module `foo` + | ^^^ use of unresolved module or unlinked crate `foo` + | + = help: you might be missing a crate named `foo` error: aborting due to 1 previous error diff --git a/tests/ui/resolve/export-fully-qualified.rs b/tests/ui/resolve/export-fully-qualified.rs index 6de33b7e191..0be3b81ebb8 100644 --- a/tests/ui/resolve/export-fully-qualified.rs +++ b/tests/ui/resolve/export-fully-qualified.rs @@ -5,7 +5,7 @@ // want to change eventually. mod foo { - pub fn bar() { foo::baz(); } //~ ERROR failed to resolve: use of undeclared crate or module `foo` + pub fn bar() { foo::baz(); } //~ ERROR failed to resolve: use of unresolved module or unlinked crate `foo` fn baz() { } } diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr index 869149d8d3c..e65483e57eb 100644 --- a/tests/ui/resolve/export-fully-qualified.stderr +++ b/tests/ui/resolve/export-fully-qualified.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `foo` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `foo` --> $DIR/export-fully-qualified.rs:8:20 | LL | pub fn bar() { foo::baz(); } - | ^^^ use of undeclared crate or module `foo` + | ^^^ use of unresolved module or unlinked crate `foo` + | + = help: you might be missing a crate named `foo` error: aborting due to 1 previous error diff --git a/tests/ui/resolve/extern-prelude-fail.stderr b/tests/ui/resolve/extern-prelude-fail.stderr index 77c10f5f995..199a31244c0 100644 --- a/tests/ui/resolve/extern-prelude-fail.stderr +++ b/tests/ui/resolve/extern-prelude-fail.stderr @@ -2,20 +2,20 @@ error[E0432]: unresolved import `extern_prelude` --> $DIR/extern-prelude-fail.rs:7:9 | LL | use extern_prelude::S; - | ^^^^^^^^^^^^^^ you might be missing crate `extern_prelude` + | ^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `extern_prelude` | -help: consider importing the `extern_prelude` crate +help: you might be missing a crate named `extern_prelude`, add it to your project and import it in your code | LL + extern crate extern_prelude; | -error[E0433]: failed to resolve: you might be missing crate `extern_prelude` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `extern_prelude` --> $DIR/extern-prelude-fail.rs:8:15 | LL | let s = ::extern_prelude::S; - | ^^^^^^^^^^^^^^ you might be missing crate `extern_prelude` + | ^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `extern_prelude` | -help: consider importing the `extern_prelude` crate +help: you might be missing a crate named `extern_prelude`, add it to your project and import it in your code | LL + extern crate extern_prelude; | diff --git a/tests/ui/resolve/issue-101749-2.rs b/tests/ui/resolve/issue-101749-2.rs index 4d3d469447c..636ff07c71c 100644 --- a/tests/ui/resolve/issue-101749-2.rs +++ b/tests/ui/resolve/issue-101749-2.rs @@ -12,5 +12,5 @@ fn main() { let rect = Rectangle::new(3, 4); // `area` is not implemented for `Rectangle`, so this should not suggest let _ = rect::area(); - //~^ ERROR failed to resolve: use of undeclared crate or module `rect` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `rect` } diff --git a/tests/ui/resolve/issue-101749-2.stderr b/tests/ui/resolve/issue-101749-2.stderr index 300aaf26cb7..96a20b4bf5a 100644 --- a/tests/ui/resolve/issue-101749-2.stderr +++ b/tests/ui/resolve/issue-101749-2.stderr @@ -1,8 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `rect` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `rect` --> $DIR/issue-101749-2.rs:14:13 | LL | let _ = rect::area(); - | ^^^^ use of undeclared crate or module `rect` + | ^^^^ use of unresolved module or unlinked crate `rect` + | + = help: you might be missing a crate named `rect` error: aborting due to 1 previous error diff --git a/tests/ui/resolve/issue-101749.fixed b/tests/ui/resolve/issue-101749.fixed index 97815793d29..3244ad7a031 100644 --- a/tests/ui/resolve/issue-101749.fixed +++ b/tests/ui/resolve/issue-101749.fixed @@ -15,5 +15,5 @@ impl Rectangle { fn main() { let rect = Rectangle::new(3, 4); let _ = rect.area(); - //~^ ERROR failed to resolve: use of undeclared crate or module `rect` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `rect` } diff --git a/tests/ui/resolve/issue-101749.rs b/tests/ui/resolve/issue-101749.rs index 994fc86778e..c977df41d2f 100644 --- a/tests/ui/resolve/issue-101749.rs +++ b/tests/ui/resolve/issue-101749.rs @@ -15,5 +15,5 @@ impl Rectangle { fn main() { let rect = Rectangle::new(3, 4); let _ = rect::area(); - //~^ ERROR failed to resolve: use of undeclared crate or module `rect` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `rect` } diff --git a/tests/ui/resolve/issue-101749.stderr b/tests/ui/resolve/issue-101749.stderr index 05515b1b460..fedbf182ee8 100644 --- a/tests/ui/resolve/issue-101749.stderr +++ b/tests/ui/resolve/issue-101749.stderr @@ -1,9 +1,10 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `rect` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `rect` --> $DIR/issue-101749.rs:17:13 | LL | let _ = rect::area(); - | ^^^^ use of undeclared crate or module `rect` + | ^^^^ use of unresolved module or unlinked crate `rect` | + = help: you might be missing a crate named `rect` help: you may have meant to call an instance method | LL | let _ = rect.area(); diff --git a/tests/ui/resolve/issue-3907-2.stderr b/tests/ui/resolve/issue-3907-2.stderr index 7c47c5973e3..4ab72a42eb8 100644 --- a/tests/ui/resolve/issue-3907-2.stderr +++ b/tests/ui/resolve/issue-3907-2.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `issue_3907::Foo` cannot be made into an object +error[E0038]: the trait `issue_3907::Foo` is not dyn compatible --> $DIR/issue-3907-2.rs:11:12 | LL | fn bar(_x: Foo) {} - | ^^^ `issue_3907::Foo` cannot be made into an object + | ^^^ `issue_3907::Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/auxiliary/issue-3907.rs:2:8 | LL | fn bar(); - | ^^^ the trait cannot be made into an object because associated function `bar` has no `self` parameter + | ^^^ the trait is not dyn compatible because associated function `bar` has no `self` parameter error[E0277]: the size for values of type `(dyn issue_3907::Foo + 'static)` cannot be known at compilation time --> $DIR/issue-3907-2.rs:11:12 diff --git a/tests/ui/resolve/issue-82865.rs b/tests/ui/resolve/issue-82865.rs index 29a898906e9..4dc12f2f589 100644 --- a/tests/ui/resolve/issue-82865.rs +++ b/tests/ui/resolve/issue-82865.rs @@ -2,7 +2,7 @@ #![feature(decl_macro)] -use x::y::z; //~ ERROR: failed to resolve: you might be missing crate `x` +use x::y::z; //~ ERROR: failed to resolve: use of unresolved module or unlinked crate `x` macro mac () { Box::z //~ ERROR: no function or associated item diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr index bc7e0f07981..090085460b0 100644 --- a/tests/ui/resolve/issue-82865.stderr +++ b/tests/ui/resolve/issue-82865.stderr @@ -1,10 +1,10 @@ -error[E0433]: failed to resolve: you might be missing crate `x` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `x` --> $DIR/issue-82865.rs:5:5 | LL | use x::y::z; - | ^ you might be missing crate `x` + | ^ use of unresolved module or unlinked crate `x` | -help: consider importing the `x` crate +help: you might be missing a crate named `x`, add it to your project and import it in your code | LL + extern crate x; | diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr index 804fa079bb9..ac6307c7a69 100644 --- a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr +++ b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr @@ -21,7 +21,7 @@ Box<dyn Any> query stack during panic: #0 [mir_built] building MIR for `<impl at $DIR/multiple_definitions_attribute_merging.rs:15:10: 15:19>::eq` #1 [check_unsafety] unsafety-checking `<impl at $DIR/multiple_definitions_attribute_merging.rs:15:10: 15:19>::eq` -end of query stack +... and 1 other queries... use `env RUST_BACKTRACE=1` to see the full query stack error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/resolve/proc_macro_generated_packed.stderr b/tests/ui/resolve/proc_macro_generated_packed.stderr index a5a02c9c393..8b700595034 100644 --- a/tests/ui/resolve/proc_macro_generated_packed.stderr +++ b/tests/ui/resolve/proc_macro_generated_packed.stderr @@ -12,6 +12,6 @@ Box<dyn Any> query stack during panic: #0 [mir_built] building MIR for `<impl at $DIR/proc_macro_generated_packed.rs:15:10: 15:19>::eq` #1 [check_unsafety] unsafety-checking `<impl at $DIR/proc_macro_generated_packed.rs:15:10: 15:19>::eq` -end of query stack +... and 1 other queries... use `env RUST_BACKTRACE=1` to see the full query stack error: aborting due to 1 previous error diff --git a/tests/ui/resolve/resolve-bad-visibility.stderr b/tests/ui/resolve/resolve-bad-visibility.stderr index 281e5afb223..ac7e1c735b1 100644 --- a/tests/ui/resolve/resolve-bad-visibility.stderr +++ b/tests/ui/resolve/resolve-bad-visibility.stderr @@ -16,24 +16,24 @@ error[E0742]: visibilities can only be restricted to ancestor modules LL | pub(in std::vec) struct F; | ^^^^^^^^ -error[E0433]: failed to resolve: you might be missing crate `nonexistent` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `nonexistent` --> $DIR/resolve-bad-visibility.rs:7:8 | LL | pub(in nonexistent) struct G; - | ^^^^^^^^^^^ you might be missing crate `nonexistent` + | ^^^^^^^^^^^ use of unresolved module or unlinked crate `nonexistent` | -help: consider importing the `nonexistent` crate +help: you might be missing a crate named `nonexistent`, add it to your project and import it in your code | LL + extern crate nonexistent; | -error[E0433]: failed to resolve: you might be missing crate `too_soon` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `too_soon` --> $DIR/resolve-bad-visibility.rs:8:8 | LL | pub(in too_soon) struct H; - | ^^^^^^^^ you might be missing crate `too_soon` + | ^^^^^^^^ use of unresolved module or unlinked crate `too_soon` | -help: consider importing the `too_soon` crate +help: you might be missing a crate named `too_soon`, add it to your project and import it in your code | LL + extern crate too_soon; | diff --git a/tests/ui/resolve/typo-suggestion-mistyped-in-path.rs b/tests/ui/resolve/typo-suggestion-mistyped-in-path.rs index 3ce17a14f14..188e2ca7f11 100644 --- a/tests/ui/resolve/typo-suggestion-mistyped-in-path.rs +++ b/tests/ui/resolve/typo-suggestion-mistyped-in-path.rs @@ -29,8 +29,8 @@ fn main() { //~| NOTE use of undeclared type `Struc` modul::foo(); - //~^ ERROR failed to resolve: use of undeclared crate or module `modul` - //~| NOTE use of undeclared crate or module `modul` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `modul` + //~| NOTE use of unresolved module or unlinked crate `modul` module::Struc::foo(); //~^ ERROR failed to resolve: could not find `Struc` in `module` diff --git a/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr b/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr index f4fb7fd955f..3ae134e43bc 100644 --- a/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr +++ b/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr @@ -30,11 +30,11 @@ LL | Struc::foo(); | use of undeclared type `Struc` | help: a struct with a similar name exists: `Struct` -error[E0433]: failed to resolve: use of undeclared crate or module `modul` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `modul` --> $DIR/typo-suggestion-mistyped-in-path.rs:31:5 | LL | modul::foo(); - | ^^^^^ use of undeclared crate or module `modul` + | ^^^^^ use of unresolved module or unlinked crate `modul` | help: there is a crate or module with a similar name | diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.rs b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.rs new file mode 100644 index 00000000000..2a7e730af16 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.rs @@ -0,0 +1,12 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum E { A } + +fn main() { + match E::A { + ! | //~ ERROR: a trailing `|` is not allowed in an or-pattern + //~^ ERROR: mismatched types + if true => {} //~ ERROR: a never pattern is always unreachable + } +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.stderr new file mode 100644 index 00000000000..26731e29ffc --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-130779-never-arm-no-oatherwise-block.stderr @@ -0,0 +1,33 @@ +error: a trailing `|` is not allowed in an or-pattern + --> $DIR/ICE-130779-never-arm-no-oatherwise-block.rs:8:11 + | +LL | ! | + | - ^ + | | + | while parsing this or-pattern starting here + | +help: remove the `|` + | +LL - ! | +LL + ! + | + +error: a never pattern is always unreachable + --> $DIR/ICE-130779-never-arm-no-oatherwise-block.rs:10:20 + | +LL | if true => {} + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: mismatched types + --> $DIR/ICE-130779-never-arm-no-oatherwise-block.rs:8:9 + | +LL | ! | + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `E` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133063-never-arm-no-otherwise-block.rs b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133063-never-arm-no-otherwise-block.rs new file mode 100644 index 00000000000..4f52f6ee4bd --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133063-never-arm-no-otherwise-block.rs @@ -0,0 +1,16 @@ +#![feature(never_type)] +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn foo(x: Void) { + loop { + match x { + (!|!) if false => {} //~ ERROR a never pattern is always unreachable + _ => {} + } + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133063-never-arm-no-otherwise-block.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133063-never-arm-no-otherwise-block.stderr new file mode 100644 index 00000000000..cc451fed318 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133063-never-arm-no-otherwise-block.stderr @@ -0,0 +1,11 @@ +error: a never pattern is always unreachable + --> $DIR/ICE-133063-never-arm-no-otherwise-block.rs:10:31 + | +LL | (!|!) if false => {} + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: aborting due to 1 previous error + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133117-duplicate-never-arm.rs b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133117-duplicate-never-arm.rs new file mode 100644 index 00000000000..bca2ab56570 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133117-duplicate-never-arm.rs @@ -0,0 +1,14 @@ +#![feature(never_type)] +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn foo(x: Void) { + match x { + (!|!) if true => {} //~ ERROR a never pattern is always unreachable + (!|!) if true => {} //~ ERROR a never pattern is always unreachable + } +} + +fn main() {} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133117-duplicate-never-arm.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133117-duplicate-never-arm.stderr new file mode 100644 index 00000000000..5da9642dc19 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/ICE-133117-duplicate-never-arm.stderr @@ -0,0 +1,20 @@ +error: a never pattern is always unreachable + --> $DIR/ICE-133117-duplicate-never-arm.rs:9:26 + | +LL | (!|!) if true => {} + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: a never pattern is always unreachable + --> $DIR/ICE-133117-duplicate-never-arm.rs:10:26 + | +LL | (!|!) if true => {} + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr deleted file mode 100644 index d78f4a5f6eb..00000000000 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.exh_pats.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error: unreachable pattern - --> $DIR/unreachable.rs:16:9 - | -LL | Err(!), - | ^^^^^^ - | - = note: this pattern matches no values because `Void` is uninhabited -note: the lint level is defined here - --> $DIR/unreachable.rs:6:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/unreachable.rs:19:19 - | -LL | let (Ok(_x) | Err(!)) = res_void; - | ^^^^^^ - | - = note: this pattern matches no values because `Void` is uninhabited - -error: unreachable pattern - --> $DIR/unreachable.rs:21:12 - | -LL | if let Err(!) = res_void {} - | ^^^^^^ - | - = note: this pattern matches no values because `Void` is uninhabited - -error: unreachable pattern - --> $DIR/unreachable.rs:23:24 - | -LL | if let (Ok(true) | Err(!)) = res_void {} - | ^^^^^^ - | - = note: this pattern matches no values because `Void` is uninhabited - -error: unreachable pattern - --> $DIR/unreachable.rs:25:23 - | -LL | for (Ok(mut _x) | Err(!)) in [res_void] {} - | ^^^^^^ - | - = note: this pattern matches no values because `Void` is uninhabited - -error: unreachable pattern - --> $DIR/unreachable.rs:29:18 - | -LL | fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {} - | ^^^^^^ - | - = note: this pattern matches no values because `Void` is uninhabited - -error: aborting due to 6 previous errors - diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.normal.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.normal.stderr deleted file mode 100644 index a3bf8e80ece..00000000000 --- a/tests/ui/rfcs/rfc-0000-never_patterns/unreachable.normal.stderr +++ /dev/null @@ -1,44 +0,0 @@ -error: unreachable pattern - --> $DIR/unreachable.rs:16:9 - | -LL | Err(!), - | ^^^^^^ - | -note: the lint level is defined here - --> $DIR/unreachable.rs:6:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/unreachable.rs:19:19 - | -LL | let (Ok(_x) | Err(!)) = res_void; - | ^^^^^^ - -error: unreachable pattern - --> $DIR/unreachable.rs:21:12 - | -LL | if let Err(!) = res_void {} - | ^^^^^^ - -error: unreachable pattern - --> $DIR/unreachable.rs:23:24 - | -LL | if let (Ok(true) | Err(!)) = res_void {} - | ^^^^^^ - -error: unreachable pattern - --> $DIR/unreachable.rs:25:23 - | -LL | for (Ok(mut _x) | Err(!)) in [res_void] {} - | ^^^^^^ - -error: unreachable pattern - --> $DIR/unreachable.rs:29:18 - | -LL | fn foo((Ok(_x) | Err(!)): Result<bool, Void>) {} - | ^^^^^^ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr deleted file mode 100644 index f2727336bc5..00000000000 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.current.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: the trait bound `Something: Termination` is not satisfied - --> $DIR/issue-103052-2.rs:15:22 - | -LL | fn main() -> Something { - | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` - | -note: required by a bound in `Main::main::{opaque#0}` - --> $DIR/issue-103052-2.rs:9:27 - | -LL | fn main() -> impl std::process::Termination; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr deleted file mode 100644 index 4bb420664f7..00000000000 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.next.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: the trait bound `Something: Termination` is not satisfied - --> $DIR/issue-103052-2.rs:15:22 - | -LL | fn main() -> Something { - | ^^^^^^^^^ the trait `Termination` is not implemented for `Something` - | -note: required by a bound in `Main::{opaque#0}` - --> $DIR/issue-103052-2.rs:9:27 - | -LL | fn main() -> impl std::process::Termination; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-err.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-err.rs index fb6718e55b2..00a0ea04c0d 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-err.rs +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-box-dyn-error-err.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:returned Box<dyn Error> from main() //@ failure-status: 1 -//@ ignore-emscripten no processes +//@ needs-subprocess use std::error::Error; use std::io; diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-never.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-never.rs index 91be3afbe22..3b80c2b49a5 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-never.rs +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-never.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:oh, dear -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() -> ! { panic!("oh, dear"); diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs index f1d972b3c55..48605309965 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern:returned Box<Error> from main() //@ failure-status: 1 -//@ ignore-emscripten no processes +//@ needs-subprocess use std::io::{Error, ErrorKind}; diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-err.rs b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-err.rs index acf3da2d55f..8f7b3da31bb 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-err.rs +++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-for-str-err.rs @@ -1,7 +1,7 @@ //@ run-fail //@ error-pattern: An error message for you //@ failure-status: 1 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() -> Result<(), &'static str> { Err("An error message for you") diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs deleted file mode 100644 index f0e111b578f..00000000000 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![feature(start)] - -#[start] -#[track_caller] //~ ERROR `#[start]` function is not allowed to be `#[track_caller]` -fn start(_argc: isize, _argv: *const *const u8) -> isize { - panic!("{}: oh no", std::panic::Location::caller()); -} diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr deleted file mode 100644 index 2738444f21f..00000000000 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-start.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: `#[start]` function is not allowed to be `#[track_caller]` - --> $DIR/error-with-start.rs:4:1 - | -LL | #[track_caller] - | ^^^^^^^^^^^^^^^ -LL | fn start(_argc: isize, _argv: *const *const u8) -> isize { - | -------------------------------------------------------- `#[start]` function is not allowed to be `#[track_caller]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr index 1047dbe1063..106268ac2c7 100644 --- a/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr +++ b/tests/ui/rfcs/rfc-2126-extern-absolute-paths/non-existent-1.stderr @@ -2,7 +2,9 @@ error[E0432]: unresolved import `xcrate` --> $DIR/non-existent-1.rs:3:5 | LL | use xcrate::S; - | ^^^^^^ use of undeclared crate or module `xcrate` + | ^^^^^^ use of unresolved module or unlinked crate `xcrate` + | + = help: you might be missing a crate named `xcrate` error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs index 3eae79faf42..c880ef0fe8a 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -6,6 +6,9 @@ fn foo() {} #[target_feature(enable = "avx")] +fn bar(arg: i32) {} + +#[target_feature(enable = "avx")] unsafe fn foo_unsafe() {} fn call(f: impl Fn()) { @@ -20,10 +23,15 @@ fn call_once(f: impl FnOnce()) { f() } +fn call_once_i32(f: impl FnOnce(i32)) { + f(0) +} + fn main() { call(foo); //~ ERROR expected a `Fn()` closure, found `#[target_features] fn() {foo}` call_mut(foo); //~ ERROR expected a `FnMut()` closure, found `#[target_features] fn() {foo}` call_once(foo); //~ ERROR expected a `FnOnce()` closure, found `#[target_features] fn() {foo}` + call_once_i32(bar); //~ ERROR expected a `FnOnce(i32)` closure, found `#[target_features] fn(i32) {bar}` call(foo_unsafe); //~^ ERROR expected a `Fn()` closure, found `unsafe fn() {foo_unsafe}` diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 2915b9ad1b3..efc061eca5f 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -1,5 +1,5 @@ error[E0277]: expected a `Fn()` closure, found `#[target_features] fn() {foo}` - --> $DIR/fn-traits.rs:24:10 + --> $DIR/fn-traits.rs:31:10 | LL | call(foo); | ---- ^^^ expected an `Fn()` closure, found `#[target_features] fn() {foo}` @@ -9,14 +9,15 @@ LL | call(foo); = help: the trait `Fn()` is not implemented for fn item `#[target_features] fn() {foo}` = note: wrap the `#[target_features] fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits + = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call` - --> $DIR/fn-traits.rs:11:17 + --> $DIR/fn-traits.rs:14:17 | LL | fn call(f: impl Fn()) { | ^^^^ required by this bound in `call` error[E0277]: expected a `FnMut()` closure, found `#[target_features] fn() {foo}` - --> $DIR/fn-traits.rs:25:14 + --> $DIR/fn-traits.rs:32:14 | LL | call_mut(foo); | -------- ^^^ expected an `FnMut()` closure, found `#[target_features] fn() {foo}` @@ -26,14 +27,15 @@ LL | call_mut(foo); = help: the trait `FnMut()` is not implemented for fn item `#[target_features] fn() {foo}` = note: wrap the `#[target_features] fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits + = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:15:25 + --> $DIR/fn-traits.rs:18:25 | LL | fn call_mut(mut f: impl FnMut()) { | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce()` closure, found `#[target_features] fn() {foo}` - --> $DIR/fn-traits.rs:26:15 + --> $DIR/fn-traits.rs:33:15 | LL | call_once(foo); | --------- ^^^ expected an `FnOnce()` closure, found `#[target_features] fn() {foo}` @@ -43,14 +45,32 @@ LL | call_once(foo); = help: the trait `FnOnce()` is not implemented for fn item `#[target_features] fn() {foo}` = note: wrap the `#[target_features] fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits + = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call_once` - --> $DIR/fn-traits.rs:19:22 + --> $DIR/fn-traits.rs:22:22 | LL | fn call_once(f: impl FnOnce()) { | ^^^^^^^^ required by this bound in `call_once` +error[E0277]: expected a `FnOnce(i32)` closure, found `#[target_features] fn(i32) {bar}` + --> $DIR/fn-traits.rs:34:19 + | +LL | call_once_i32(bar); + | ------------- ^^^ expected an `FnOnce(i32)` closure, found `#[target_features] fn(i32) {bar}` + | | + | required by a bound introduced by this call + | + = help: the trait `FnOnce(i32)` is not implemented for fn item `#[target_features] fn(i32) {bar}` + = note: `#[target_feature]` functions do not implement the `Fn` traits + = note: try casting the function to a `fn` pointer or wrapping it in a closure +note: required by a bound in `call_once_i32` + --> $DIR/fn-traits.rs:26:26 + | +LL | fn call_once_i32(f: impl FnOnce(i32)) { + | ^^^^^^^^^^^ required by this bound in `call_once_i32` + error[E0277]: expected a `Fn()` closure, found `unsafe fn() {foo_unsafe}` - --> $DIR/fn-traits.rs:28:10 + --> $DIR/fn-traits.rs:36:10 | LL | call(foo_unsafe); | ---- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` @@ -61,14 +81,15 @@ LL | call(foo_unsafe); = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits + = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call` - --> $DIR/fn-traits.rs:11:17 + --> $DIR/fn-traits.rs:14:17 | LL | fn call(f: impl Fn()) { | ^^^^ required by this bound in `call` error[E0277]: expected a `FnMut()` closure, found `unsafe fn() {foo_unsafe}` - --> $DIR/fn-traits.rs:30:14 + --> $DIR/fn-traits.rs:38:14 | LL | call_mut(foo_unsafe); | -------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` @@ -79,14 +100,15 @@ LL | call_mut(foo_unsafe); = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits + = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call_mut` - --> $DIR/fn-traits.rs:15:25 + --> $DIR/fn-traits.rs:18:25 | LL | fn call_mut(mut f: impl FnMut()) { | ^^^^^^^ required by this bound in `call_mut` error[E0277]: expected a `FnOnce()` closure, found `unsafe fn() {foo_unsafe}` - --> $DIR/fn-traits.rs:32:15 + --> $DIR/fn-traits.rs:40:15 | LL | call_once(foo_unsafe); | --------- ^^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }` @@ -97,12 +119,13 @@ LL | call_once(foo_unsafe); = note: unsafe function cannot be called generically without an unsafe block = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits + = note: try casting the function to a `fn` pointer or wrapping it in a closure note: required by a bound in `call_once` - --> $DIR/fn-traits.rs:19:22 + --> $DIR/fn-traits.rs:22:22 | LL | fn call_once(f: impl FnOnce()) { | ^^^^^^^^ required by this bound in `call_once` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs deleted file mode 100644 index 6aa8f6fd821..00000000000 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ only-x86_64 - -#![feature(start)] -#![feature(target_feature_11)] - -#[start] -#[target_feature(enable = "avx2")] -//~^ ERROR `#[start]` function is not allowed to have `#[target_feature]` -fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr deleted file mode 100644 index d0a67c4f6a8..00000000000 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/issue-108645-target-feature-on-start.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: `#[start]` function is not allowed to have `#[target_feature]` - --> $DIR/issue-108645-target-feature-on-start.rs:7:1 - | -LL | #[target_feature(enable = "avx2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | -LL | fn start(_argc: isize, _argv: *const *const u8) -> isize { 0 } - | -------------------------------------------------------- `#[start]` function is not allowed to have `#[target_feature]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr deleted file mode 100644 index f556ecf7f91..00000000000 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr +++ /dev/null @@ -1,1111 +0,0 @@ -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:31:9 - | -LL | if (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:31:9 - | -LL | if (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:34:11 - | -LL | if (((let 0 = 1))) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:34:11 - | -LL | if (((let 0 = 1))) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:37:9 - | -LL | if (let 0 = 1) && true {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:37:9 - | -LL | if (let 0 = 1) && true {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:40:17 - | -LL | if true && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:40:17 - | -LL | if true && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:43:9 - | -LL | if (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:43:9 - | -LL | if (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:43:24 - | -LL | if (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:43:24 - | -LL | if (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:47:35 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:47:35 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:47:48 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:47:35 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:47:61 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:47:35 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:56:12 - | -LL | while (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:56:12 - | -LL | while (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:59:14 - | -LL | while (((let 0 = 1))) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:59:14 - | -LL | while (((let 0 = 1))) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:62:12 - | -LL | while (let 0 = 1) && true {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:62:12 - | -LL | while (let 0 = 1) && true {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:65:20 - | -LL | while true && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:65:20 - | -LL | while true && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:12 - | -LL | while (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:12 - | -LL | while (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:27 - | -LL | while (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:27 - | -LL | while (let 0 = 1) && (let 0 = 1) {} - | ^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:72:38 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:72:38 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:72:51 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:72:38 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:72:64 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:72:38 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:9 - | -LL | if &let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:98:9 - | -LL | if !let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:100:9 - | -LL | if *let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:102:9 - | -LL | if -let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:110:9 - | -LL | if (let 0 = 0)? {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:113:16 - | -LL | if true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:113:13 - | -LL | if true || let 0 = 0 {} - | ^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:115:17 - | -LL | if (true || let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:117:25 - | -LL | if true && (true || let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:25 - | -LL | if true || (true && let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:123:12 - | -LL | if x = let 0 = 0 {} - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:126:15 - | -LL | if true..(let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:129:11 - | -LL | if ..(let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:131:9 - | -LL | if (let 0 = 0).. {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:135:8 - | -LL | if let Range { start: _, end: _ } = true..true && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:138:8 - | -LL | if let Range { start: _, end: _ } = true..true || false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:144:8 - | -LL | if let Range { start: F, end } = F..|| true {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:150:8 - | -LL | if let Range { start: true, end } = t..&&false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:154:19 - | -LL | if let true = let true = true {} - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:160:12 - | -LL | while &let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:163:12 - | -LL | while !let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:165:12 - | -LL | while *let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:12 - | -LL | while -let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:175:12 - | -LL | while (let 0 = 0)? {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:178:19 - | -LL | while true || let 0 = 0 {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:178:16 - | -LL | while true || let 0 = 0 {} - | ^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:180:20 - | -LL | while (true || let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:182:28 - | -LL | while true && (true || let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:184:28 - | -LL | while true || (true && let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:188:15 - | -LL | while x = let 0 = 0 {} - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:191:18 - | -LL | while true..(let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:194:14 - | -LL | while ..(let 0 = 0) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:196:12 - | -LL | while (let 0 = 0).. {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:200:11 - | -LL | while let Range { start: _, end: _ } = true..true && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:203:11 - | -LL | while let Range { start: _, end: _ } = true..true || false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:209:11 - | -LL | while let Range { start: F, end } = F..|| true {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:215:11 - | -LL | while let Range { start: true, end } = t..&&false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:219:22 - | -LL | while let true = let true = true {} - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:236:6 - | -LL | &let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:6 - | -LL | !let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:241:6 - | -LL | *let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:243:6 - | -LL | -let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:245:13 - | -LL | let _ = let _ = 3; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:253:6 - | -LL | (let 0 = 0)?; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:256:13 - | -LL | true || let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:258:14 - | -LL | (true || let 0 = 0); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:260:22 - | -LL | true && (true || let 0 = 0); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:264:9 - | -LL | x = let 0 = 0; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:267:12 - | -LL | true..(let 0 = 0); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:269:8 - | -LL | ..(let 0 = 0); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:271:6 - | -LL | (let 0 = 0)..; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:274:6 - | -LL | (let Range { start: _, end: _ } = true..true || false); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:278:6 - | -LL | (let true = let true = true); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:278:17 - | -LL | (let true = let true = true); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:284:25 - | -LL | let x = true && let y = 1; - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:290:19 - | -LL | [1, 2, 3][let _ = ()] - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:295:6 - | -LL | &let 0 = 0 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:306:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:311:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:316:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:327:9 - | -LL | true && let 1 = 1 - | ^^^^^^^^^^^^^^^^^ - | -help: enclose the `const` expression in braces - | -LL | { true && let 1 = 1 } - | + + - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:337:9 - | -LL | if (let Some(a) = opt && true) { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:337:9 - | -LL | if (let Some(a) = opt && true) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:341:9 - | -LL | if (let Some(a) = opt) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:341:9 - | -LL | if (let Some(a) = opt) && true { - | ^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:9 - | -LL | if (let Some(a) = opt) && (let Some(b) = a) { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:344:9 - | -LL | if (let Some(a) = opt) && (let Some(b) = a) { - | ^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:32 - | -LL | if (let Some(a) = opt) && (let Some(b) = a) { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:344:32 - | -LL | if (let Some(a) = opt) && (let Some(b) = a) { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:351:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:351:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:351:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:9 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:31 - | -LL | if (let Some(a) = opt && (let Some(b) = a)) && true { - | ^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:9 - | -LL | if (let Some(a) = opt && (true)) && true { - | ^^^^^^^^^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:9 - | -LL | if (let Some(a) = opt && (true)) && true { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:375:22 - | -LL | let x = (true && let y = 1); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:380:20 - | -LL | ([1, 2, 3][let _ = ()]) - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:87:16 - | -LL | use_expr!((let 0 = 1 && 0 == 0)); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:89:16 - | -LL | use_expr!((let 0 = 1)); - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:47:8 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:47:21 - | -LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:72:11 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:72:24 - | -LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:348:8 - | -LL | if let Some(a) = opt && (true && true) { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:363:28 - | -LL | if (true && (true)) && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:365:18 - | -LL | if (true) && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:367:16 - | -LL | if true && let Some(a) = opt { - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:371:8 - | -LL | if let true = (true && fun()) && (true) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information - = help: add `#![feature(let_chains)]` 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[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:126:8 - | -LL | if true..(let 0 = 0) {} - | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>` - | - = note: expected type `bool` - found struct `std::ops::Range<bool>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:135:12 - | -LL | if let Range { start: _, end: _ } = true..true && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:138:12 - | -LL | if let Range { start: _, end: _ } = true..true || false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:144:12 - | -LL | if let Range { start: F, end } = F..|| true {} - | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` - | | - | expected fn pointer, found `Range<_>` - | - = note: expected fn pointer `fn() -> bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:150:12 - | -LL | if let Range { start: true, end } = t..&&false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:106:20 - | -LL | if let 0 = 0? {} - | ^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:191:11 - | -LL | while true..(let 0 = 0) {} - | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range<bool>` - | - = note: expected type `bool` - found struct `std::ops::Range<bool>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:200:15 - | -LL | while let Range { start: _, end: _ } = true..true && false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:203:15 - | -LL | while let Range { start: _, end: _ } = true..true || false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:209:15 - | -LL | while let Range { start: F, end } = F..|| true {} - | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` - | | - | expected fn pointer, found `Range<_>` - | - = note: expected fn pointer `fn() -> bool` - found struct `std::ops::Range<_>` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:215:15 - | -LL | while let Range { start: true, end } = t..&&false {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:171:23 - | -LL | while let 0 = 0? {} - | ^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:274:10 - | -LL | (let Range { start: _, end: _ } = true..true || false); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` - | | - | expected `bool`, found `Range<_>` - | - = note: expected type `bool` - found struct `std::ops::Range<_>` - -error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:249:17 - | -LL | let 0 = 0?; - | ^^ the `?` operator cannot be applied to type `{integer}` - | - = help: the trait `Try` is not implemented for `{integer}` - -error: aborting due to 114 previous errors - -Some errors have detailed explanations: E0277, E0308, E0658. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rmeta/emit-artifact-notifications.polonius.stderr b/tests/ui/rmeta/emit-artifact-notifications.polonius.stderr deleted file mode 100644 index 255c7b370f9..00000000000 --- a/tests/ui/rmeta/emit-artifact-notifications.polonius.stderr +++ /dev/null @@ -1 +0,0 @@ -{"artifact":"$TEST_BUILD_DIR/rmeta/emit-artifact-notifications.polonius/libemit_artifact_notifications.rmeta","emit":"metadata"} diff --git a/tests/ui/runtime/atomic-print.rs b/tests/ui/runtime/atomic-print.rs index 73520589736..6b899d675a2 100644 --- a/tests/ui/runtime/atomic-print.rs +++ b/tests/ui/runtime/atomic-print.rs @@ -2,8 +2,8 @@ #![allow(unused_must_use)] #![allow(deprecated)] -//@ ignore-wasm32 no processes or threads -//@ ignore-sgx no processes +//@ needs-threads +//@ needs-subprocess use std::{env, fmt, process, sync, thread}; diff --git a/tests/ui/runtime/backtrace-debuginfo.rs b/tests/ui/runtime/backtrace-debuginfo.rs index da747ded44f..afc96d6bb5f 100644 --- a/tests/ui/runtime/backtrace-debuginfo.rs +++ b/tests/ui/runtime/backtrace-debuginfo.rs @@ -9,8 +9,7 @@ //@ compile-flags:-g -Copt-level=0 -Cllvm-args=-enable-tail-merge=0 //@ compile-flags:-Cforce-frame-pointers=yes //@ compile-flags:-Cstrip=none -//@ ignore-wasm32 spawning processes is not supported -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia Backtrace not symbolized, trace different line alignment // FIXME(#117097): backtrace (possibly unwinding mechanism) seems to be different on at least diff --git a/tests/ui/runtime/native-print-no-runtime.rs b/tests/ui/runtime/native-print-no-runtime.rs deleted file mode 100644 index f0ed7d97b2c..00000000000 --- a/tests/ui/runtime/native-print-no-runtime.rs +++ /dev/null @@ -1,9 +0,0 @@ -//@ run-pass - -#![feature(start)] - -#[start] -pub fn main(_: isize, _: *const *const u8) -> isize { - println!("hello"); - 0 -} diff --git a/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs index 229408fb724..f3f9ce0bd87 100644 --- a/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs +++ b/tests/ui/runtime/on-broken-pipe/auxiliary/assert-sigpipe-disposition.rs @@ -4,15 +4,16 @@ //@ compile-flags: -Cpanic=abort //@ no-prefer-dynamic so panic=abort works -#![feature(start, rustc_private)] +#![feature(rustc_private)] +#![no_main] extern crate libc; -// Use #[start] so we don't have a runtime that messes with SIGPIPE. -#[start] -fn start(argc: isize, argv: *const *const u8) -> isize { +// Use no_main so we don't have a runtime that messes with SIGPIPE. +#[no_mangle] +extern "C" fn main(argc: core::ffi::c_int, argv: *const *const u8) -> core::ffi::c_int { assert_eq!(argc, 2, "Must pass SIG_IGN or SIG_DFL as first arg"); - let arg1 = unsafe { std::ffi::CStr::from_ptr(*argv.offset(1) as *const libc::c_char) } + let arg1 = unsafe { core::ffi::CStr::from_ptr(*argv.offset(1) as *const libc::c_char) } .to_str() .unwrap(); @@ -23,8 +24,8 @@ fn start(argc: isize, argv: *const *const u8) -> isize { }; let actual = unsafe { - let mut actual: libc::sigaction = std::mem::zeroed(); - libc::sigaction(libc::SIGPIPE, std::ptr::null(), &mut actual); + let mut actual: libc::sigaction = core::mem::zeroed(); + libc::sigaction(libc::SIGPIPE, core::ptr::null(), &mut actual); #[cfg(not(target_os = "aix"))] { actual.sa_sigaction diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs index c5300635ad9..6be34afb560 100644 --- a/tests/ui/runtime/out-of-stack.rs +++ b/tests/ui/runtime/out-of-stack.rs @@ -3,8 +3,7 @@ #![allow(unused_must_use)] #![allow(unconditional_recursion)] //@ ignore-android: FIXME (#20004) -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590) //@ ignore-nto no stack overflow handler used (no alternate stack available) //@ ignore-ios stack overflow handlers aren't enabled diff --git a/tests/ui/runtime/rt-explody-panic-payloads.rs b/tests/ui/runtime/rt-explody-panic-payloads.rs index bd3624a8aee..c177fd260ed 100644 --- a/tests/ui/runtime/rt-explody-panic-payloads.rs +++ b/tests/ui/runtime/rt-explody-panic-payloads.rs @@ -1,7 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; use std::process::Command; diff --git a/tests/ui/runtime/running-with-no-runtime.rs b/tests/ui/runtime/running-with-no-runtime.rs index 695025b3859..7ac0dd912dc 100644 --- a/tests/ui/runtime/running-with-no-runtime.rs +++ b/tests/ui/runtime/running-with-no-runtime.rs @@ -1,16 +1,15 @@ //@ run-pass -//@ ignore-wasm32 spawning processes is not supported -//@ ignore-sgx no processes +//@ needs-subprocess -#![feature(start)] +#![no_main] use std::ffi::CStr; use std::process::{Command, Output}; use std::panic; use std::str; -#[start] -fn start(argc: isize, argv: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(argc: core::ffi::c_int, argv: *const *const u8) -> core::ffi::c_int { if argc > 1 { unsafe { match **argv.offset(1) as char { diff --git a/tests/ui/rust-2018/unresolved-asterisk-imports.stderr b/tests/ui/rust-2018/unresolved-asterisk-imports.stderr index b6bf109824f..049d52893d4 100644 --- a/tests/ui/rust-2018/unresolved-asterisk-imports.stderr +++ b/tests/ui/rust-2018/unresolved-asterisk-imports.stderr @@ -2,7 +2,9 @@ error[E0432]: unresolved import `not_existing_crate` --> $DIR/unresolved-asterisk-imports.rs:3:5 | LL | use not_existing_crate::*; - | ^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `not_existing_crate` + | ^^^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `not_existing_crate` + | + = help: you might be missing a crate named `not_existing_crate` error: aborting due to 1 previous error diff --git a/tests/ui/rust-2024/safe-outside-extern.gated.stderr b/tests/ui/rust-2024/safe-outside-extern.gated.stderr deleted file mode 100644 index e0b218281f3..00000000000 --- a/tests/ui/rust-2024/safe-outside-extern.gated.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:4:1 - | -LL | safe fn foo() {} - | ^^^^^^^^^^^^^^^^ - -error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:8:1 - | -LL | safe static FOO: i32 = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:13:5 - | -LL | safe fn foo(); - | ^^^^^^^^^^^^^^ - -error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:19:5 - | -LL | safe fn foo() {} - | ^^^^^^^^^^^^^^^^ - -error: function pointers cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:24:14 - | -LL | type FnPtr = safe fn(i32, i32) -> i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block - --> $DIR/safe-outside-extern.rs:28:1 - | -LL | unsafe static LOL: u8 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors - diff --git a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr b/tests/ui/rust-2024/safe-outside-extern.ungated.stderr deleted file mode 100644 index 98a4c0eab92..00000000000 --- a/tests/ui/rust-2024/safe-outside-extern.ungated.stderr +++ /dev/null @@ -1,89 +0,0 @@ -error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:4:1 - | -LL | safe fn foo() {} - | ^^^^^^^^^^^^^^^^ - -error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:8:1 - | -LL | safe static FOO: i32 = 1; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:13:5 - | -LL | safe fn foo(); - | ^^^^^^^^^^^^^^ - -error: items outside of `unsafe extern { }` cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:19:5 - | -LL | safe fn foo() {} - | ^^^^^^^^^^^^^^^^ - -error: function pointers cannot be declared with `safe` safety qualifier - --> $DIR/safe-outside-extern.rs:24:14 - | -LL | type FnPtr = safe fn(i32, i32) -> i32; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block - --> $DIR/safe-outside-extern.rs:28:1 - | -LL | unsafe static LOL: u8 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0658]: `unsafe extern {}` blocks and `safe` keyword are experimental - --> $DIR/safe-outside-extern.rs:4:1 - | -LL | safe fn foo() {} - | ^^^^ - | - = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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]: `unsafe extern {}` blocks and `safe` keyword are experimental - --> $DIR/safe-outside-extern.rs:8:1 - | -LL | safe static FOO: i32 = 1; - | ^^^^ - | - = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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]: `unsafe extern {}` blocks and `safe` keyword are experimental - --> $DIR/safe-outside-extern.rs:13:5 - | -LL | safe fn foo(); - | ^^^^ - | - = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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]: `unsafe extern {}` blocks and `safe` keyword are experimental - --> $DIR/safe-outside-extern.rs:19:5 - | -LL | safe fn foo() {} - | ^^^^ - | - = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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]: `unsafe extern {}` blocks and `safe` keyword are experimental - --> $DIR/safe-outside-extern.rs:24:14 - | -LL | type FnPtr = safe fn(i32, i32) -> i32; - | ^^^^ - | - = note: see issue #123743 <https://github.com/rust-lang/rust/issues/123743> for more information - = help: add `#![feature(unsafe_extern_blocks)]` 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 11 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed index 8b179f7ef93..cba3d7f1f9f 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed @@ -40,6 +40,15 @@ macro_rules! meta2 { } } +macro_rules! with_cfg_attr { + () => { + #[cfg_attr(all(), unsafe(link_section = ".custom_section"))] + //~^ ERROR: unsafe attribute used without unsafe + //~| WARN this is accepted in the current edition + pub extern "C" fn abc() {} + }; +} + tt!([unsafe(no_mangle)]); //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition @@ -52,6 +61,8 @@ meta2!(unsafe(export_name = "baw")); //~| WARN this is accepted in the current edition ident2!(export_name, "bars"); +with_cfg_attr!(); + #[unsafe(no_mangle)] //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs index 34e5a6b96e3..4bbf9b25de5 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs @@ -40,6 +40,15 @@ macro_rules! meta2 { } } +macro_rules! with_cfg_attr { + () => { + #[cfg_attr(all(), link_section = ".custom_section")] + //~^ ERROR: unsafe attribute used without unsafe + //~| WARN this is accepted in the current edition + pub extern "C" fn abc() {} + }; +} + tt!([no_mangle]); //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition @@ -52,6 +61,8 @@ meta2!(export_name = "baw"); //~| WARN this is accepted in the current edition ident2!(export_name, "bars"); +with_cfg_attr!(); + #[no_mangle] //~^ ERROR: unsafe attribute used without unsafe //~| WARN this is accepted in the current edition diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr index 87330d2693d..15a48fb7159 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr @@ -1,5 +1,5 @@ error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:43:6 + --> $DIR/unsafe-attributes-fix.rs:52:6 | LL | tt!([no_mangle]); | ^^^^^^^^^ usage of unsafe attribute @@ -34,7 +34,7 @@ LL | #[unsafe($e)] | +++++++ + error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:47:7 + --> $DIR/unsafe-attributes-fix.rs:56:7 | LL | meta!(no_mangle); | ^^^^^^^^^ usage of unsafe attribute @@ -47,7 +47,7 @@ LL | meta!(unsafe(no_mangle)); | +++++++ + error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:50:8 + --> $DIR/unsafe-attributes-fix.rs:59:8 | LL | meta2!(export_name = "baw"); | ^^^^^^^^^^^ usage of unsafe attribute @@ -77,7 +77,24 @@ LL | #[unsafe($e = $l)] | +++++++ + error: unsafe attribute used without unsafe - --> $DIR/unsafe-attributes-fix.rs:55:3 + --> $DIR/unsafe-attributes-fix.rs:45:27 + | +LL | #[cfg_attr(all(), link_section = ".custom_section")] + | ^^^^^^^^^^^^ usage of unsafe attribute +... +LL | with_cfg_attr!(); + | ---------------- in this macro invocation + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/unsafe-attributes.html> + = note: this error originates in the macro `with_cfg_attr` (in Nightly builds, run with -Z macro-backtrace for more info) +help: wrap the attribute in `unsafe(...)` + | +LL | #[cfg_attr(all(), unsafe(link_section = ".custom_section"))] + | +++++++ + + +error: unsafe attribute used without unsafe + --> $DIR/unsafe-attributes-fix.rs:66:3 | LL | #[no_mangle] | ^^^^^^^^^ usage of unsafe attribute @@ -89,5 +106,5 @@ help: wrap the attribute in `unsafe(...)` LL | #[unsafe(no_mangle)] | +++++++ + -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.ungated.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.ungated.stderr deleted file mode 100644 index 80e7a45f57e..00000000000 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-impl-trait.ungated.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected one of `!` or `::`, found keyword `impl` - --> $DIR/safe-impl-trait.rs:5:6 - | -LL | safe impl Bar for () { } - | ^^^^ expected one of `!` or `::` - -error: aborting due to 1 previous error - diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.gated.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.gated.stderr deleted file mode 100644 index de84037f28c..00000000000 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.gated.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected one of `!` or `::`, found keyword `trait` - --> $DIR/safe-trait.rs:4:6 - | -LL | safe trait Foo {} - | ^^^^^ expected one of `!` or `::` - -error: aborting due to 1 previous error - diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.ungated.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.ungated.stderr deleted file mode 100644 index de84037f28c..00000000000 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-trait.ungated.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: expected one of `!` or `::`, found keyword `trait` - --> $DIR/safe-trait.rs:4:6 - | -LL | safe trait Foo {} - | ^^^^^ expected one of `!` or `::` - -error: aborting due to 1 previous error - diff --git a/tests/ui/sanitizer/memory-eager.rs b/tests/ui/sanitizer/memory-eager.rs index 9e7889fa1bc..532d7b308f6 100644 --- a/tests/ui/sanitizer/memory-eager.rs +++ b/tests/ui/sanitizer/memory-eager.rs @@ -15,7 +15,7 @@ // since it will be linked with an uninstrumented version of it. #![feature(core_intrinsics)] -#![feature(start)] +#![no_main] use std::hint::black_box; use std::mem::MaybeUninit; @@ -29,8 +29,8 @@ fn random() -> char { black_box(r) } -#[start] -fn main(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: std::ffi::c_int, _argv: *const *const u8) -> std::ffi::c_int { random(); 0 } diff --git a/tests/ui/sanitizer/memory-passing.rs b/tests/ui/sanitizer/memory-passing.rs index c8ab64bfaf8..96a4cd909c7 100644 --- a/tests/ui/sanitizer/memory-passing.rs +++ b/tests/ui/sanitizer/memory-passing.rs @@ -12,8 +12,8 @@ // since it will be linked with an uninstrumented version of it. #![feature(core_intrinsics)] -#![feature(start)] #![allow(invalid_value)] +#![no_main] use std::hint::black_box; @@ -25,8 +25,8 @@ fn calling_black_box_on_zst_ok() { black_box(zst); } -#[start] -fn main(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: std::ffi::c_int, _argv: *const *const u8) -> std::ffi::c_int { calling_black_box_on_zst_ok(); 0 } diff --git a/tests/ui/sanitizer/memory.rs b/tests/ui/sanitizer/memory.rs index bd2d6771749..a91fefe4d16 100644 --- a/tests/ui/sanitizer/memory.rs +++ b/tests/ui/sanitizer/memory.rs @@ -15,8 +15,8 @@ // since it will be linked with an uninstrumented version of it. #![feature(core_intrinsics)] -#![feature(start)] #![allow(invalid_value)] +#![no_main] use std::hint::black_box; use std::mem::MaybeUninit; @@ -39,8 +39,8 @@ fn xor(a: &[isize]) -> isize { s } -#[start] -fn main(_: isize, _: *const *const u8) -> isize { +#[no_mangle] +extern "C" fn main(_argc: std::ffi::c_int, _argv: *const *const u8) -> std::ffi::c_int { let r = black_box(random as fn() -> [isize; 32])(); - xor(&r) + xor(&r) as std::ffi::c_int } diff --git a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr index 9af2a08f371..bafa290a3cf 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr @@ -53,7 +53,7 @@ LL | assert_eq!(smart_ptr.a::<&Foo>(), 2); | ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>` | = note: expected reference `&Foo` - found struct `SmartPtr<'_, Foo, >` + found struct `SmartPtr<'_, Foo>` error[E0308]: mismatched types --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:62:16 @@ -62,7 +62,7 @@ LL | assert_eq!(smart_ptr.b::<&Foo>(), 1); | ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>` | = note: expected reference `&Foo` - found struct `SmartPtr<'_, Foo, >` + found struct `SmartPtr<'_, Foo>` error: aborting due to 8 previous errors diff --git a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr index 6e864f44aa3..f67918a2577 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr @@ -83,7 +83,7 @@ LL | smart_ptr.get::<&Foo>(); | ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>` | = note: expected reference `&Foo` - found struct `SmartPtr<'_, Foo, >` + found struct `SmartPtr<'_, Foo>` error[E0271]: type mismatch resolving `<Silly as FindReceiver>::Receiver == Foo` --> $DIR/arbitrary-self-from-method-substs.rs:92:9 diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr index 2eb7597d5c1..3e018995ba5 100644 --- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.curr.stderr @@ -1,38 +1,40 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:32 | LL | fn foo(self: &Rc<Self>) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc<dyn Foo>; - | ^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn foo(self: &Rc<Self>) -> usize; | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on - = help: only type `usize` implements the trait, consider using it directly instead + = help: only type `usize` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:13 | LL | fn foo(self: &Rc<Self>) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc<dyn Foo>; - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn foo(self: &Rc<Self>) -> usize; | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on - = help: only type `usize` implements the trait, consider using it directly instead + = help: only type `usize` implements `Foo`; consider using it directly instead. = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>` error: aborting due to 2 previous errors diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr index 02af692c4a3..12c93d58537 100644 --- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.dyn_compatible_for_dispatch.stderr @@ -1,20 +1,21 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/arbitrary-self-types-dyn-incompatible.rs:33:13 | LL | fn foo(self: &Rc<Self>) -> usize; | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` ... LL | let x = Rc::new(5usize) as Rc<dyn Foo>; - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/arbitrary-self-types-dyn-incompatible.rs:8:18 | LL | trait Foo { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn foo(self: &Rc<Self>) -> usize; | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on - = help: only type `usize` implements the trait, consider using it directly instead + = help: only type `usize` implements `Foo`; consider using it directly instead. = note: required for the cast from `Rc<usize>` to `Rc<dyn Foo>` error: aborting due to 1 previous error diff --git a/tests/ui/sepcomp/sepcomp-unwind.rs b/tests/ui/sepcomp/sepcomp-unwind.rs index 6a40b5ccc12..8c25278bb7e 100644 --- a/tests/ui/sepcomp/sepcomp-unwind.rs +++ b/tests/ui/sepcomp/sepcomp-unwind.rs @@ -2,7 +2,7 @@ //@ needs-unwind #![allow(dead_code)] //@ compile-flags: -C codegen-units=3 -//@ ignore-emscripten no threads support +//@ needs-threads // Test unwinding through multiple compilation units. diff --git a/tests/ui/simd/target-feature-mixup.rs b/tests/ui/simd/target-feature-mixup.rs index 62d87c3a6dc..2786251c795 100644 --- a/tests/ui/simd/target-feature-mixup.rs +++ b/tests/ui/simd/target-feature-mixup.rs @@ -3,8 +3,7 @@ #![allow(stable_features)] #![allow(overflowing_literals)] -//@ ignore-wasm32 no subprocess support -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-fuchsia must translate zircon signal to SIGILL, FIXME (#58590) #![feature(repr_simd, target_feature, cfg_target_feature)] diff --git a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr index a4b65256574..6559845c23e 100644 --- a/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr +++ b/tests/ui/span/issue-42234-unknown-receiver-type.generic_arg.stderr @@ -17,10 +17,6 @@ error[E0282]: type annotations needed LL | .sum::<_>() | ^^^ cannot infer type of the type parameter `S` declared on the method `sum` | -help: consider specifying the generic argument - | -LL | .sum::<S>() - | ~~~~~ error: aborting due to 2 previous errors diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.coherence.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.coherence.stderr deleted file mode 100644 index e9498a00317..00000000000 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.coherence.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0119]: conflicting implementations of trait `Overlap` for type `u32` - --> $DIR/specialization-default-items-drop-coherence.rs:29:1 - | -LL | impl Overlap for u32 { - | -------------------- first implementation here -... -LL | impl Overlap for <u32 as Default>::Id { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-overlap-projection.current.stderr b/tests/ui/specialization/specialization-overlap-projection.current.stderr deleted file mode 100644 index 4e77cb17fbb..00000000000 --- a/tests/ui/specialization/specialization-overlap-projection.current.stderr +++ /dev/null @@ -1,30 +0,0 @@ -warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:4:12 - | -LL | #![feature(specialization)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information - = help: consider using `min_specialization` instead, which is more stable and complete - = note: `#[warn(incomplete_features)]` on by default - -error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:19:1 - | -LL | impl Foo for u32 {} - | ---------------- first implementation here -LL | impl Foo for <u8 as Assoc>::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:21:1 - | -LL | impl Foo for u32 {} - | ---------------- first implementation here -... -LL | impl Foo for <u16 as Assoc>::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error: aborting due to 2 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/specialization/specialization-overlap-projection.next.stderr b/tests/ui/specialization/specialization-overlap-projection.next.stderr deleted file mode 100644 index 4e77cb17fbb..00000000000 --- a/tests/ui/specialization/specialization-overlap-projection.next.stderr +++ /dev/null @@ -1,30 +0,0 @@ -warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/specialization-overlap-projection.rs:4:12 - | -LL | #![feature(specialization)] - | ^^^^^^^^^^^^^^ - | - = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information - = help: consider using `min_specialization` instead, which is more stable and complete - = note: `#[warn(incomplete_features)]` on by default - -error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:19:1 - | -LL | impl Foo for u32 {} - | ---------------- first implementation here -LL | impl Foo for <u8 as Assoc>::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error[E0119]: conflicting implementations of trait `Foo` for type `u32` - --> $DIR/specialization-overlap-projection.rs:21:1 - | -LL | impl Foo for u32 {} - | ---------------- first implementation here -... -LL | impl Foo for <u16 as Assoc>::Output {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `u32` - -error: aborting due to 2 previous errors; 1 warning emitted - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.rs b/tests/ui/statics/unsizing-wfcheck-issue-127299.rs index cd15be54ec7..fd07937d90f 100644 --- a/tests/ui/statics/unsizing-wfcheck-issue-127299.rs +++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.rs @@ -6,12 +6,12 @@ trait Qux { pub struct Lint { pub desc: &'static dyn Qux, - //~^ ERROR cannot be made into an object + //~^ ERROR is not dyn compatible } static FOO: &Lint = &Lint { desc: "desc" }; //~^ ERROR cannot be shared between threads safely -//~| ERROR cannot be made into an object -//~| ERROR cannot be made into an object +//~| ERROR is not dyn compatible +//~| ERROR is not dyn compatible fn main() {} diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr index 35dd570e91f..08c744979f5 100644 --- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr +++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Qux` cannot be made into an object +error[E0038]: the trait `Qux` is not dyn compatible --> $DIR/unsizing-wfcheck-issue-127299.rs:8:24 | LL | pub desc: &'static dyn Qux, - | ^^^^^^^ `Qux` cannot be made into an object + | ^^^^^^^ `Qux` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8 | LL | trait Qux { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar() -> i32; | ^^^ ...because associated function `bar` has no `self` parameter help: consider turning `bar` into a method by giving it a `&self` argument @@ -36,17 +37,18 @@ LL | pub struct Lint { = note: required because it appears within the type `&'static Lint` = note: shared static variables must have a type that implements `Sync` -error[E0038]: the trait `Qux` cannot be made into an object +error[E0038]: the trait `Qux` is not dyn compatible --> $DIR/unsizing-wfcheck-issue-127299.rs:12:35 | LL | static FOO: &Lint = &Lint { desc: "desc" }; - | ^^^^^^ `Qux` cannot be made into an object + | ^^^^^^ `Qux` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8 | LL | trait Qux { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar() -> i32; | ^^^ ...because associated function `bar` has no `self` parameter = note: required for the cast from `&'static str` to `&'static (dyn Qux + 'static)` @@ -59,17 +61,18 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o LL | fn bar() -> i32 where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Qux` cannot be made into an object +error[E0038]: the trait `Qux` is not dyn compatible --> $DIR/unsizing-wfcheck-issue-127299.rs:12:35 | LL | static FOO: &Lint = &Lint { desc: "desc" }; - | ^^^^^^ `Qux` cannot be made into an object + | ^^^^^^ `Qux` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/unsizing-wfcheck-issue-127299.rs:4:8 | LL | trait Qux { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn bar() -> i32; | ^^^ ...because associated function `bar` has no `self` parameter help: consider turning `bar` into a method by giving it a `&self` argument diff --git a/tests/ui/std/thread-sleep-ms.rs b/tests/ui/std/thread-sleep-ms.rs index 0a3d0253a20..2d668b8265c 100644 --- a/tests/ui/std/thread-sleep-ms.rs +++ b/tests/ui/std/thread-sleep-ms.rs @@ -1,12 +1,9 @@ //@ run-pass -//@ ignore-sgx not supported -//@ ignore-emscripten -// FIXME: test hangs on emscripten -#![allow(deprecated)] -#![allow(unused_imports)] +//@ needs-threads +//@ ignore-emscripten (FIXME: test hangs on emscripten) -use std::thread; +#![allow(deprecated)] fn main() { - thread::sleep_ms(250); + std::thread::sleep_ms(250); } diff --git a/tests/ui/stdio-is-blocking.rs b/tests/ui/stdio-is-blocking.rs index dda100951dd..615530dcd47 100644 --- a/tests/ui/stdio-is-blocking.rs +++ b/tests/ui/stdio-is-blocking.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess use std::env; use std::io::prelude::*; diff --git a/tests/ui/str/str-overrun.rs b/tests/ui/str/str-overrun.rs index b8e245475da..6d62b837694 100644 --- a/tests/ui/str/str-overrun.rs +++ b/tests/ui/str/str-overrun.rs @@ -1,6 +1,6 @@ //@ run-fail //@ error-pattern:index out of bounds: the len is 5 but the index is 5 -//@ ignore-emscripten no processes +//@ needs-subprocess fn main() { let s: String = "hello".to_string(); diff --git a/tests/ui/structs-enums/unit-like-struct-drop-run.rs b/tests/ui/structs-enums/unit-like-struct-drop-run.rs index 02d14265f3e..3d00871837c 100644 --- a/tests/ui/structs-enums/unit-like-struct-drop-run.rs +++ b/tests/ui/structs-enums/unit-like-struct-drop-run.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-unwind -//@ ignore-emscripten no threads support +//@ needs-threads // Make sure the destructor is run for unit-like structs. diff --git a/tests/ui/structs/default-field-values/non-exhaustive-ctor.disabled.stderr b/tests/ui/structs/default-field-values/non-exhaustive-ctor.disabled.stderr new file mode 100644 index 00000000000..63793425657 --- /dev/null +++ b/tests/ui/structs/default-field-values/non-exhaustive-ctor.disabled.stderr @@ -0,0 +1,86 @@ +error[E0658]: default values on fields are experimental + --> $DIR/non-exhaustive-ctor.rs:9:22 + | +LL | pub field: () = (), + | ^^^^^ + | + = note: see issue #132162 <https://github.com/rust-lang/rust/issues/132162> for more information + = help: add `#![feature(default_field_values)]` 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]: default values on fields are experimental + --> $DIR/non-exhaustive-ctor.rs:11:25 + | +LL | pub field1: Priv = Priv, + | ^^^^^^^ + | + = note: see issue #132162 <https://github.com/rust-lang/rust/issues/132162> for more information + = help: add `#![feature(default_field_values)]` 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]: default values on fields are experimental + --> $DIR/non-exhaustive-ctor.rs:13:25 + | +LL | pub field2: Priv = Priv, + | ^^^^^^^ + | + = note: see issue #132162 <https://github.com/rust-lang/rust/issues/132162> for more information + = help: add `#![feature(default_field_values)]` 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[E0797]: base expression required after `..` + --> $DIR/non-exhaustive-ctor.rs:20:19 + | +LL | let _ = S { .. }; // ok + | ^ + | +help: add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields + | +LL + #![feature(default_field_values)] + | +help: add a base expression here + | +LL | let _ = S { ../* expr */ }; // ok + | ++++++++++ + +error[E0797]: base expression required after `..` + --> $DIR/non-exhaustive-ctor.rs:22:30 + | +LL | let _ = S { field: (), .. }; // ok + | ^ + | +help: add `#![feature(default_field_values)]` to the crate attributes to enable default values on `struct` fields + | +LL + #![feature(default_field_values)] + | +help: add a base expression here + | +LL | let _ = S { field: (), ../* expr */ }; // ok + | ++++++++++ + +error[E0063]: missing fields `field`, `field1` and `field2` in initializer of `S` + --> $DIR/non-exhaustive-ctor.rs:24:13 + | +LL | let _ = S { }; + | ^ missing `field`, `field1` and `field2` + | +help: all remaining fields have default values, if you added `#![feature(default_field_values)]` to your crate you could use those values with `..` + | +LL | let _ = S { .. }; + | ~~~~~~ + +error[E0063]: missing fields `field1` and `field2` in initializer of `S` + --> $DIR/non-exhaustive-ctor.rs:26:13 + | +LL | let _ = S { field: () }; + | ^ missing `field1` and `field2` + | +help: all remaining fields have default values, if you added `#![feature(default_field_values)]` to your crate you could use those values with `..` + | +LL | let _ = S { field: (), .. }; + | ++++ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0063, E0658, E0797. +For more information about an error, try `rustc --explain E0063`. diff --git a/tests/ui/structs/default-field-values/non-exhaustive-ctor.enabled.fixed b/tests/ui/structs/default-field-values/non-exhaustive-ctor.enabled.fixed new file mode 100644 index 00000000000..7a371f993e8 --- /dev/null +++ b/tests/ui/structs/default-field-values/non-exhaustive-ctor.enabled.fixed @@ -0,0 +1,28 @@ +//@ revisions: enabled disabled +//@[enabled] run-rustfix +#![allow(private_interfaces, dead_code)] +#![cfg_attr(enabled, feature(default_field_values))] +use m::S; + +mod m { + pub struct S { + pub field: () = (), + //[disabled]~^ ERROR default values on fields are experimental + pub field1: Priv = Priv, + //[disabled]~^ ERROR default values on fields are experimental + pub field2: Priv = Priv, + //[disabled]~^ ERROR default values on fields are experimental + } + struct Priv; +} + +fn main() { + let _ = S { .. }; // ok + //[disabled]~^ ERROR base expression required after `..` + let _ = S { field: (), .. }; // ok + //[disabled]~^ ERROR base expression required after `..` + let _ = S { .. }; + //~^ ERROR missing fields `field`, `field1` and `field2` + let _ = S { field: (), .. }; + //~^ ERROR missing fields `field1` and `field2` +} diff --git a/tests/ui/structs/default-field-values/non-exhaustive-ctor.enabled.stderr b/tests/ui/structs/default-field-values/non-exhaustive-ctor.enabled.stderr new file mode 100644 index 00000000000..6d035ebdc47 --- /dev/null +++ b/tests/ui/structs/default-field-values/non-exhaustive-ctor.enabled.stderr @@ -0,0 +1,25 @@ +error[E0063]: missing fields `field`, `field1` and `field2` in initializer of `S` + --> $DIR/non-exhaustive-ctor.rs:24:13 + | +LL | let _ = S { }; + | ^ missing `field`, `field1` and `field2` + | +help: all remaining fields have default values, you can use those values with `..` + | +LL | let _ = S { .. }; + | ~~~~~~ + +error[E0063]: missing fields `field1` and `field2` in initializer of `S` + --> $DIR/non-exhaustive-ctor.rs:26:13 + | +LL | let _ = S { field: () }; + | ^ missing `field1` and `field2` + | +help: all remaining fields have default values, you can use those values with `..` + | +LL | let _ = S { field: (), .. }; + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0063`. diff --git a/tests/ui/structs/default-field-values/non-exhaustive-ctor.rs b/tests/ui/structs/default-field-values/non-exhaustive-ctor.rs new file mode 100644 index 00000000000..b60b219f8bc --- /dev/null +++ b/tests/ui/structs/default-field-values/non-exhaustive-ctor.rs @@ -0,0 +1,28 @@ +//@ revisions: enabled disabled +//@[enabled] run-rustfix +#![allow(private_interfaces, dead_code)] +#![cfg_attr(enabled, feature(default_field_values))] +use m::S; + +mod m { + pub struct S { + pub field: () = (), + //[disabled]~^ ERROR default values on fields are experimental + pub field1: Priv = Priv, + //[disabled]~^ ERROR default values on fields are experimental + pub field2: Priv = Priv, + //[disabled]~^ ERROR default values on fields are experimental + } + struct Priv; +} + +fn main() { + let _ = S { .. }; // ok + //[disabled]~^ ERROR base expression required after `..` + let _ = S { field: (), .. }; // ok + //[disabled]~^ ERROR base expression required after `..` + let _ = S { }; + //~^ ERROR missing fields `field`, `field1` and `field2` + let _ = S { field: () }; + //~^ ERROR missing fields `field1` and `field2` +} diff --git a/tests/ui/structs/default-field-values/visibility.rs b/tests/ui/structs/default-field-values/visibility.rs new file mode 100644 index 00000000000..ff1245551b0 --- /dev/null +++ b/tests/ui/structs/default-field-values/visibility.rs @@ -0,0 +1,42 @@ +#![feature(default_field_values)] +pub mod foo { + #[derive(Default)] + pub struct Alpha { + beta: u8 = 42, + gamma: bool = true, + } +} + +mod bar { + use crate::foo::Alpha; + fn baz() { + let _x = Alpha { .. }; + //~^ ERROR fields `beta` and `gamma` of struct `Alpha` are private + let _x = Alpha { + beta: 0, //~ ERROR fields `beta` and `gamma` of struct `Alpha` are private + gamma: false, + }; + let _x = Alpha { + beta: 0, //~ ERROR fields `beta` and `gamma` of struct `Alpha` are private + .. + }; + let _x = Alpha { beta: 0, .. }; + //~^ ERROR fields `beta` and `gamma` of struct `Alpha` are private + let _x = Alpha { beta: 0, ..Default::default() }; + //~^ ERROR fields `beta` and `gamma` of struct `Alpha` are private + } +} + +pub mod baz { + pub struct S { + x: i32 = 1, + } +} +fn main() { + let _a = baz::S { + .. //~ ERROR field `x` of struct `S` is private + }; + let _b = baz::S { + x: 0, //~ ERROR field `x` of struct `S` is private + }; +} diff --git a/tests/ui/structs/default-field-values/visibility.stderr b/tests/ui/structs/default-field-values/visibility.stderr new file mode 100644 index 00000000000..38b96033252 --- /dev/null +++ b/tests/ui/structs/default-field-values/visibility.stderr @@ -0,0 +1,61 @@ +error[E0451]: field `x` of struct `S` is private + --> $DIR/visibility.rs:37:9 + | +LL | let _a = baz::S { + | ------ in this type +LL | .. + | ^^ field `x` is private + +error[E0451]: field `x` of struct `S` is private + --> $DIR/visibility.rs:40:9 + | +LL | let _b = baz::S { + | ------ in this type +LL | x: 0, + | ^ private field + +error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private + --> $DIR/visibility.rs:13:26 + | +LL | let _x = Alpha { .. }; + | ^^ fields `beta` and `gamma` are private + +error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private + --> $DIR/visibility.rs:16:13 + | +LL | let _x = Alpha { + | ----- in this type +LL | beta: 0, + | ^^^^ private field +LL | gamma: false, + | ^^^^^ private field + +error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private + --> $DIR/visibility.rs:20:13 + | +LL | let _x = Alpha { + | ----- in this type +LL | beta: 0, + | ^^^^^^^ private field +LL | .. + | ^^ field `gamma` is private + +error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private + --> $DIR/visibility.rs:23:26 + | +LL | let _x = Alpha { beta: 0, .. }; + | ^^^^^^^ ^^ field `gamma` is private + | | + | private field + +error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private + --> $DIR/visibility.rs:25:26 + | +LL | let _x = Alpha { beta: 0, ..Default::default() }; + | ^^^^^^^ ^^^^^^^^^^^^^^^^^^ field `gamma` is private + | | + | private field + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0451`. diff --git a/tests/ui/structs/ice-struct-tail-normalization-113272.rs b/tests/ui/structs/ice-struct-tail-normalization-113272.rs index 0ae24a7b71b..ce2871fabb8 100644 --- a/tests/ui/structs/ice-struct-tail-normalization-113272.rs +++ b/tests/ui/structs/ice-struct-tail-normalization-113272.rs @@ -13,6 +13,6 @@ struct Other { fn main() { unsafe { std::mem::transmute::<Option<()>, Option<&Other>>(None); - //~^ ERROR cannot transmute + //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types } } diff --git a/tests/ui/structs/rhs-type.rs b/tests/ui/structs/rhs-type.rs index fde5c16a068..8ce924672cf 100644 --- a/tests/ui/structs/rhs-type.rs +++ b/tests/ui/structs/rhs-type.rs @@ -3,7 +3,7 @@ //@ run-fail //@ error-pattern:bye -//@ ignore-emscripten no processes +//@ needs-subprocess #![allow(unreachable_code)] #![allow(unused_variables)] diff --git a/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.rs b/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.rs new file mode 100644 index 00000000000..a9c2c20ef37 --- /dev/null +++ b/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.rs @@ -0,0 +1,51 @@ +// https://github.com/rust-lang/rust/issues/109195 +struct Foo; + +impl Foo { + fn bar_baz() {} +} + +impl Foo { + fn bar_quux() {} +} + +fn main() { + String::from::utf8; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf8` + String::from::utf8(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf8` + String::from::utf16(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `from_utf16` + String::from::method_that_doesnt_exist(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `from` + str::into::string(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `into_string` + str::char::indices(); + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `char_indices` + Foo::bar::baz; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `bar_baz` + Foo::bar::quux; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `bar_quux` + Foo::bar::fizz; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `bar` + i32::wrapping::add; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP there is an associated function with a similar name: `wrapping_add` + i32::wrapping::method_that_doesnt_exist; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `wrapping` + + // this one ideally should suggest `downcast_mut_unchecked` + <dyn std::any::Any>::downcast::mut_unchecked; + //~^ ERROR ambiguous associated type [E0223] + //~| HELP if there were a trait named `Example` with associated type `downcast` +} diff --git a/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.stderr b/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.stderr new file mode 100644 index 00000000000..5863aa28f41 --- /dev/null +++ b/tests/ui/suggestions/ambiguous-assoc-type-path-suggest-similar-item.stderr @@ -0,0 +1,135 @@ +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:13:5 + | +LL | String::from::utf8; + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf8` + | +LL | String::from_utf8; + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:16:5 + | +LL | String::from::utf8(); + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf8` + | +LL | String::from_utf8(); + | ~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:19:5 + | +LL | String::from::utf16(); + | ^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `from_utf16` + | +LL | String::from_utf16(); + | ~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:22:5 + | +LL | String::from::method_that_doesnt_exist(); + | ^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path + | +LL | <String as Example>::from::method_that_doesnt_exist(); + | ~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:25:5 + | +LL | str::into::string(); + | ^^^^^^^^^ + | +help: there is an associated function with a similar name: `into_string` + | +LL | str::into_string(); + | ~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:28:5 + | +LL | str::char::indices(); + | ^^^^^^^^^ + | +help: there is an associated function with a similar name: `char_indices` + | +LL | str::char_indices(); + | ~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:31:5 + | +LL | Foo::bar::baz; + | ^^^^^^^^ + | +help: there is an associated function with a similar name: `bar_baz` + | +LL | Foo::bar_baz; + | ~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:34:5 + | +LL | Foo::bar::quux; + | ^^^^^^^^ + | +help: there is an associated function with a similar name: `bar_quux` + | +LL | Foo::bar_quux; + | ~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:37:5 + | +LL | Foo::bar::fizz; + | ^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `bar` implemented for `Foo`, you could use the fully-qualified path + | +LL | <Foo as Example>::bar::fizz; + | ~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:40:5 + | +LL | i32::wrapping::add; + | ^^^^^^^^^^^^^ + | +help: there is an associated function with a similar name: `wrapping_add` + | +LL | i32::wrapping_add; + | ~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:43:5 + | +LL | i32::wrapping::method_that_doesnt_exist; + | ^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `wrapping` implemented for `i32`, you could use the fully-qualified path + | +LL | <i32 as Example>::wrapping::method_that_doesnt_exist; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error[E0223]: ambiguous associated type + --> $DIR/ambiguous-assoc-type-path-suggest-similar-item.rs:48:5 + | +LL | <dyn std::any::Any>::downcast::mut_unchecked; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `downcast` implemented for `(dyn Any + 'static)`, you could use the fully-qualified path + | +LL | <(dyn Any + 'static) as Example>::downcast::mut_unchecked; + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/suggestions/crate-or-module-typo.rs b/tests/ui/suggestions/crate-or-module-typo.rs index dbc0605c76b..393fc7a1f72 100644 --- a/tests/ui/suggestions/crate-or-module-typo.rs +++ b/tests/ui/suggestions/crate-or-module-typo.rs @@ -1,6 +1,6 @@ //@ edition:2018 -use st::cell::Cell; //~ ERROR failed to resolve: use of undeclared crate or module `st` +use st::cell::Cell; //~ ERROR failed to resolve: use of unresolved module or unlinked crate `st` mod bar { pub fn bar() { bar::baz(); } //~ ERROR failed to resolve: function `bar` is not a crate or module @@ -11,7 +11,7 @@ mod bar { use bas::bar; //~ ERROR unresolved import `bas` struct Foo { - bar: st::cell::Cell<bool> //~ ERROR failed to resolve: use of undeclared crate or module `st` + bar: st::cell::Cell<bool> //~ ERROR failed to resolve: use of unresolved module or unlinked crate `st` } fn main() {} diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr index 084d0408a8e..75aa6e614b6 100644 --- a/tests/ui/suggestions/crate-or-module-typo.stderr +++ b/tests/ui/suggestions/crate-or-module-typo.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `st` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `st` --> $DIR/crate-or-module-typo.rs:3:5 | LL | use st::cell::Cell; - | ^^ use of undeclared crate or module `st` + | ^^ use of unresolved module or unlinked crate `st` | help: there is a crate or module with a similar name | @@ -13,18 +13,18 @@ error[E0432]: unresolved import `bas` --> $DIR/crate-or-module-typo.rs:11:5 | LL | use bas::bar; - | ^^^ use of undeclared crate or module `bas` + | ^^^ use of unresolved module or unlinked crate `bas` | help: there is a crate or module with a similar name | LL | use bar::bar; | ~~~ -error[E0433]: failed to resolve: use of undeclared crate or module `st` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `st` --> $DIR/crate-or-module-typo.rs:14:10 | LL | bar: st::cell::Cell<bool> - | ^^ use of undeclared crate or module `st` + | ^^ use of unresolved module or unlinked crate `st` | help: there is a crate or module with a similar name | diff --git a/tests/ui/issues/auxiliary/issue-111011.rs b/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.rs index 0c1a8ce1cf6..47a590668dd 100644 --- a/tests/ui/issues/auxiliary/issue-111011.rs +++ b/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.rs @@ -1,10 +1,12 @@ //@ edition:2021 +// issue: https://github.com/rust-lang/rust/issues/111011 fn foo<X>(x: impl FnOnce() -> Box<X>) {} // just to make sure async closures can still be suggested for boxing. fn bar<X>(x: Box<dyn FnOnce() -> X>) {} fn main() { - foo(async move || {}); //~ ERROR mismatched types + foo(async move || {}); + //~^ ERROR expected `{async closure@dont-suggest-boxing-async-closure-body.rs:9:9}` to be a closure that returns `Box<_>` bar(async move || {}); //~ ERROR mismatched types } diff --git a/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.stderr b/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.stderr new file mode 100644 index 00000000000..db2a3b9a9c1 --- /dev/null +++ b/tests/ui/suggestions/dont-suggest-boxing-async-closure-body.stderr @@ -0,0 +1,41 @@ +error[E0271]: expected `{async closure@dont-suggest-boxing-async-closure-body.rs:9:9}` to be a closure that returns `Box<_>`, but it returns `{async closure body@$DIR/dont-suggest-boxing-async-closure-body.rs:9:23: 9:25}` + --> $DIR/dont-suggest-boxing-async-closure-body.rs:9:9 + | +LL | foo(async move || {}); + | --- ^^^^^^^^^^^^^^^^ expected `Box<_>`, found `async` closure body + | | + | required by a bound introduced by this call + | + = note: expected struct `Box<_>` + found `async` closure body `{async closure body@$DIR/dont-suggest-boxing-async-closure-body.rs:9:23: 9:25}` +note: required by a bound in `foo` + --> $DIR/dont-suggest-boxing-async-closure-body.rs:4:31 + | +LL | fn foo<X>(x: impl FnOnce() -> Box<X>) {} + | ^^^^^^ required by this bound in `foo` + +error[E0308]: mismatched types + --> $DIR/dont-suggest-boxing-async-closure-body.rs:11:9 + | +LL | bar(async move || {}); + | --- ^^^^^^^^^^^^^^^^ expected `Box<dyn FnOnce() -> _>`, found `{async closure@dont-suggest-boxing-async-closure-body.rs:11:9}` + | | + | arguments to this function are incorrect + | + = note: expected struct `Box<(dyn FnOnce() -> _ + 'static)>` + found closure `{async closure@$DIR/dont-suggest-boxing-async-closure-body.rs:11:9: 11:22}` + = note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html +note: function defined here + --> $DIR/dont-suggest-boxing-async-closure-body.rs:6:4 + | +LL | fn bar<X>(x: Box<dyn FnOnce() -> X>) {} + | ^^^ ------------------------- +help: store this in the heap by calling `Box::new` + | +LL | bar(Box::new(async move || {})); + | +++++++++ + + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0308. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/suggestions/dyn-incompatible-trait-references-self.rs b/tests/ui/suggestions/dyn-incompatible-trait-references-self.rs index 4b3d5faba46..66b435247d4 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-references-self.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-references-self.rs @@ -6,10 +6,10 @@ trait Trait { //~| ERROR the size for values of type `Self` cannot be known } -fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` is not dyn compatible trait Other: Sized {} -fn foo(x: &dyn Other) {} //~ ERROR the trait `Other` cannot be made into an object +fn foo(x: &dyn Other) {} //~ ERROR the trait `Other` is not dyn compatible fn main() {} diff --git a/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr index 242c44abd9d..cb0e7fce910 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-references-self.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/dyn-incompatible-trait-references-self.rs:9:12 | LL | fn bar(x: &dyn Trait) {} - | ^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-references-self.rs:2:22 | LL | trait Trait { - | ----- this trait cannot be made into an object... + | ----- this trait is not dyn compatible... LL | fn baz(&self, _: Self) {} | ^^^^ ...because method `baz` references the `Self` type in this parameter LL | @@ -17,19 +18,20 @@ LL | fn bat(&self) -> Self {} = help: consider moving `baz` to another trait = help: consider moving `bat` to another trait -error[E0038]: the trait `Other` cannot be made into an object +error[E0038]: the trait `Other` is not dyn compatible --> $DIR/dyn-incompatible-trait-references-self.rs:13:12 | LL | fn foo(x: &dyn Other) {} - | ^^^^^^^^^ `Other` cannot be made into an object + | ^^^^^^^^^ `Other` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-references-self.rs:11:14 | LL | trait Other: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/dyn-incompatible-trait-references-self.rs:2:22 diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs index 4ab10f40eb6..747926c400a 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.rs @@ -3,12 +3,12 @@ trait A: Sized { fn f(a: dyn A) -> dyn A; //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `A` cannot be made into an object + //~| ERROR the trait `A` is not dyn compatible } trait B { fn f(a: dyn B) -> dyn B; //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `B` cannot be made into an object + //~| ERROR the trait `B` is not dyn compatible } trait C { fn f(&self, a: dyn C) -> dyn C; diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr index 5e0d1a14452..2efcad1e7bd 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self-2021.stderr @@ -11,19 +11,20 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `A` cannot be made into an object +error[E0038]: the trait `A` is not dyn compatible --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:4:13 | LL | fn f(a: dyn A) -> dyn A; - | ^^^^^ `A` cannot be made into an object + | ^^^^^ `A` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:3:10 | LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... error: associated item referring to unboxed trait object for its own trait --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:13 @@ -38,17 +39,18 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `B` cannot be made into an object +error[E0038]: the trait `B` is not dyn compatible --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:13 | LL | fn f(a: dyn B) -> dyn B; - | ^^^^^ `B` cannot be made into an object + | ^^^^^ `B` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-should-use-self-2021.rs:9:8 | LL | trait B { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | fn f(a: dyn B) -> dyn B; | ^ ...because associated function `f` has no `self` parameter help: consider turning `f` into a method by giving it a `&self` argument diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs index 75f99075eb1..2893bbc8b71 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.rs @@ -2,12 +2,12 @@ trait A: Sized { fn f(a: A) -> A; //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `A` cannot be made into an object + //~| ERROR the trait `A` is not dyn compatible } trait B { fn f(a: B) -> B; //~^ ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `B` cannot be made into an object + //~| ERROR the trait `B` is not dyn compatible } trait C { fn f(&self, a: C) -> C; diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr index 93f6ea2b12e..ecb3ee9185f 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-self.stderr @@ -11,19 +11,20 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `A` cannot be made into an object +error[E0038]: the trait `A` is not dyn compatible --> $DIR/dyn-incompatible-trait-should-use-self.rs:3:13 | LL | fn f(a: A) -> A; - | ^ `A` cannot be made into an object + | ^ `A` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-should-use-self.rs:2:10 | LL | trait A: Sized { | - ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... error: associated item referring to unboxed trait object for its own trait --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:13 @@ -38,17 +39,18 @@ help: you might have meant to use `Self` to refer to the implementing type LL | fn f(a: Self) -> Self; | ~~~~ ~~~~ -error[E0038]: the trait `B` cannot be made into an object +error[E0038]: the trait `B` is not dyn compatible --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:13 | LL | fn f(a: B) -> B; - | ^ `B` cannot be made into an object + | ^ `B` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-should-use-self.rs:8:8 | LL | trait B { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | fn f(a: B) -> B; | ^ ...because associated function `f` has no `self` parameter help: consider turning `f` into a method by giving it a `&self` argument diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed index fd9b78934c7..2b26d8cc82e 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed @@ -6,7 +6,7 @@ trait Trait { fn bar(self: &Self) {} //~ ERROR invalid `self` parameter type } -fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` is not dyn compatible trait Other {} diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.rs b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.rs index e4aa0d89239..b0b02dedb2b 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.rs +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.rs @@ -6,7 +6,7 @@ trait Trait { fn bar(self: ()) {} //~ ERROR invalid `self` parameter type } -fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` cannot be made into an object +fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` is not dyn compatible trait Other {} diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr index beafd7c2ab0..696840d3ba4 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:9:12 | LL | fn bar(x: &dyn Trait) {} - | ^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/dyn-incompatible-trait-should-use-where-sized.rs:5:8 | LL | trait Trait { - | ----- this trait cannot be made into an object... + | ----- this trait is not dyn compatible... LL | fn foo() where Self: Other, { } | ^^^ ...because associated function `foo` has no `self` parameter LL | fn bar(self: ()) {} diff --git a/tests/ui/suggestions/import-visible-path-39175.fixed b/tests/ui/suggestions/import-visible-path-39175.fixed new file mode 100644 index 00000000000..1f2b5b8b0ce --- /dev/null +++ b/tests/ui/suggestions/import-visible-path-39175.fixed @@ -0,0 +1,16 @@ +// This test ignores some platforms as the particular extension trait used +// to demonstrate the issue is only available on unix. This is fine as +// the fix to suggested paths is not platform-dependent and will apply on +// these platforms also. + +//@ run-rustfix +//@ only-unix (the diagnostics is influenced by `use std::os::unix::process::CommandExt;`) + +use std::os::unix::process::CommandExt; +use std::process::Command; +// use std::os::unix::process::CommandExt; + +fn main() { + let _ = Command::new("echo").arg("hello").exec(); +//~^ ERROR no method named `exec` +} diff --git a/tests/ui/issues/issue-39175.rs b/tests/ui/suggestions/import-visible-path-39175.rs index 7b801317b71..a7e6134b2d9 100644 --- a/tests/ui/issues/issue-39175.rs +++ b/tests/ui/suggestions/import-visible-path-39175.rs @@ -3,14 +3,13 @@ // the fix to suggested paths is not platform-dependent and will apply on // these platforms also. -//@ ignore-windows -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ run-rustfix +//@ only-unix (the diagnostics is influenced by `use std::os::unix::process::CommandExt;`) use std::process::Command; // use std::os::unix::process::CommandExt; fn main() { - Command::new("echo").arg("hello").exec(); + let _ = Command::new("echo").arg("hello").exec(); //~^ ERROR no method named `exec` } diff --git a/tests/ui/issues/issue-39175.stderr b/tests/ui/suggestions/import-visible-path-39175.stderr index bbe8badb652..0b558ca4b52 100644 --- a/tests/ui/issues/issue-39175.stderr +++ b/tests/ui/suggestions/import-visible-path-39175.stderr @@ -1,8 +1,8 @@ error[E0599]: no method named `exec` found for mutable reference `&mut Command` in the current scope - --> $DIR/issue-39175.rs:14:39 + --> $DIR/import-visible-path-39175.rs:13:47 | -LL | Command::new("echo").arg("hello").exec(); - | ^^^^ +LL | let _ = Command::new("echo").arg("hello").exec(); + | ^^^^ | = help: items from traits can only be used if the trait is in scope help: there is a method `pre_exec` with a similar name, but with different arguments diff --git a/tests/ui/suggestions/issue-109195.rs b/tests/ui/suggestions/issue-109195.rs deleted file mode 100644 index cc499b0d776..00000000000 --- a/tests/ui/suggestions/issue-109195.rs +++ /dev/null @@ -1,20 +0,0 @@ -fn main() { - String::from::utf8; - //~^ ERROR ambiguous associated type [E0223] - //~| HELP there is an associated function with a similar name: `from_utf8` - String::from::utf8(); - //~^ ERROR ambiguous associated type [E0223] - //~| HELP there is an associated function with a similar name: `from_utf8` - String::from::utf16(); - //~^ ERROR ambiguous associated type [E0223] - //~| HELP there is an associated function with a similar name: `from_utf16` - String::from::method_that_doesnt_exist(); - //~^ ERROR ambiguous associated type [E0223] - //~| HELP if there were a trait named `Example` with associated type `from` - str::from::utf8(); - //~^ ERROR ambiguous associated type [E0223] - //~| HELP if there were a trait named `Example` with associated type `from` - str::from::utf8_mut(); - //~^ ERROR ambiguous associated type [E0223] - //~| HELP if there were a trait named `Example` with associated type `from` -} diff --git a/tests/ui/suggestions/issue-109195.stderr b/tests/ui/suggestions/issue-109195.stderr deleted file mode 100644 index 10cf9cfd28c..00000000000 --- a/tests/ui/suggestions/issue-109195.stderr +++ /dev/null @@ -1,69 +0,0 @@ -error[E0223]: ambiguous associated type - --> $DIR/issue-109195.rs:2:5 - | -LL | String::from::utf8; - | ^^^^^^^^^^^^ - | -help: there is an associated function with a similar name: `from_utf8` - | -LL | String::from_utf8; - | ~~~~~~~~~ - -error[E0223]: ambiguous associated type - --> $DIR/issue-109195.rs:5:5 - | -LL | String::from::utf8(); - | ^^^^^^^^^^^^ - | -help: there is an associated function with a similar name: `from_utf8` - | -LL | String::from_utf8(); - | ~~~~~~~~~ - -error[E0223]: ambiguous associated type - --> $DIR/issue-109195.rs:8:5 - | -LL | String::from::utf16(); - | ^^^^^^^^^^^^ - | -help: there is an associated function with a similar name: `from_utf16` - | -LL | String::from_utf16(); - | ~~~~~~~~~~ - -error[E0223]: ambiguous associated type - --> $DIR/issue-109195.rs:11:5 - | -LL | String::from::method_that_doesnt_exist(); - | ^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `from` implemented for `String`, you could use the fully-qualified path - | -LL | <String as Example>::from::method_that_doesnt_exist(); - | ~~~~~~~~~~~~~~~~~~~~~~~~~ - -error[E0223]: ambiguous associated type - --> $DIR/issue-109195.rs:14:5 - | -LL | str::from::utf8(); - | ^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path - | -LL | <str as Example>::from::utf8(); - | ~~~~~~~~~~~~~~~~~~~~~~ - -error[E0223]: ambiguous associated type - --> $DIR/issue-109195.rs:17:5 - | -LL | str::from::utf8_mut(); - | ^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `from` implemented for `str`, you could use the fully-qualified path - | -LL | <str as Example>::from::utf8_mut(); - | ~~~~~~~~~~~~~~~~~~~~~~ - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/suggestions/issue-112590-suggest-import.rs b/tests/ui/suggestions/issue-112590-suggest-import.rs index 0938814c559..a7868b71919 100644 --- a/tests/ui/suggestions/issue-112590-suggest-import.rs +++ b/tests/ui/suggestions/issue-112590-suggest-import.rs @@ -1,8 +1,8 @@ pub struct S; -impl fmt::Debug for S { //~ ERROR failed to resolve: use of undeclared crate or module `fmt` - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { //~ ERROR failed to resolve: use of undeclared crate or module `fmt` - //~^ ERROR failed to resolve: use of undeclared crate or module `fmt` +impl fmt::Debug for S { //~ ERROR failed to resolve: use of unresolved module or unlinked crate `fmt` + fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { //~ ERROR failed to resolve: use of unresolved module or unlinked crate `fmt` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `fmt` Ok(()) } } diff --git a/tests/ui/suggestions/issue-112590-suggest-import.stderr b/tests/ui/suggestions/issue-112590-suggest-import.stderr index aeac18c16f0..bbbd2c481c1 100644 --- a/tests/ui/suggestions/issue-112590-suggest-import.stderr +++ b/tests/ui/suggestions/issue-112590-suggest-import.stderr @@ -1,31 +1,34 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `fmt` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `fmt` --> $DIR/issue-112590-suggest-import.rs:3:6 | LL | impl fmt::Debug for S { - | ^^^ use of undeclared crate or module `fmt` + | ^^^ use of unresolved module or unlinked crate `fmt` | + = help: you might be missing a crate named `fmt` help: consider importing this module | LL + use std::fmt; | -error[E0433]: failed to resolve: use of undeclared crate or module `fmt` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `fmt` --> $DIR/issue-112590-suggest-import.rs:4:28 | LL | fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - | ^^^ use of undeclared crate or module `fmt` + | ^^^ use of unresolved module or unlinked crate `fmt` | + = help: you might be missing a crate named `fmt` help: consider importing this module | LL + use std::fmt; | -error[E0433]: failed to resolve: use of undeclared crate or module `fmt` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `fmt` --> $DIR/issue-112590-suggest-import.rs:4:51 | LL | fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - | ^^^ use of undeclared crate or module `fmt` + | ^^^ use of unresolved module or unlinked crate `fmt` | + = help: you might be missing a crate named `fmt` help: consider importing this module | LL + use std::fmt; diff --git a/tests/ui/suggestions/issue-116434-2015.rs b/tests/ui/suggestions/issue-116434-2015.rs index 2e94473eb1a..1518765152f 100644 --- a/tests/ui/suggestions/issue-116434-2015.rs +++ b/tests/ui/suggestions/issue-116434-2015.rs @@ -7,7 +7,7 @@ trait Foo { //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| HELP if this is a dyn-compatible trait, use `dyn` - //~| ERROR the trait `Clone` cannot be made into an object [E0038] + //~| ERROR the trait `Clone` is not dyn compatible [E0038] //~| HELP there is an associated type with the same name } @@ -22,7 +22,7 @@ trait DbInterface { //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| HELP if this is a dyn-compatible trait, use `dyn` - //~| ERROR the trait `DbHandle` cannot be made into an object [E0038] + //~| ERROR the trait `DbHandle` is not dyn compatible [E0038] //~| HELP there is an associated type with the same name } diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr index 24fc87f765f..508c3ec5e4f 100644 --- a/tests/ui/suggestions/issue-116434-2015.stderr +++ b/tests/ui/suggestions/issue-116434-2015.stderr @@ -39,14 +39,15 @@ help: if this is a dyn-compatible trait, use `dyn` LL | fn foo() -> dyn Clone; | +++ -error[E0038]: the trait `Clone` cannot be made into an object +error[E0038]: the trait `Clone` is not dyn compatible --> $DIR/issue-116434-2015.rs:3:17 | LL | fn foo() -> Clone; - | ^^^^^ `Clone` cannot be made into an object + | ^^^^^ `Clone` is not dyn compatible | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> help: there is an associated type with the same name | LL | fn foo() -> Self::Clone; @@ -66,19 +67,20 @@ help: if this is a dyn-compatible trait, use `dyn` LL | fn handle() -> dyn DbHandle; | +++ -error[E0038]: the trait `DbHandle` cannot be made into an object +error[E0038]: the trait `DbHandle` is not dyn compatible --> $DIR/issue-116434-2015.rs:18:20 | LL | fn handle() -> DbHandle; - | ^^^^^^^^ `DbHandle` cannot be made into an object + | ^^^^^^^^ `DbHandle` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-116434-2015.rs:14:17 | LL | trait DbHandle: Sized {} | -------- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... + | this trait is not dyn compatible... help: there is an associated type with the same name | LL | fn handle() -> Self::DbHandle; diff --git a/tests/ui/suggestions/issue-98500.rs b/tests/ui/suggestions/issue-98500.rs index 289b16abf4b..869b665c8cb 100644 --- a/tests/ui/suggestions/issue-98500.rs +++ b/tests/ui/suggestions/issue-98500.rs @@ -9,6 +9,6 @@ pub trait B where } struct S(Box<dyn B>); -//~^ ERROR the trait `B` cannot be made into an object +//~^ ERROR the trait `B` is not dyn compatible fn main() {} diff --git a/tests/ui/suggestions/issue-98500.stderr b/tests/ui/suggestions/issue-98500.stderr index d7136ec1a64..97b712acfcb 100644 --- a/tests/ui/suggestions/issue-98500.stderr +++ b/tests/ui/suggestions/issue-98500.stderr @@ -1,10 +1,11 @@ -error[E0038]: the trait `B` cannot be made into an object +error[E0038]: the trait `B` is not dyn compatible --> $DIR/issue-98500.rs:11:14 | LL | struct S(Box<dyn B>); - | ^^^^^ `B` cannot be made into an object + | ^^^^^ `B` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/auxiliary/dyn-incompatible.rs:4:8 | LL | fn f(); @@ -15,7 +16,7 @@ LL | fn f2(self: &Arc<Self>); ::: $DIR/issue-98500.rs:5:11 | LL | pub trait B where - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... = help: consider moving `f` to another trait = help: consider moving `f2` to another trait diff --git a/tests/ui/suggestions/undeclared-module-alloc.rs b/tests/ui/suggestions/undeclared-module-alloc.rs index e5f22369b94..a0bddc94471 100644 --- a/tests/ui/suggestions/undeclared-module-alloc.rs +++ b/tests/ui/suggestions/undeclared-module-alloc.rs @@ -1,5 +1,5 @@ //@ edition:2018 -use alloc::rc::Rc; //~ ERROR failed to resolve: use of undeclared crate or module `alloc` +use alloc::rc::Rc; //~ ERROR failed to resolve: use of unresolved module or unlinked crate `alloc` fn main() {} diff --git a/tests/ui/suggestions/undeclared-module-alloc.stderr b/tests/ui/suggestions/undeclared-module-alloc.stderr index a439546492b..00e498aa9ba 100644 --- a/tests/ui/suggestions/undeclared-module-alloc.stderr +++ b/tests/ui/suggestions/undeclared-module-alloc.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `alloc` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `alloc` --> $DIR/undeclared-module-alloc.rs:3:5 | LL | use alloc::rc::Rc; - | ^^^^^ use of undeclared crate or module `alloc` + | ^^^^^ use of unresolved module or unlinked crate `alloc` | = help: add `extern crate alloc` to use the `alloc` crate diff --git a/tests/ui/test-attrs/terse.rs b/tests/ui/test-attrs/terse.rs index 6c3f29ed10f..6e605f994f2 100644 --- a/tests/ui/test-attrs/terse.rs +++ b/tests/ui/test-attrs/terse.rs @@ -4,7 +4,7 @@ //@ check-run-results //@ exec-env:RUST_BACKTRACE=0 //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-emscripten no threads support +//@ needs-threads //@ needs-unwind #[test] diff --git a/tests/ui/test-attrs/test-panic-abort-disabled.rs b/tests/ui/test-attrs/test-panic-abort-disabled.rs index fbe3d7d5d18..05dd9395c2b 100644 --- a/tests/ui/test-attrs/test-panic-abort-disabled.rs +++ b/tests/ui/test-attrs/test-panic-abort-disabled.rs @@ -4,8 +4,9 @@ //@ run-flags: --test-threads=1 //@ needs-unwind -//@ ignore-wasm no panic or subprocess support -//@ ignore-emscripten no panic or subprocess support +//@ ignore-wasm no panic support +//@ ignore-emscripten no panic support +//@ needs-subprocess #![cfg(test)] diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.rs b/tests/ui/test-attrs/test-panic-abort-nocapture.rs index 4377ae1ac3b..f7e15dbdbc3 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.rs +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.rs @@ -7,9 +7,9 @@ //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ ignore-android #120567 -//@ ignore-wasm no panic or subprocess support -//@ ignore-emscripten no panic or subprocess support -//@ ignore-sgx no subprocess support +//@ ignore-wasm no panic support +//@ ignore-emscripten no panic support +//@ needs-subprocess #![cfg(test)] diff --git a/tests/ui/test-attrs/test-panic-abort.rs b/tests/ui/test-attrs/test-panic-abort.rs index 3d203e059a4..951cf54346b 100644 --- a/tests/ui/test-attrs/test-panic-abort.rs +++ b/tests/ui/test-attrs/test-panic-abort.rs @@ -7,9 +7,9 @@ //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ ignore-android #120567 -//@ ignore-wasm no panic or subprocess support -//@ ignore-emscripten no panic or subprocess support -//@ ignore-sgx no subprocess support +//@ ignore-wasm no panic support +//@ ignore-emscripten no panic support +//@ needs-subprocess #![cfg(test)] #![feature(test)] diff --git a/tests/ui/test-attrs/test-runner-hides-start.rs b/tests/ui/test-attrs/test-runner-hides-start.rs deleted file mode 100644 index 444ac237cfa..00000000000 --- a/tests/ui/test-attrs/test-runner-hides-start.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -//@ compile-flags: --test - -#![feature(start)] - -#[start] -fn start(_: isize, _: *const *const u8) -> isize { panic!(); } diff --git a/tests/ui/test-attrs/test-thread-capture.rs b/tests/ui/test-attrs/test-thread-capture.rs index c56f87f2dda..0a5b1e9816f 100644 --- a/tests/ui/test-attrs/test-thread-capture.rs +++ b/tests/ui/test-attrs/test-thread-capture.rs @@ -4,7 +4,7 @@ //@ check-run-results //@ exec-env:RUST_BACKTRACE=0 //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-emscripten no threads support +//@ needs-threads //@ needs-unwind #[test] diff --git a/tests/ui/test-attrs/test-thread-nocapture.rs b/tests/ui/test-attrs/test-thread-nocapture.rs index 5b82e9b2720..ce5db7bf1c3 100644 --- a/tests/ui/test-attrs/test-thread-nocapture.rs +++ b/tests/ui/test-attrs/test-thread-nocapture.rs @@ -4,7 +4,7 @@ //@ check-run-results //@ exec-env:RUST_BACKTRACE=0 //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-emscripten no threads support +//@ needs-threads //@ needs-unwind #[test] diff --git a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs index 82abf21df3f..e85c7c83339 100644 --- a/tests/ui/threads-sendsync/eprint-on-tls-drop.rs +++ b/tests/ui/threads-sendsync/eprint-on-tls-drop.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-threads -//@ ignore-sgx no processes +//@ needs-subprocess use std::cell::RefCell; use std::env; diff --git a/tests/ui/threads-sendsync/issue-24313.rs b/tests/ui/threads-sendsync/issue-24313.rs index 99c6c4a5e12..83ab5122e82 100644 --- a/tests/ui/threads-sendsync/issue-24313.rs +++ b/tests/ui/threads-sendsync/issue-24313.rs @@ -1,6 +1,6 @@ //@ run-pass //@ needs-threads -//@ ignore-sgx no processes +//@ needs-subprocess use std::process::Command; use std::{env, thread}; diff --git a/tests/ui/tool-attributes/unknown-tool-name.rs b/tests/ui/tool-attributes/unknown-tool-name.rs index 73fca61c65d..ba21aecc230 100644 --- a/tests/ui/tool-attributes/unknown-tool-name.rs +++ b/tests/ui/tool-attributes/unknown-tool-name.rs @@ -1,2 +1,2 @@ -#[foo::bar] //~ ERROR failed to resolve: use of undeclared crate or module `foo` +#[foo::bar] //~ ERROR failed to resolve: use of unresolved module or unlinked crate `foo` fn main() {} diff --git a/tests/ui/tool-attributes/unknown-tool-name.stderr b/tests/ui/tool-attributes/unknown-tool-name.stderr index 361d359a10e..9b636fcb0bd 100644 --- a/tests/ui/tool-attributes/unknown-tool-name.stderr +++ b/tests/ui/tool-attributes/unknown-tool-name.stderr @@ -1,8 +1,8 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `foo` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `foo` --> $DIR/unknown-tool-name.rs:1:3 | LL | #[foo::bar] - | ^^^ use of undeclared crate or module `foo` + | ^^^ use of unresolved module or unlinked crate `foo` error: aborting due to 1 previous error diff --git a/tests/ui/traits/alias/generic-default-in-dyn.rs b/tests/ui/traits/alias/generic-default-in-dyn.rs index d44e1c2a975..b263e578c31 100644 --- a/tests/ui/traits/alias/generic-default-in-dyn.rs +++ b/tests/ui/traits/alias/generic-default-in-dyn.rs @@ -2,9 +2,9 @@ trait SendEqAlias<T> = PartialEq; //~^ ERROR trait aliases are experimental struct Foo<T>(dyn SendEqAlias<T>); -//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393] +//~^ ERROR the trait alias `SendEqAlias` is not dyn compatible struct Bar<T>(dyn SendEqAlias<T>, T); -//~^ ERROR the type parameter `Rhs` must be explicitly specified [E0393] +//~^ ERROR the trait alias `SendEqAlias` is not dyn compatible fn main() {} diff --git a/tests/ui/traits/alias/generic-default-in-dyn.stderr b/tests/ui/traits/alias/generic-default-in-dyn.stderr index 50031e184c1..1ab9e6d5c5c 100644 --- a/tests/ui/traits/alias/generic-default-in-dyn.stderr +++ b/tests/ui/traits/alias/generic-default-in-dyn.stderr @@ -8,29 +8,37 @@ LL | trait SendEqAlias<T> = PartialEq; = help: add `#![feature(trait_alias)]` 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[E0393]: the type parameter `Rhs` must be explicitly specified +error[E0038]: the trait alias `SendEqAlias` is not dyn compatible --> $DIR/generic-default-in-dyn.rs:4:19 | LL | struct Foo<T>(dyn SendEqAlias<T>); - | ^^^^^^^^^^^^^^ missing reference to `Rhs` - --> $SRC_DIR/core/src/cmp.rs:LL:COL + | ^^^^^^^^^^^^^^ `SendEqAlias` is not dyn compatible | - = note: type parameter `Rhs` must be specified for this +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/generic-default-in-dyn.rs:1:24 | - = note: because of the default `Self` reference, type parameters must be specified on object types +LL | trait SendEqAlias<T> = PartialEq; + | ----------- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait is not dyn compatible... -error[E0393]: the type parameter `Rhs` must be explicitly specified +error[E0038]: the trait alias `SendEqAlias` is not dyn compatible --> $DIR/generic-default-in-dyn.rs:7:19 | LL | struct Bar<T>(dyn SendEqAlias<T>, T); - | ^^^^^^^^^^^^^^ missing reference to `Rhs` - --> $SRC_DIR/core/src/cmp.rs:LL:COL + | ^^^^^^^^^^^^^^ `SendEqAlias` is not dyn compatible | - = note: type parameter `Rhs` must be specified for this +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/generic-default-in-dyn.rs:1:24 | - = note: because of the default `Self` reference, type parameters must be specified on object types +LL | trait SendEqAlias<T> = PartialEq; + | ----------- ^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait is not dyn compatible... error: aborting due to 3 previous errors -Some errors have detailed explanations: E0393, E0658. -For more information about an error, try `rustc --explain E0393`. +Some errors have detailed explanations: E0038, E0658. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/alias/no-duplicates.stderr b/tests/ui/traits/alias/no-duplicates.stderr index bf244b97e9b..6a901a80554 100644 --- a/tests/ui/traits/alias/no-duplicates.stderr +++ b/tests/ui/traits/alias/no-duplicates.stderr @@ -4,32 +4,32 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait ... LL | type _T00 = dyn _0 + _0; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:19:22 + --> $DIR/no-duplicates.rs:19:17 | LL | trait _0 = Obj; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T01 = dyn _1 + _0; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -40,18 +40,18 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _1 = _0; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias ... LL | type _T02 = dyn _1 + _1; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -62,10 +62,10 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T03 = dyn Obj + _1; - | --- ^^ trait alias used in trait object type (additional use) + | --- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -73,17 +73,17 @@ LL | type _T03 = dyn Obj + _1; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:28:22 + --> $DIR/no-duplicates.rs:28:17 | LL | trait _0 = Obj; - | --- first non-auto trait + | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T04 = dyn _1 + Obj; - | -- ^^^ additional non-auto trait + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -92,23 +92,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/no-duplicates.rs:37:17 | LL | trait _0 = Obj; - | --- - | | - | additional non-auto trait - | first non-auto trait -LL | trait _1 = _0; - | -- referenced here (additional use) + | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- -- referenced here (additional use) - | | - | referenced here (first use) + | -- second non-auto trait comes from this alias +LL | trait _3 = Obj; + | --- first non-auto trait ... LL | type _T10 = dyn _2 + _3; - | ^^ + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -120,14 +114,14 @@ LL | trait _0 = Obj; | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _3 = Obj; | --- first non-auto trait ... LL | type _T11 = dyn _3 + _2; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -139,10 +133,10 @@ LL | trait _0 = Obj; | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T12 = dyn Obj + _2; - | --- ^^ trait alias used in trait object type (additional use) + | --- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -153,42 +147,34 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/no-duplicates.rs:46:17 | LL | trait _0 = Obj; - | --- - | | - | additional non-auto trait - | first non-auto trait -LL | trait _1 = _0; - | -- referenced here (additional use) + | --- additional non-auto trait ... LL | trait _2 = _0 + _1; - | -- -- referenced here (additional use) - | | - | referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T13 = dyn _2 + Obj; - | ^^ + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:49:22 + --> $DIR/no-duplicates.rs:49:17 | LL | trait _0 = Obj; - | --- first non-auto trait + | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _3 = Obj; - | --- additional non-auto trait + | --- first non-auto trait ... LL | type _T14 = dyn _1 + _3; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -199,15 +185,15 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | trait _3 = Obj; | --- first non-auto trait ... LL | type _T15 = dyn _3 + _1; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -218,17 +204,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- first non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- first non-auto trait comes from this alias ... LL | trait _3 = Obj; | --- additional non-auto trait LL | trait _4 = _3; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T16 = dyn _1 + _4; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -239,17 +225,17 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = Obj; | --- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | trait _3 = Obj; | --- first non-auto trait LL | trait _4 = _3; - | -- referenced here (first use) + | -- first non-auto trait comes from this alias ... LL | type _T17 = dyn _4 + _1; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -260,13 +246,13 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | LL | type _T20 = dyn _5 + _5; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -278,7 +264,7 @@ LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | type _T21 = dyn Obj + _5; - | --- ^^ trait alias used in trait object type (additional use) + | --- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -286,29 +272,29 @@ LL | type _T21 = dyn Obj + _5; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:71:22 + --> $DIR/no-duplicates.rs:71:17 | LL | trait _5 = Obj + Send; - | --- first non-auto trait + | --- additional non-auto trait ... LL | type _T22 = dyn _5 + Obj; - | -- ^^^ additional non-auto trait + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:74:36 + --> $DIR/no-duplicates.rs:74:17 | LL | trait _5 = Obj + Send; - | --- first non-auto trait + | --- additional non-auto trait ... LL | type _T23 = dyn _5 + Send + Sync + Obj; - | -- ^^^ additional non-auto trait + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -319,19 +305,19 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- -- referenced here (additional use) + | -- -- second non-auto trait comes from this alias | | - | referenced here (first use) + | first non-auto trait comes from this alias LL | LL | type _T30 = dyn _6; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -342,19 +328,19 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- -- referenced here (additional use) + | -- -- second non-auto trait comes from this alias | | - | referenced here (first use) + | first non-auto trait comes from this alias ... LL | type _T31 = dyn _6 + Send; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -365,38 +351,38 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _5 = Obj + Send; | --- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait ... LL | trait _6 = _5 + _5; // ==> Obj + Send + Obj + Send - | -- -- referenced here (additional use) + | -- -- second non-auto trait comes from this alias | | - | referenced here (first use) + | first non-auto trait comes from this alias ... LL | type _T32 = dyn Send + _6; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:95:22 + --> $DIR/no-duplicates.rs:95:17 | LL | trait _5 = Obj + Send; - | --- first non-auto trait + | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | LL | type _T40 = dyn _8 + Obj; - | -- ^^^ additional non-auto trait + | ^^ --- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -408,12 +394,12 @@ LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T41 = dyn Obj + _8; - | --- ^^ trait alias used in trait object type (additional use) + | --- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -421,25 +407,25 @@ LL | type _T41 = dyn Obj + _8; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-duplicates.rs:101:22 + --> $DIR/no-duplicates.rs:101:17 | LL | trait _3 = Obj; - | --- additional non-auto trait + | --- first non-auto trait LL | trait _4 = _3; - | -- referenced here (additional use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Obj + Send; - | --- first non-auto trait + | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T42 = dyn _8 + _4; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -450,20 +436,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _3 = Obj; | --- first non-auto trait LL | trait _4 = _3; - | -- referenced here (first use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T43 = dyn _4 + _8; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -474,20 +460,20 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _3 = Obj; | --- first non-auto trait LL | trait _4 = _3; - | -- referenced here (first use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Obj + Send; | --- additional non-auto trait ... LL | trait _7 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _8 = Unpin + _7; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T44 = dyn _4 + Send + Sync + _8; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Obj + Obj {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -500,9 +486,9 @@ LL | trait _9 = for<'a> ObjL<'a>; LL | trait _10 = for<'b> ObjL<'b>; | ---------------- additional non-auto trait LL | type _T50 = dyn _9 + _10; - | -- ^^^ trait alias used in trait object type (additional use) + | -- ^^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: for<'a> ObjL<'a> + for<'b> ObjL<'b> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -515,9 +501,9 @@ LL | trait _11 = ObjT<for<'a> fn(&'a u8)>; LL | trait _12 = ObjT<for<'b> fn(&'b u8)>; | ------------------------ additional non-auto trait LL | type _T60 = dyn _11 + _12; - | --- ^^^ trait alias used in trait object type (additional use) + | --- ^^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjT<for<'a> fn(&'a u8)> + ObjT<for<'b> fn(&'b u8)> {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> diff --git a/tests/ui/traits/alias/no-extra-traits.stderr b/tests/ui/traits/alias/no-extra-traits.stderr index 4b1ddf6843c..fcdb4937ff5 100644 --- a/tests/ui/traits/alias/no-extra-traits.stderr +++ b/tests/ui/traits/alias/no-extra-traits.stderr @@ -1,15 +1,15 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:16:22 + --> $DIR/no-extra-traits.rs:16:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | type _T00 = dyn _0 + ObjB; - | -- ^^^^ additional non-auto trait + | ^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object @@ -19,7 +19,7 @@ LL | trait _0 = ObjA; | ---- additional non-auto trait ... LL | type _T01 = dyn ObjB + _0; - | ---- ^^ trait alias used in trait object type (additional use) + | ---- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -32,10 +32,10 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T02 = dyn ObjB + _1; - | ---- ^^ trait alias used in trait object type (additional use) + | ---- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -43,19 +43,19 @@ LL | type _T02 = dyn ObjB + _1; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:25:22 + --> $DIR/no-extra-traits.rs:25:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T03 = dyn _1 + ObjB; - | -- ^^^^ additional non-auto trait + | ^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object @@ -64,34 +64,34 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _2 = ObjB; | ---- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _3 = _2; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T10 = dyn _2 + _3; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:37:22 + --> $DIR/no-extra-traits.rs:37:17 | LL | trait _2 = ObjB; | ---- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _3 = _2; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T11 = dyn _3 + _2; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -102,38 +102,38 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _2 = ObjB; | ---- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _3 = _2; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _4 = _3; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T12 = dyn _2 + _4; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:43:22 + --> $DIR/no-extra-traits.rs:43:17 | LL | trait _2 = ObjB; | ---- | | - | additional non-auto trait | first non-auto trait + | additional non-auto trait LL | trait _3 = _2; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _4 = _3; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T13 = dyn _4 + _2; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> @@ -144,50 +144,50 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait LL | LL | type _T20 = dyn _5 + _1; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:53:22 + --> $DIR/no-extra-traits.rs:53:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | type _T21 = dyn _1 + _5; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:56:22 + --> $DIR/no-extra-traits.rs:56:17 | LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | type _T22 = dyn _5 + ObjA; - | -- ^^^^ additional non-auto trait + | ^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object @@ -197,7 +197,7 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T23 = dyn ObjA + _5; - | ---- ^^ trait alias used in trait object type (additional use) + | ---- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -210,50 +210,50 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec LL | trait _0 = ObjA; | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; | ---- first non-auto trait ... LL | type _T24 = dyn Send + _5 + _1 + Sync; - | -- ^^ trait alias used in trait object type (additional use) + | -- ^^ second non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias | = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:65:29 + --> $DIR/no-extra-traits.rs:65:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | type _T25 = dyn _1 + Sync + _5 + Send; - | -- ^^ trait alias used in trait object type (additional use) + | ^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:68:36 + --> $DIR/no-extra-traits.rs:68:31 | LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | type _T26 = dyn Sync + Send + _5 + ObjA; - | -- ^^^^ additional non-auto trait + | ^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object @@ -263,7 +263,7 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | type _T27 = dyn Send + Sync + ObjA + _5; - | ---- ^^ trait alias used in trait object type (additional use) + | ---- ^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -274,199 +274,199 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec --> $DIR/no-extra-traits.rs:80:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias ... LL | type _T30 = dyn _6; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:83:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias ... LL | type _T31 = dyn _6 + Send; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:86:24 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias ... LL | type _T32 = dyn Send + _6; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:89:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias LL | trait _7 = _6; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias LL | trait _8 = _7; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias ... LL | type _T33 = dyn _8; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:92:17 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias LL | trait _7 = _6; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias LL | trait _8 = _7; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias ... LL | type _T34 = dyn _8 + Send; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object --> $DIR/no-extra-traits.rs:95:24 | LL | trait _0 = ObjA; - | ---- first non-auto trait + | ---- additional non-auto trait LL | trait _1 = _0; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- additional non-auto trait + | ---- first non-auto trait ... LL | trait _6 = _1 + _5; - | -- -- referenced here (additional use) + | -- -- first non-auto trait comes from this alias | | - | referenced here (first use) + | second non-auto trait comes from this alias LL | trait _7 = _6; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias LL | trait _8 = _7; | -- | | - | referenced here (additional use) - | referenced here (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias ... LL | type _T35 = dyn Send + _8; | ^^ | | - | trait alias used in trait object type (additional use) - | trait alias used in trait object type (first use) + | first non-auto trait comes from this alias + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:103:23 + --> $DIR/no-extra-traits.rs:103:17 | LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | LL | type _T40 = dyn _10 + ObjA; - | --- ^^^^ additional non-auto trait + | ^^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object @@ -476,12 +476,12 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T41 = dyn ObjA + _10; - | ---- ^^^ trait alias used in trait object type (additional use) + | ---- ^^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -489,46 +489,46 @@ LL | type _T41 = dyn ObjA + _10; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:109:23 + --> $DIR/no-extra-traits.rs:109:17 | LL | trait _0 = ObjA; - | ---- additional non-auto trait + | ---- first non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T42 = dyn _10 + _1; - | --- ^^ trait alias used in trait object type (additional use) + | ^^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:112:37 + --> $DIR/no-extra-traits.rs:112:24 | LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T43 = dyn Send + _10 + Sync + ObjA; - | --- ^^^^ additional non-auto trait + | ^^^ ---- first non-auto trait | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object @@ -538,12 +538,12 @@ LL | trait _5 = Sync + ObjB + Send; | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (additional use) + | -- second non-auto trait comes from this alias ... LL | type _T44 = dyn ObjA + _10 + Send + Sync; - | ---- ^^^ trait alias used in trait object type (additional use) + | ---- ^^^ second non-auto trait comes from this alias | | | first non-auto trait | @@ -551,27 +551,27 @@ LL | type _T44 = dyn ObjA + _10 + Send + Sync; = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/no-extra-traits.rs:118:37 + --> $DIR/no-extra-traits.rs:118:31 | LL | trait _0 = ObjA; - | ---- additional non-auto trait + | ---- first non-auto trait LL | trait _1 = _0; - | -- referenced here (additional use) + | -- first non-auto trait comes from this alias ... LL | trait _5 = Sync + ObjB + Send; - | ---- first non-auto trait + | ---- additional non-auto trait ... LL | trait _9 = _5 + Sync; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias LL | trait _10 = Unpin + _9; - | -- referenced here (first use) + | -- second non-auto trait comes from this alias ... LL | type _T45 = dyn Sync + Send + _10 + _1; - | --- ^^ trait alias used in trait object type (additional use) + | ^^^ -- first non-auto trait comes from this alias | | - | trait alias used in trait object type (first use) + | second non-auto trait comes from this alias | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjB + ObjA {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: ObjA + ObjB {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error: aborting due to 28 previous errors diff --git a/tests/ui/traits/alias/object-fail.rs b/tests/ui/traits/alias/object-fail.rs index 5c753ff207c..9a1cbad53e7 100644 --- a/tests/ui/traits/alias/object-fail.rs +++ b/tests/ui/traits/alias/object-fail.rs @@ -5,7 +5,7 @@ trait IteratorAlias = Iterator; fn main() { let _: &dyn EqAlias = &123; - //~^ ERROR the trait `Eq` cannot be made into an object [E0038] + //~^ ERROR the trait alias `EqAlias` is not dyn compatible [E0038] let _: &dyn IteratorAlias = &vec![123].into_iter(); //~^ ERROR must be specified } diff --git a/tests/ui/traits/alias/object-fail.stderr b/tests/ui/traits/alias/object-fail.stderr index 1b89b87db9f..52ce79a4597 100644 --- a/tests/ui/traits/alias/object-fail.stderr +++ b/tests/ui/traits/alias/object-fail.stderr @@ -1,13 +1,19 @@ -error[E0038]: the trait `Eq` cannot be made into an object - --> $DIR/object-fail.rs:7:13 +error[E0038]: the trait alias `EqAlias` is not dyn compatible + --> $DIR/object-fail.rs:7:17 | LL | let _: &dyn EqAlias = &123; - | ^^^^^^^^^^^ `Eq` cannot be made into an object + | ^^^^^^^ `EqAlias` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $SRC_DIR/core/src/cmp.rs:LL:COL | - = note: the trait cannot be made into an object because it uses `Self` as a type parameter + = note: ...because it uses `Self` as a type parameter + | + ::: $DIR/object-fail.rs:3:7 + | +LL | trait EqAlias = Eq; + | ------- this trait is not dyn compatible... error[E0191]: the value of the associated type `Item` in `Iterator` must be specified --> $DIR/object-fail.rs:9:17 diff --git a/tests/ui/traits/alias/self-in-const-generics.rs b/tests/ui/traits/alias/self-in-const-generics.rs index b0de8ccd678..a7d0ac9cbb4 100644 --- a/tests/ui/traits/alias/self-in-const-generics.rs +++ b/tests/ui/traits/alias/self-in-const-generics.rs @@ -7,6 +7,6 @@ trait Bar<const N: usize> {} trait BB = Bar<{ 2 + 1 }>; fn foo(x: &dyn BB) {} -//~^ ERROR the trait alias `BB` cannot be made into an object [E0038] +//~^ ERROR the trait alias `BB` is not dyn compatible [E0038] fn main() {} diff --git a/tests/ui/traits/alias/self-in-const-generics.stderr b/tests/ui/traits/alias/self-in-const-generics.stderr index 3de31b64c8b..3c799492591 100644 --- a/tests/ui/traits/alias/self-in-const-generics.stderr +++ b/tests/ui/traits/alias/self-in-const-generics.stderr @@ -1,10 +1,21 @@ -error[E0038]: the trait alias `BB` cannot be made into an object +error[E0038]: the trait alias `BB` is not dyn compatible --> $DIR/self-in-const-generics.rs:9:16 | LL | fn foo(x: &dyn BB) {} - | ^^ + | ^^ `BB` is not dyn compatible | - = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/self-in-const-generics.rs:7:12 + | +LL | trait BB = Bar<{ 2 + 1 }>; + | -- ^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter + | | + | this trait is not dyn compatible... +help: consider using an opaque type instead + | +LL | fn foo(x: &impl BB) {} + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/traits/alias/self-in-generics.rs b/tests/ui/traits/alias/self-in-generics.rs index 433b741532d..53752d9cede 100644 --- a/tests/ui/traits/alias/self-in-generics.rs +++ b/tests/ui/traits/alias/self-in-generics.rs @@ -6,6 +6,6 @@ pub trait SelfInput = Fn(&mut Self); pub fn f(_f: &dyn SelfInput) {} -//~^ ERROR the trait alias `SelfInput` cannot be made into an object [E0038] +//~^ ERROR the trait alias `SelfInput` is not dyn compatible [E0038] fn main() {} diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr index ffc0a00ad7d..5639b2b44a1 100644 --- a/tests/ui/traits/alias/self-in-generics.stderr +++ b/tests/ui/traits/alias/self-in-generics.stderr @@ -1,10 +1,23 @@ -error[E0038]: the trait alias `SelfInput` cannot be made into an object +error[E0038]: the trait alias `SelfInput` is not dyn compatible --> $DIR/self-in-generics.rs:8:19 | LL | pub fn f(_f: &dyn SelfInput) {} - | ^^^^^^^^^ + | ^^^^^^^^^ `SelfInput` is not dyn compatible | - = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/self-in-generics.rs:6:23 + | +LL | pub trait SelfInput = Fn(&mut Self); + | --------- ^^^^^^^^^^^^^ + | | | + | | ...because it uses `Self` as a type parameter + | | ...because it uses `Self` as a type parameter + | this trait is not dyn compatible... +help: consider using an opaque type instead + | +LL | pub fn f(_f: &impl SelfInput) {} + | ~~~~ error: aborting due to 1 previous error diff --git a/tests/ui/traits/bad-sized.stderr b/tests/ui/traits/bad-sized.stderr index 0e82867ef03..21718cf0951 100644 --- a/tests/ui/traits/bad-sized.stderr +++ b/tests/ui/traits/bad-sized.stderr @@ -1,12 +1,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait object - --> $DIR/bad-sized.rs:4:28 + --> $DIR/bad-sized.rs:4:20 | LL | let x: Vec<dyn Trait + Sized> = Vec::new(); - | ----- ^^^^^ additional non-auto trait + | ^^^^^ ----- first non-auto trait | | - | first non-auto trait + | additional non-auto trait | - = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Trait + Sized {}` + = help: consider creating a new trait with all of these as supertraits and using that trait here instead: `trait NewTrait: Sized + Trait {}` = note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits> error: aborting due to 1 previous error diff --git a/tests/ui/traits/const-traits/staged-api.stderr b/tests/ui/traits/const-traits/staged-api.stderr index 29aafa4e0f3..acc93f747a8 100644 --- a/tests/ui/traits/const-traits/staged-api.stderr +++ b/tests/ui/traits/const-traits/staged-api.stderr @@ -106,7 +106,7 @@ error: const function that might be (indirectly) exposed to stable cannot use `# LL | const_context_not_const_stable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unstable features help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) | LL + #[rustc_const_unstable(feature = "...", issue = "...")] diff --git a/tests/ui/traits/issue-20692.rs b/tests/ui/traits/issue-20692.rs index 1cb2d8c7302..10611a232f7 100644 --- a/tests/ui/traits/issue-20692.rs +++ b/tests/ui/traits/issue-20692.rs @@ -2,10 +2,10 @@ trait Array: Sized + Copy {} fn f<T: Array>(x: &T) { let _ = x - //~^ ERROR `Array` cannot be made into an object + //~^ ERROR `Array` is not dyn compatible as &dyn Array; - //~^ ERROR `Array` cannot be made into an object + //~^ ERROR `Array` is not dyn compatible } fn main() {} diff --git a/tests/ui/traits/issue-20692.stderr b/tests/ui/traits/issue-20692.stderr index 5e6a967fdc4..50ea7cde961 100644 --- a/tests/ui/traits/issue-20692.stderr +++ b/tests/ui/traits/issue-20692.stderr @@ -1,32 +1,34 @@ -error[E0038]: the trait `Array` cannot be made into an object +error[E0038]: the trait `Array` is not dyn compatible --> $DIR/issue-20692.rs:7:5 | LL | &dyn Array; - | ^^^^^^^^^^ `Array` cannot be made into an object + | ^^^^^^^^^^ `Array` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-20692.rs:1:14 | LL | trait Array: Sized + Copy {} | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized` | | | | | ...because it requires `Self: Sized` - | this trait cannot be made into an object... + | this trait is not dyn compatible... -error[E0038]: the trait `Array` cannot be made into an object +error[E0038]: the trait `Array` is not dyn compatible --> $DIR/issue-20692.rs:4:13 | LL | let _ = x - | ^ `Array` cannot be made into an object + | ^ `Array` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-20692.rs:1:14 | LL | trait Array: Sized + Copy {} | ----- ^^^^^ ^^^^ ...because it requires `Self: Sized` | | | | | ...because it requires `Self: Sized` - | this trait cannot be made into an object... + | this trait is not dyn compatible... = note: required for the cast from `&T` to `&dyn Array` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/issue-28576.rs b/tests/ui/traits/issue-28576.rs index e19bd263581..fd026044401 100644 --- a/tests/ui/traits/issue-28576.rs +++ b/tests/ui/traits/issue-28576.rs @@ -6,7 +6,7 @@ pub trait Bar: Foo<Assoc=()> { //~^ ERROR: the size for values of type `Self` cannot be known //~| ERROR: the size for values of type `Self` cannot be known fn new(&self, b: & - dyn Bar //~ ERROR the trait `Bar` cannot be made into an object + dyn Bar //~ ERROR the trait `Bar` is not dyn compatible <Assoc=()> ); } diff --git a/tests/ui/traits/issue-28576.stderr b/tests/ui/traits/issue-28576.stderr index 23581f2ee51..ba113d573d6 100644 --- a/tests/ui/traits/issue-28576.stderr +++ b/tests/ui/traits/issue-28576.stderr @@ -18,14 +18,16 @@ help: consider relaxing the implicit `Sized` restriction LL | pub trait Foo<RHS: ?Sized=Self> { | ++++++++ -error[E0038]: the trait `Bar` cannot be made into an object - --> $DIR/issue-28576.rs:9:12 +error[E0038]: the trait `Bar` is not dyn compatible + --> $DIR/issue-28576.rs:9:16 | -LL | / dyn Bar +LL | dyn Bar + | ________________^ LL | | <Assoc=()> - | |________________________^ `Bar` cannot be made into an object + | |________________________^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-28576.rs:5:16 | LL | pub trait Bar: Foo<Assoc=()> { @@ -33,7 +35,7 @@ LL | pub trait Bar: Foo<Assoc=()> { | | | | | | | ...because it uses `Self` as a type parameter | | ...because it uses `Self` as a type parameter - | this trait cannot be made into an object... + | this trait is not dyn compatible... help: consider using an opaque type instead | LL | impl Bar diff --git a/tests/ui/traits/issue-38404.rs b/tests/ui/traits/issue-38404.rs index 9b60116f733..36da594c015 100644 --- a/tests/ui/traits/issue-38404.rs +++ b/tests/ui/traits/issue-38404.rs @@ -1,8 +1,8 @@ trait A<T>: std::ops::Add<Self> + Sized {} trait B<T>: A<T> {} trait C<T>: A<dyn B<T, Output = usize>> {} -//~^ ERROR the trait `B` cannot be made into an object -//~| ERROR the trait `B` cannot be made into an object -//~| ERROR the trait `B` cannot be made into an object +//~^ ERROR the trait `B` is not dyn compatible +//~| ERROR the trait `B` is not dyn compatible +//~| ERROR the trait `B` is not dyn compatible fn main() {} diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr index 145eeb88dd5..f9e592255dd 100644 --- a/tests/ui/traits/issue-38404.stderr +++ b/tests/ui/traits/issue-38404.stderr @@ -1,45 +1,48 @@ -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/issue-38404.rs:3:15 +error[E0038]: the trait `B` is not dyn compatible + --> $DIR/issue-38404.rs:3:19 | LL | trait C<T>: A<dyn B<T, Output = usize>> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `B` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-38404.rs:1:13 | LL | trait A<T>: std::ops::Add<Self> + Sized {} | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter LL | trait B<T>: A<T> {} - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/issue-38404.rs:3:15 +error[E0038]: the trait `B` is not dyn compatible + --> $DIR/issue-38404.rs:3:19 | LL | trait C<T>: A<dyn B<T, Output = usize>> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `B` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-38404.rs:1:13 | LL | trait A<T>: std::ops::Add<Self> + Sized {} | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter LL | trait B<T>: A<T> {} - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0038]: the trait `B` cannot be made into an object - --> $DIR/issue-38404.rs:3:15 +error[E0038]: the trait `B` is not dyn compatible + --> $DIR/issue-38404.rs:3:19 | LL | trait C<T>: A<dyn B<T, Output = usize>> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^ `B` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-38404.rs:1:13 | LL | trait A<T>: std::ops::Add<Self> + Sized {} | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter LL | trait B<T>: A<T> {} - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/traits/issue-38604.rs b/tests/ui/traits/issue-38604.rs index 002a3c43fcb..d90aa61ef9f 100644 --- a/tests/ui/traits/issue-38604.rs +++ b/tests/ui/traits/issue-38604.rs @@ -11,6 +11,6 @@ impl Foo for () { } fn main() { - let _f: Box<dyn Foo> = //~ ERROR `Foo` cannot be made into an object - Box::new(()); //~ ERROR `Foo` cannot be made into an object + let _f: Box<dyn Foo> = //~ ERROR `Foo` is not dyn compatible + Box::new(()); //~ ERROR `Foo` is not dyn compatible } diff --git a/tests/ui/traits/issue-38604.stderr b/tests/ui/traits/issue-38604.stderr index 5c788b0c85d..94f9c1540ad 100644 --- a/tests/ui/traits/issue-38604.stderr +++ b/tests/ui/traits/issue-38604.stderr @@ -1,32 +1,34 @@ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/issue-38604.rs:14:13 | LL | let _f: Box<dyn Foo> = - | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-38604.rs:2:22 | LL | trait Foo where u32: Q<Self> { | --- ^^^^^^^ ...because it uses `Self` as a type parameter | | - | this trait cannot be made into an object... - = help: only type `()` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `()` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/issue-38604.rs:15:9 | LL | Box::new(()); - | ^^^^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-38604.rs:2:22 | LL | trait Foo where u32: Q<Self> { | --- ^^^^^^^ ...because it uses `Self` as a type parameter | | - | this trait cannot be made into an object... - = help: only type `()` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `()` implements `Foo`; consider using it directly instead. = note: required for the cast from `Box<()>` to `Box<dyn Foo>` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/issue-72410.rs b/tests/ui/traits/issue-72410.rs index c95f1dfdca5..df3738e2730 100644 --- a/tests/ui/traits/issue-72410.rs +++ b/tests/ui/traits/issue-72410.rs @@ -12,7 +12,7 @@ pub trait Foo { pub trait Bar { fn map() where for<'a> &'a mut [dyn Bar]: ; - //~^ ERROR: the trait `Bar` cannot be made into an object + //~^ ERROR: the trait `Bar` is not dyn compatible } fn main() {} diff --git a/tests/ui/traits/issue-72410.stderr b/tests/ui/traits/issue-72410.stderr index 6d56a198fc1..002345bff84 100644 --- a/tests/ui/traits/issue-72410.stderr +++ b/tests/ui/traits/issue-72410.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `Bar` cannot be made into an object +error[E0038]: the trait `Bar` is not dyn compatible --> $DIR/issue-72410.rs:14:19 | LL | where for<'a> &'a mut [dyn Bar]: ; - | ^^^^^^^^^^^^^^^^^ `Bar` cannot be made into an object + | ^^^^^^^^^^^^^^^^^ `Bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-72410.rs:13:8 | LL | pub trait Bar { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn map() | ^^^ ...because associated function `map` has no `self` parameter help: consider turning `map` into a method by giving it a `&self` argument diff --git a/tests/ui/traits/item-privacy.rs b/tests/ui/traits/item-privacy.rs index a3e1a22e7a8..f5c741ccaa5 100644 --- a/tests/ui/traits/item-privacy.rs +++ b/tests/ui/traits/item-privacy.rs @@ -99,8 +99,8 @@ fn check_assoc_const() { S::C; // OK // A, B, C are resolved as inherent items, their traits don't need to be in scope <dyn C>::A; //~ ERROR associated constant `A` is private - //~^ ERROR the trait `assoc_const::C` cannot be made into an object - <dyn C>::B; // ERROR the trait `assoc_const::C` cannot be made into an object + //~^ ERROR the trait `assoc_const::C` is not dyn compatible + <dyn C>::B; // ERROR the trait `assoc_const::C` is not dyn compatible C::C; // OK } diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index c20d2f723c5..c97158a5b76 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -136,13 +136,14 @@ LL | const A: u8 = 0; LL | <dyn C>::A; | ^ private associated constant -error[E0038]: the trait `assoc_const::C` cannot be made into an object +error[E0038]: the trait `assoc_const::C` is not dyn compatible --> $DIR/item-privacy.rs:101:6 | LL | <dyn C>::A; - | ^^^^^ `assoc_const::C` cannot be made into an object + | ^^^^^ `assoc_const::C` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/item-privacy.rs:25:15 | LL | const A: u8 = 0; @@ -152,13 +153,13 @@ LL | const B: u8 = 0; | ^ ...because it contains this associated `const` ... LL | pub trait C: A + B { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | const C: u8 = 0; | ^ ...because it contains this associated `const` = help: consider moving `C` to another trait = help: consider moving `A` to another trait = help: consider moving `B` to another trait - = help: only type `S` implements the trait, consider using it directly instead + = help: only type `S` implements `assoc_const::C`; consider using it directly instead. error[E0223]: ambiguous associated type --> $DIR/item-privacy.rs:115:12 diff --git a/tests/ui/traits/missing-for-type-in-impl.e2015.stderr b/tests/ui/traits/missing-for-type-in-impl.e2015.stderr index 541b49b024f..682d18842b8 100644 --- a/tests/ui/traits/missing-for-type-in-impl.e2015.stderr +++ b/tests/ui/traits/missing-for-type-in-impl.e2015.stderr @@ -34,17 +34,18 @@ help: you might have intended to implement this trait for a given type LL | impl Foo<i64> for /* Type */ { | ++++++++++++++ -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/missing-for-type-in-impl.rs:8:6 | LL | impl Foo<i64> { - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/missing-for-type-in-impl.rs:4:8 | LL | trait Foo<T> { - | --- this trait cannot be made into an object... + | --- this trait is not dyn compatible... LL | fn id(me: T) -> T; | ^^ ...because associated function `id` has no `self` parameter help: consider turning `id` into a method by giving it a `&self` argument diff --git a/tests/ui/traits/missing-for-type-in-impl.rs b/tests/ui/traits/missing-for-type-in-impl.rs index e5dd3651609..e8163954274 100644 --- a/tests/ui/traits/missing-for-type-in-impl.rs +++ b/tests/ui/traits/missing-for-type-in-impl.rs @@ -11,7 +11,7 @@ impl Foo<i64> { //[e2015]~| WARNING trait objects without an explicit `dyn` are deprecated //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //[e2015]~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -//[e2015]~| ERROR the trait `Foo` cannot be made into an object +//[e2015]~| ERROR the trait `Foo` is not dyn compatible fn id(me: i64) -> i64 {me} } diff --git a/tests/ui/traits/next-solver/coherence/issue-102048.next.stderr b/tests/ui/traits/next-solver/coherence/issue-102048.next.stderr deleted file mode 100644 index 39fde307f23..00000000000 --- a/tests/ui/traits/next-solver/coherence/issue-102048.next.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0119]: conflicting implementations of trait `Trait<for<'a> fn(<_ as WithAssoc1<'a>>::Assoc, <_ as WithAssoc2<'a>>::Assoc)>` for type `(_, _)` - --> $DIR/issue-102048.rs:44:1 - | -LL | / impl<T, U> Trait<for<'a> fn(<T as WithAssoc1<'a>>::Assoc, <U as WithAssoc2<'a>>::Assoc)> for (T, U) -LL | | where -LL | | T: for<'a> WithAssoc1<'a> + for<'a> WithAssoc2<'a, Assoc = i32>, -LL | | U: for<'a> WithAssoc2<'a>, - | |______________________________- first implementation here -... -LL | / impl<T, U> Trait<for<'a> fn(<U as WithAssoc1<'a>>::Assoc, u32)> for (T, U) where -LL | | U: for<'a> WithAssoc1<'a> - | |_____________________________^ conflicting implementation for `(_, _)` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.rs b/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.rs new file mode 100644 index 00000000000..5cea9bb74d7 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.rs @@ -0,0 +1,28 @@ +//@ compile-flags: -Znext-solver + +// When encountering a fulfillment error from an `alias-relate` goal failing, we +// would previously manually construct a `normalizes-to` goal involving the alias +// and an infer var. This would then ICE as normalization would return a nested +// goal (the `T: Sized` from the `Trait` impl for `Foo<T>` below) from the root goal +// which is not supported. + +struct Foo<T>(T); + +trait Trait { + type Assoc; +} + +// `T: Sized` being explicit is not required, but the bound being present *is*. +impl<T: Sized> Trait for Foo<T> { + type Assoc = u64; +} + +fn bar<T: Trait<Assoc = u32>>(_: T) {} + +fn main() { + let foo = Foo(Default::default()); + bar(foo); + //~^ ERROR: type mismatch resolving `<Foo<_> as Trait>::Assoc == u32` + // Here diagnostics would manually construct a `<Foo<?y> as Trait>::Assoc normalizes-to ?x` goal + // which would return a nested goal of `?y: Sized` from the impl. +} diff --git a/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.stderr b/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.stderr new file mode 100644 index 00000000000..ff3cbdb2c78 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `<Foo<_> as Trait>::Assoc == u32` + --> $DIR/alias_relate_error_uses_structurally_normalize.rs:24:9 + | +LL | bar(foo); + | --- ^^^ expected `u32`, found `u64` + | | + | required by a bound introduced by this call + | +note: required by a bound in `bar` + --> $DIR/alias_relate_error_uses_structurally_normalize.rs:20:17 + | +LL | fn bar<T: Trait<Assoc = u32>>(_: T) {} + | ^^^^^^^^^^^ required by this bound in `bar` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.current.stderr b/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.current.stderr new file mode 100644 index 00000000000..a863886181c --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.current.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `Foo: Trait` is not satisfied + --> $DIR/dont-pick-fnptr-bound-as-leaf.rs:24:20 + | +LL | requires_trait(Foo); + | -------------- ^^^ the trait `Trait` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | +note: required by a bound in `requires_trait` + --> $DIR/dont-pick-fnptr-bound-as-leaf.rs:19:22 + | +LL | fn requires_trait<T: Trait>(_: T) {} + | ^^^^^ required by this bound in `requires_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.next.stderr b/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.next.stderr new file mode 100644 index 00000000000..a863886181c --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.next.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `Foo: Trait` is not satisfied + --> $DIR/dont-pick-fnptr-bound-as-leaf.rs:24:20 + | +LL | requires_trait(Foo); + | -------------- ^^^ the trait `Trait` is not implemented for `Foo` + | | + | required by a bound introduced by this call + | +note: required by a bound in `requires_trait` + --> $DIR/dont-pick-fnptr-bound-as-leaf.rs:19:22 + | +LL | fn requires_trait<T: Trait>(_: T) {} + | ^^^^^ required by this bound in `requires_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.rs b/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.rs new file mode 100644 index 00000000000..995f2c9fbee --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/dont-pick-fnptr-bound-as-leaf.rs @@ -0,0 +1,28 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +// When emitting an error for `Foo: Trait` not holding we attempt to find a nested goal +// to give as the reason why the bound does not hold. This test checks that we do not +// try to tell the user that `Foo: FnPtr` is unimplemented as that would be confusing. + +#![feature(fn_ptr_trait)] + +use std::marker::FnPtr; + +trait Trait {} + +impl<T: FnPtr> Trait for T {} + +struct Foo; + +fn requires_trait<T: Trait>(_: T) {} +//~^ NOTE: required by a bound in `requires_trait` +//~| NOTE: required by this bound in `requires_trait` + +fn main() { + requires_trait(Foo); + //~^ ERROR: the trait bound `Foo: Trait` is not satisfied + //~| NOTE: the trait `Trait` is not implemented for `Foo` + //~| NOTE: required by a bound introduced by this call +} diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs new file mode 100644 index 00000000000..d05def2cb75 --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Znext-solver + +trait Wf { + type Assoc; +} + +struct S { + f: &'static <() as Wf>::Assoc, + //~^ ERROR the trait bound `(): Wf` is not satisfied +} + +fn main() { + let x: S = todo!(); + let y: &() = x.f; + //~^ ERROR mismatched types + //~| ERROR the trait bound `(): Wf` is not satisfied +} diff --git a/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr new file mode 100644 index 00000000000..32a7766a638 --- /dev/null +++ b/tests/ui/traits/next-solver/non-wf-in-coerce-pointers.stderr @@ -0,0 +1,39 @@ +error[E0277]: the trait bound `(): Wf` is not satisfied + --> $DIR/non-wf-in-coerce-pointers.rs:8:17 + | +LL | f: &'static <() as Wf>::Assoc, + | ^^^^^^^^^^^^^^^^^ the trait `Wf` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/non-wf-in-coerce-pointers.rs:3:1 + | +LL | trait Wf { + | ^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/non-wf-in-coerce-pointers.rs:14:18 + | +LL | let y: &() = x.f; + | --- ^^^ types differ + | | + | expected due to this + | + = note: expected reference `&()` + found reference `&'static <() as Wf>::Assoc` + +error[E0277]: the trait bound `(): Wf` is not satisfied + --> $DIR/non-wf-in-coerce-pointers.rs:14:18 + | +LL | let y: &() = x.f; + | ^^^ the trait `Wf` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/non-wf-in-coerce-pointers.rs:3:1 + | +LL | trait Wf { + | ^^^^^^^^ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs b/tests/ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs new file mode 100644 index 00000000000..dc96652f82f --- /dev/null +++ b/tests/ui/traits/next-solver/normalization-shadowing/global-trait-with-project.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// `(): Trait` is a global where-bound with a projection bound. +// This previously resulted in ambiguity as we considered both +// the impl and the where-bound while normalizing. + +trait Trait { + type Assoc; +} +impl Trait for () { + type Assoc = &'static (); +} + +fn foo<'a>(x: <() as Trait>::Assoc) +where + (): Trait<Assoc = &'a ()>, +{ +} + +fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs index a635edb4485..28785ae3dea 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs +++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.rs @@ -17,8 +17,8 @@ impl<T: ?Sized> Bar<T> for () {} fn main() { let x: &dyn Foo = &(); - //~^ ERROR the trait `Foo` cannot be made into an object - //~| ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible + //~| ERROR the trait `Foo` is not dyn compatible needs_bar(x); - //~^ ERROR the trait `Foo` cannot be made into an object + //~^ ERROR the trait `Foo` is not dyn compatible } diff --git a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr index dd2dca74f90..8448890c084 100644 --- a/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr +++ b/tests/ui/traits/non_lifetime_binders/supertrait-dyn-compatibility.stderr @@ -7,51 +7,54 @@ LL | #![feature(non_lifetime_binders)] = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information = note: `#[warn(incomplete_features)]` on by default -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/supertrait-dyn-compatibility.rs:19:23 | LL | let x: &dyn Foo = &(); - | ^^^ `Foo` cannot be made into an object + | ^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for<T> Bar<T> {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables | | - | this trait cannot be made into an object... - = help: only type `()` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `()` implements `Foo`; consider using it directly instead. = note: required for the cast from `&()` to `&dyn Foo` -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/supertrait-dyn-compatibility.rs:19:12 | LL | let x: &dyn Foo = &(); - | ^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for<T> Bar<T> {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables | | - | this trait cannot be made into an object... - = help: only type `()` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `()` implements `Foo`; consider using it directly instead. -error[E0038]: the trait `Foo` cannot be made into an object +error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/supertrait-dyn-compatibility.rs:22:5 | LL | needs_bar(x); - | ^^^^^^^^^ `Foo` cannot be made into an object + | ^^^^^^^^^ `Foo` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/supertrait-dyn-compatibility.rs:4:12 | LL | trait Foo: for<T> Bar<T> {} | --- ^^^^^^^^^^^^^ ...because where clause cannot reference non-lifetime `for<...>` variables | | - | this trait cannot be made into an object... - = help: only type `()` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `()` implements `Foo`; consider using it directly instead. error: aborting due to 3 previous errors; 1 warning emitted diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs index 4aadd45c49c..6fcd67b4950 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs @@ -8,9 +8,9 @@ trait Try { fn w<'a, T: 'a, F: Fn(&'a T)>() { let b: &dyn FromResidual = &(); - //~^ ERROR: the trait `FromResidual` cannot be made into an object - //~| ERROR: the trait `FromResidual` cannot be made into an object - //~| ERROR: the trait `FromResidual` cannot be made into an object + //~^ ERROR: the trait `FromResidual` is not dyn compatible + //~| ERROR: the trait `FromResidual` is not dyn compatible + //~| ERROR the type parameter `R` must be explicitly specified } fn main() {} diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index c67a8c05379..ae3762704c6 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -1,22 +1,30 @@ -error[E0038]: the trait `FromResidual` cannot be made into an object +error[E0393]: the type parameter `R` must be explicitly specified --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17 | +LL | trait FromResidual<R = <Self as Try>::Residual> { + | ----------------------------------------------- type parameter `R` must be specified for this +... LL | let b: &dyn FromResidual = &(); | ^^^^^^^^^^^^ | - = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause + = note: because the parameter default references `Self`, the parameter must be specified on the object type +help: set the type parameter to the desired type + | +LL | let b: &dyn FromResidual<R> = &(); + | +++ -error[E0038]: the trait `FromResidual` cannot be made into an object +error[E0038]: the trait `FromResidual` is not dyn compatible --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32 | LL | let b: &dyn FromResidual = &(); - | ^^^ `FromResidual` cannot be made into an object + | ^^^ `FromResidual` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8 | LL | trait FromResidual<R = <Self as Try>::Residual> { - | ------------ this trait cannot be made into an object... + | ------------ this trait is not dyn compatible... LL | fn from_residual(residual: R) -> Self; | ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter = note: required for the cast from `&()` to `&dyn FromResidual<{type error}>` @@ -29,17 +37,18 @@ help: alternatively, consider constraining `from_residual` so it does not apply LL | fn from_residual(residual: R) -> Self where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `FromResidual` cannot be made into an object +error[E0038]: the trait `FromResidual` is not dyn compatible --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:12 | LL | let b: &dyn FromResidual = &(); - | ^^^^^^^^^^^^^^^^^ `FromResidual` cannot be made into an object + | ^^^^^^^^^^^^^^^^^ `FromResidual` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:2:8 | LL | trait FromResidual<R = <Self as Try>::Residual> { - | ------------ this trait cannot be made into an object... + | ------------ this trait is not dyn compatible... LL | fn from_residual(residual: R) -> Self; | ^^^^^^^^^^^^^ ...because associated function `from_residual` has no `self` parameter help: consider turning `from_residual` into a method by giving it a `&self` argument @@ -53,4 +62,5 @@ LL | fn from_residual(residual: R) -> Self where Self: Sized; error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0038, E0393. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/object/macro-matcher.rs b/tests/ui/traits/object/macro-matcher.rs index 91097874997..675d9f51532 100644 --- a/tests/ui/traits/object/macro-matcher.rs +++ b/tests/ui/traits/object/macro-matcher.rs @@ -6,7 +6,7 @@ macro_rules! m { fn main() { m!(dyn Copy + Send + 'static); - //~^ ERROR the trait `Copy` cannot be made into an object + //~^ ERROR the trait `Copy` is not dyn compatible m!(dyn 'static + Send); m!(dyn 'static +); //~ ERROR at least one trait is required for an object type } diff --git a/tests/ui/traits/object/macro-matcher.stderr b/tests/ui/traits/object/macro-matcher.stderr index 7924c86e294..ab0fc213c9f 100644 --- a/tests/ui/traits/object/macro-matcher.stderr +++ b/tests/ui/traits/object/macro-matcher.stderr @@ -4,14 +4,15 @@ error[E0224]: at least one trait is required for an object type LL | m!(dyn 'static +); | ^^^^^^^^^^^^^ -error[E0038]: the trait `Copy` cannot be made into an object +error[E0038]: the trait `Copy` is not dyn compatible --> $DIR/macro-matcher.rs:8:8 | LL | m!(dyn Copy + Send + 'static); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^ `Copy` is not dyn compatible | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> error: aborting due to 2 previous errors diff --git a/tests/ui/traits/object/safety.stderr b/tests/ui/traits/object/safety.stderr index a2cb656b08d..eab59f39c28 100644 --- a/tests/ui/traits/object/safety.stderr +++ b/tests/ui/traits/object/safety.stderr @@ -1,17 +1,18 @@ -error[E0038]: the trait `Tr` cannot be made into an object +error[E0038]: the trait `Tr` is not dyn compatible --> $DIR/safety.rs:15:22 | LL | let _: &dyn Tr = &St; - | ^^^ `Tr` cannot be made into an object + | ^^^ `Tr` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/safety.rs:4:8 | LL | trait Tr { - | -- this trait cannot be made into an object... + | -- this trait is not dyn compatible... LL | fn foo(); | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `St` implements the trait, consider using it directly instead + = help: only type `St` implements `Tr`; consider using it directly instead. = note: required for the cast from `&St` to `&dyn Tr` help: consider turning `foo` into a method by giving it a `&self` argument | @@ -22,20 +23,21 @@ help: alternatively, consider constraining `foo` so it does not apply to trait o LL | fn foo() where Self: Sized; | +++++++++++++++++ -error[E0038]: the trait `Tr` cannot be made into an object +error[E0038]: the trait `Tr` is not dyn compatible --> $DIR/safety.rs:15:12 | LL | let _: &dyn Tr = &St; - | ^^^^^^^ `Tr` cannot be made into an object + | ^^^^^^^ `Tr` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/safety.rs:4:8 | LL | trait Tr { - | -- this trait cannot be made into an object... + | -- this trait is not dyn compatible... LL | fn foo(); | ^^^ ...because associated function `foo` has no `self` parameter - = help: only type `St` implements the trait, consider using it directly instead + = help: only type `St` implements `Tr`; consider using it directly instead. help: consider turning `foo` into a method by giving it a `&self` argument | LL | fn foo(&self); diff --git a/tests/ui/traits/test-2.stderr b/tests/ui/traits/test-2.stderr index 3da95b47844..8915e490b4d 100644 --- a/tests/ui/traits/test-2.stderr +++ b/tests/ui/traits/test-2.stderr @@ -26,65 +26,74 @@ note: method defined here, with 1 generic parameter: `X` LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } | ^^^^ - -error[E0038]: the trait `bar` cannot be made into an object +error[E0038]: the trait `bar` is not dyn compatible --> $DIR/test-2.rs:13:22 | LL | (Box::new(10) as Box<dyn bar>).dup(); - | ^^^^^^^^^^^^ `bar` cannot be made into an object + | ^^^^^^^^^^^^ `bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/test-2.rs:4:30 | LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters | | | | | ...because method `dup` references the `Self` type in its return type - | this trait cannot be made into an object... + | this trait is not dyn compatible... = help: consider moving `dup` to another trait = help: consider moving `blah` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead: + = help: the following types implement `bar`: i32 u32 + consider defining an enum where each variant holds one of these types, + implementing `bar` for this new enum and using it instead -error[E0038]: the trait `bar` cannot be made into an object +error[E0038]: the trait `bar` is not dyn compatible --> $DIR/test-2.rs:13:5 | LL | (Box::new(10) as Box<dyn bar>).dup(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` cannot be made into an object + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/test-2.rs:4:30 | LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters | | | | | ...because method `dup` references the `Self` type in its return type - | this trait cannot be made into an object... + | this trait is not dyn compatible... = help: consider moving `dup` to another trait = help: consider moving `blah` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead: + = help: the following types implement `bar`: i32 u32 + consider defining an enum where each variant holds one of these types, + implementing `bar` for this new enum and using it instead -error[E0038]: the trait `bar` cannot be made into an object +error[E0038]: the trait `bar` is not dyn compatible --> $DIR/test-2.rs:13:6 | LL | (Box::new(10) as Box<dyn bar>).dup(); - | ^^^^^^^^^^^^ `bar` cannot be made into an object + | ^^^^^^^^^^^^ `bar` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/test-2.rs:4:30 | LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } | --- ^^^^ ^^^^ ...because method `blah` has generic type parameters | | | | | ...because method `dup` references the `Self` type in its return type - | this trait cannot be made into an object... + | this trait is not dyn compatible... = help: consider moving `dup` to another trait = help: consider moving `blah` to another trait - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `bar` for this new enum and using it instead: + = help: the following types implement `bar`: i32 u32 + consider defining an enum where each variant holds one of these types, + implementing `bar` for this new enum and using it instead = note: required for the cast from `Box<{integer}>` to `Box<dyn bar>` error: aborting due to 5 previous errors diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr deleted file mode 100644 index e6cb6a75399..00000000000 --- a/tests/ui/traits/trait-upcasting/type-checking-test-3.polonius.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:11:13 - | -LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { - | -- lifetime `'a` defined here -LL | let _ = x as &dyn Bar<'a>; // Error - | ^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - -error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:16:13 - | -LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) { - | -- lifetime `'a` defined here -LL | let _ = x as &dyn Bar<'static>; // Error - | ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr deleted file mode 100644 index 8d506e5807e..00000000000 --- a/tests/ui/traits/trait-upcasting/type-checking-test-4.polonius.stderr +++ /dev/null @@ -1,52 +0,0 @@ -error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:15:13 - | -LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { - | -- lifetime `'a` defined here -LL | let _ = x as &dyn Bar<'static, 'a>; // Error - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - -error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:20:13 - | -LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) { - | -- lifetime `'a` defined here -LL | let _ = x as &dyn Bar<'a, 'static>; // Error - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` - -error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:26:5 - | -LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { - | -- lifetime `'a` defined here -LL | let y = x as &dyn Bar<'_, '_>; -LL | y.get_b() // ERROR - | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - -error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:31:5 - | -LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { - | -- lifetime `'a` defined here -LL | <_ as Bar>::get_b(x) // ERROR - | ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - -error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:36:5 - | -LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { - | -- lifetime `'a` defined here -LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - -error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:44:5 - | -LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> { - | -- lifetime `'a` defined here -... -LL | z.get_b() // ERROR - | ^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - -error: aborting due to 6 previous errors - diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.stderr b/tests/ui/traits/unspecified-self-in-trait-ref.stderr index 22dceadc10d..6f5ae786de6 100644 --- a/tests/ui/traits/unspecified-self-in-trait-ref.stderr +++ b/tests/ui/traits/unspecified-self-in-trait-ref.stderr @@ -97,7 +97,7 @@ LL | pub trait Bar<X=usize, A=Self> { LL | let e = Bar::<usize>::lol(); | ^^^^^^^^^^^^ missing reference to `A` | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type error: aborting due to 5 previous errors; 5 warnings emitted diff --git a/tests/ui/treat-err-as-bug/panic-causes-oom-112708.stderr b/tests/ui/treat-err-as-bug/panic-causes-oom-112708.stderr deleted file mode 100644 index 2d49071ac49..00000000000 --- a/tests/ui/treat-err-as-bug/panic-causes-oom-112708.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error: denote infinite loops with `loop { ... }` - --> $DIR/panic-causes-oom-112708.rs:13:5 - | -LL | while true {} - | ^^^^^^^^^^ help: use `loop` - | -note: the lint level is defined here - --> $DIR/panic-causes-oom-112708.rs:12:12 - | -LL | #[deny(while_true)] - | ^^^^^^^^^^ - - -query stack during panic: -#0 [early_lint_checks] perform lints prior to macro expansion -#1 [hir_crate] getting the crate HIR -end of query stack - -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [early_lint_checks] perform lints prior to macro expansion -#1 [hir_crate] getting the crate HIR -end of query stack - -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [early_lint_checks] perform lints prior to macro expansion -#1 [hir_crate] getting the crate HIR -end of query stack -thread caused non-unwinding panic. aborting. diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr index 85a943c26e2..16bbc996d90 100644 --- a/tests/ui/type-alias-impl-trait/issue-77179.stderr +++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr @@ -28,10 +28,7 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/issue-77179.rs:18:25 | LL | fn bar() -> Pointer<_>; - | ^ - | | - | not allowed in type signatures - | help: use type parameters instead: `T` + | ^ not allowed in type signatures error: aborting due to 3 previous errors diff --git a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr b/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr deleted file mode 100644 index 79b726f83dd..00000000000 --- a/tests/ui/type-alias-impl-trait/wf-nested.fail.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:64:38 - | -LL | fn define<T>() -> OuterOpaque<T> {} - | ^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound - | -LL | fn define<T: 'static>() -> OuterOpaque<T> {} - | +++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr deleted file mode 100644 index b61b69d8e40..00000000000 --- a/tests/ui/type-alias-impl-trait/wf-nested.pass.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:34:38 - | -LL | fn define<T>() -> OuterOpaque<T> {} - | ^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound - | -LL | fn define<T: 'static>() -> OuterOpaque<T> {} - | +++++++++ - -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:37:69 - | -LL | fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {} - | ^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound - | -LL | fn define_rpit<T: 'static>() -> impl Trait<&'static T, Out = impl Sized> {} - | +++++++++ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr b/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr deleted file mode 100644 index dbd3a1394f8..00000000000 --- a/tests/ui/type-alias-impl-trait/wf-nested.pass_sound.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:46:38 - | -LL | fn define<T>() -> OuterOpaque<T> {} - | ^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound - | -LL | fn define<T: 'static>() -> OuterOpaque<T> {} - | +++++++++ - -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:51:17 - | -LL | let _ = outer.get(); - | ^^^^^^^^^^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds - | -help: consider adding an explicit lifetime bound - | -LL | fn test<T: 'static>() { - | +++++++++ - -error[E0310]: the parameter type `T` may not live long enough - --> $DIR/wf-nested.rs:51:17 - | -LL | let _ = outer.get(); - | ^^^^^^^^^^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider adding an explicit lifetime bound - | -LL | fn test<T: 'static>() { - | +++++++++ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0310`. diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs index 55f45ade388..c5f8b2764ec 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs @@ -4,7 +4,7 @@ type Pat<const START: u32, const END: u32> = std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); //~^ ERROR type and const arguments are not allowed on const parameter `START` -//~| ERROR type arguments are not allowed on const parameter `END` +//~| ERROR generic arguments are not allowed on const parameter `END` //~| ERROR associated item constraints are not allowed here fn main() {} diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr index 7f4e6e314f5..f31809bf397 100644 --- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr +++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr @@ -12,11 +12,11 @@ note: const parameter `START` defined here LL | type Pat<const START: u32, const END: u32> = | ^^^^^ -error[E0109]: type arguments are not allowed on const parameter `END` +error[E0109]: generic arguments are not allowed on const parameter `END` --> $DIR/bad_const_generics_args_on_const_param.rs:5:64 | LL | std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>); - | --- ^ type argument not allowed + | --- ^ generic argument not allowed | | | not allowed on const parameter `END` | diff --git a/tests/ui/type/pattern_types/derives.noimpl.stderr b/tests/ui/type/pattern_types/derives.noimpl.stderr deleted file mode 100644 index 9450e575344..00000000000 --- a/tests/ui/type/pattern_types/derives.noimpl.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0369]: binary operation `==` cannot be applied to type `(i32) is 0..=999999999` - --> $DIR/derives.rs:14:20 - | -LL | #[derive(Clone, Copy, PartialEq)] - | --------- in this derive macro expansion -LL | #[repr(transparent)] -LL | struct Nanoseconds(NanoI32); - | ^^^^^^^ - | - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0369`. diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr index 2d5bcf1fbc4..71717c6945e 100644 --- a/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr +++ b/tests/ui/type/type-parameter-defaults-referencing-Self-ppaux.stderr @@ -10,21 +10,20 @@ help: consider using a box or reference as appropriate LL | let y = x as dyn MyAdd<i32>; | ^ -error[E0038]: the trait `MyAdd` cannot be made into an object +error[E0038]: the trait `MyAdd` is not dyn compatible --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 | LL | let y = x as dyn MyAdd<i32>; - | ^^^^^^^^^^^^^^ `MyAdd` cannot be made into an object + | ^^^^^^^^^^^^^^ `MyAdd` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:6:55 | LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; } - | ----- ^^^^ ...because method `add` references the `Self` type in its return type - | | - | this trait cannot be made into an object... + | ----- this trait is not dyn compatible... ^^^^ ...because method `add` references the `Self` type in its return type = help: consider moving `add` to another trait - = help: only type `i32` implements the trait, consider using it directly instead + = help: only type `i32` implements `MyAdd`; consider using it directly instead. error: aborting due to 2 previous errors diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr index c81405f03f8..23f10c9262c 100644 --- a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr +++ b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr @@ -7,7 +7,7 @@ LL | trait Foo<T=Self> { LL | fn foo(x: &dyn Foo) { } | ^^^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn foo(x: &dyn Foo<T>) { } diff --git a/tests/ui/type_length_limit.polonius.stderr b/tests/ui/type_length_limit.polonius.stderr deleted file mode 100644 index bc09f159183..00000000000 --- a/tests/ui/type_length_limit.polonius.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: reached the type-length limit while instantiating `std::mem::drop::<Option<((((...,....., ...), ..., ...), ..., ...)>>` - --> $SRC_DIR/core/src/mem/mod.rs:LL:COL - | -LL | pub fn drop<T>(_x: T) {} - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: the full type name has been written to '$TEST_BUILD_DIR/type_length_limit.polonius/type_length_limit.long-type.txt' - = help: consider adding a `#![type_length_limit="8"]` attribute to your crate - -error: aborting due to 1 previous error - diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.current.stderr index dd2ce092368..dc3d998c399 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.stderr +++ b/tests/ui/typeck/bad-index-due-to-nested.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `K: Hash` is not satisfied - --> $DIR/bad-index-due-to-nested.rs:20:5 + --> $DIR/bad-index-due-to-nested.rs:24:5 | LL | map[k] | ^^^ the trait `Hash` is not implemented for `K` | note: required for `HashMap<K, V>` to implement `Index<&K>` - --> $DIR/bad-index-due-to-nested.rs:7:12 + --> $DIR/bad-index-due-to-nested.rs:11:12 | LL | impl<K, V> Index<&K> for HashMap<K, V> | ^^^^^^^^^ ^^^^^^^^^^^^^ @@ -18,13 +18,13 @@ LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V | +++++++++++++++++ error[E0277]: the trait bound `V: Copy` is not satisfied - --> $DIR/bad-index-due-to-nested.rs:20:5 + --> $DIR/bad-index-due-to-nested.rs:24:5 | LL | map[k] | ^^^ the trait `Copy` is not implemented for `V` | note: required for `HashMap<K, V>` to implement `Index<&K>` - --> $DIR/bad-index-due-to-nested.rs:7:12 + --> $DIR/bad-index-due-to-nested.rs:11:12 | LL | impl<K, V> Index<&K> for HashMap<K, V> | ^^^^^^^^^ ^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a | +++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/bad-index-due-to-nested.rs:20:9 + --> $DIR/bad-index-due-to-nested.rs:24:9 | LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { | - found this type parameter @@ -52,7 +52,7 @@ LL | map[&k] | + error[E0308]: mismatched types - --> $DIR/bad-index-due-to-nested.rs:20:5 + --> $DIR/bad-index-due-to-nested.rs:24:5 | LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { | - found this type parameter ----- expected `&'a V` because of return type diff --git a/tests/ui/typeck/bad-index-due-to-nested.next.stderr b/tests/ui/typeck/bad-index-due-to-nested.next.stderr new file mode 100644 index 00000000000..a0b275b7852 --- /dev/null +++ b/tests/ui/typeck/bad-index-due-to-nested.next.stderr @@ -0,0 +1,76 @@ +error[E0277]: the trait bound `K: Hash` is not satisfied + --> $DIR/bad-index-due-to-nested.rs:24:5 + | +LL | map[k] + | ^^^ the trait `Hash` is not implemented for `K` + | +note: required for `HashMap<K, V>` to implement `Index<&K>` + --> $DIR/bad-index-due-to-nested.rs:11:12 + | +LL | impl<K, V> Index<&K> for HashMap<K, V> + | ^^^^^^^^^ ^^^^^^^^^^^^^ +LL | where +LL | K: Hash, + | ---- unsatisfied trait bound introduced here +help: consider restricting type parameter `K` with trait `Hash` + | +LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { + | +++++++++++++++++ + +error[E0277]: the trait bound `V: Copy` is not satisfied + --> $DIR/bad-index-due-to-nested.rs:24:5 + | +LL | map[k] + | ^^^ the trait `Copy` is not implemented for `V` + | +note: required for `HashMap<K, V>` to implement `Index<&K>` + --> $DIR/bad-index-due-to-nested.rs:11:12 + | +LL | impl<K, V> Index<&K> for HashMap<K, V> + | ^^^^^^^^^ ^^^^^^^^^^^^^ +... +LL | V: Copy, + | ---- unsatisfied trait bound introduced here +help: consider restricting type parameter `V` with trait `Copy` + | +LL | fn index<'a, K, V: std::marker::Copy>(map: &'a HashMap<K, V>, k: K) -> &'a V { + | +++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/bad-index-due-to-nested.rs:24:9 + | +LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { + | - found this type parameter +LL | map[k] + | ^ expected `&K`, found type parameter `K` + | + = note: expected reference `&_` + found type parameter `_` +help: consider borrowing here + | +LL | map[&k] + | + + +error[E0277]: the trait bound `K: Hash` is not satisfied + --> $DIR/bad-index-due-to-nested.rs:24:5 + | +LL | map[k] + | ^^^^^^ the trait `Hash` is not implemented for `K` + | +note: required for `HashMap<K, V>` to implement `Index<&K>` + --> $DIR/bad-index-due-to-nested.rs:11:12 + | +LL | impl<K, V> Index<&K> for HashMap<K, V> + | ^^^^^^^^^ ^^^^^^^^^^^^^ +LL | where +LL | K: Hash, + | ---- unsatisfied trait bound introduced here +help: consider restricting type parameter `K` with trait `Hash` + | +LL | fn index<'a, K: std::hash::Hash, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { + | +++++++++++++++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/bad-index-due-to-nested.rs b/tests/ui/typeck/bad-index-due-to-nested.rs index 2564b530004..e7f385865af 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.rs +++ b/tests/ui/typeck/bad-index-due-to-nested.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + use std::hash::Hash; use std::marker::PhantomData; use std::ops::Index; @@ -21,7 +25,8 @@ fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { //~^ ERROR the trait bound `K: Hash` is not satisfied //~| ERROR the trait bound `V: Copy` is not satisfied //~| ERROR mismatched types - //~| ERROR mismatched types + //[current]~| ERROR mismatched types + //[next]~^^^^^ ERROR the trait bound `K: Hash` is not satisfied } fn main() {} diff --git a/tests/ui/typeck/ice-self-mismatch-const-generics.stderr b/tests/ui/typeck/ice-self-mismatch-const-generics.stderr index c502ea4565f..068cf3ee903 100644 --- a/tests/ui/typeck/ice-self-mismatch-const-generics.stderr +++ b/tests/ui/typeck/ice-self-mismatch-const-generics.stderr @@ -8,8 +8,8 @@ LL | pub fn new(thing: T) -> GenericStruct<1, T> { LL | Self { thing } | ^^^^^^^^^^^^^^ expected `1`, found `0` | - = note: expected struct `GenericStruct<_, 1>` - found struct `GenericStruct<_, 0>` + = note: expected struct `GenericStruct<1, _>` + found struct `GenericStruct<0, _>` help: use the type name directly | LL | GenericStruct::<1, T> { thing } @@ -25,8 +25,8 @@ LL | pub fn new(thing: T) -> GenericStruct2<1, T> { LL | Self { 0: thing } | ^^^^^^^^^^^^^^^^^ expected `1`, found `0` | - = note: expected struct `GenericStruct2<_, 1>` - found struct `GenericStruct2<_, 0>` + = note: expected struct `GenericStruct2<1, _>` + found struct `GenericStruct2<0, _>` help: use the type name directly | LL | GenericStruct2::<1, T> { 0: thing } diff --git a/tests/ui/typeck/issue-120856.rs b/tests/ui/typeck/issue-120856.rs index e435a0f9d8e..51dd63a6f89 100644 --- a/tests/ui/typeck/issue-120856.rs +++ b/tests/ui/typeck/issue-120856.rs @@ -1,5 +1,5 @@ pub type Archived<T> = <m::Alias as n::Trait>::Archived; -//~^ ERROR failed to resolve: use of undeclared crate or module `m` -//~| ERROR failed to resolve: use of undeclared crate or module `n` +//~^ ERROR failed to resolve: use of unresolved module or unlinked crate `m` +//~| ERROR failed to resolve: use of unresolved module or unlinked crate `n` fn main() {} diff --git a/tests/ui/typeck/issue-120856.stderr b/tests/ui/typeck/issue-120856.stderr index 1fc8b200473..e366744409f 100644 --- a/tests/ui/typeck/issue-120856.stderr +++ b/tests/ui/typeck/issue-120856.stderr @@ -1,20 +1,24 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `n` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `n` --> $DIR/issue-120856.rs:1:37 | LL | pub type Archived<T> = <m::Alias as n::Trait>::Archived; | ^ | | - | use of undeclared crate or module `n` + | use of unresolved module or unlinked crate `n` | help: a trait with a similar name exists: `Fn` + | + = help: you might be missing a crate named `n` -error[E0433]: failed to resolve: use of undeclared crate or module `m` +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `m` --> $DIR/issue-120856.rs:1:25 | LL | pub type Archived<T> = <m::Alias as n::Trait>::Archived; | ^ | | - | use of undeclared crate or module `m` + | use of unresolved module or unlinked crate `m` | help: a type parameter with a similar name exists: `T` + | + = help: you might be missing a crate named `m` error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-82772.stderr b/tests/ui/typeck/issue-82772.stderr index 321143cb968..a314306137a 100644 --- a/tests/ui/typeck/issue-82772.stderr +++ b/tests/ui/typeck/issue-82772.stderr @@ -2,19 +2,19 @@ error[E0451]: field `0` of struct `Box` is private --> $DIR/issue-82772.rs:5:15 | LL | let Box { 0: _, .. }: Box<()>; - | ^^^^ private field + | ^ private field error[E0451]: field `1` of struct `Box` is private --> $DIR/issue-82772.rs:6:15 | LL | let Box { 1: _, .. }: Box<()>; - | ^^^^ private field + | ^ private field error[E0451]: field `1` of struct `ModPrivateStruct` is private --> $DIR/issue-82772.rs:7:28 | LL | let ModPrivateStruct { 1: _, .. } = ModPrivateStruct::default(); - | ^^^^ private field + | ^ private field error: aborting due to 3 previous errors diff --git a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.cargo-invoked.stderr b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.cargo-invoked.stderr new file mode 100644 index 00000000000..8a3b87b0d11 --- /dev/null +++ b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.cargo-invoked.stderr @@ -0,0 +1,11 @@ +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `page_size` + --> $DIR/path-to-method-sugg-unresolved-expr.rs:5:21 + | +LL | let page_size = page_size::get(); + | ^^^^^^^^^ use of unresolved module or unlinked crate `page_size` + | + = help: if you wanted to use a crate named `page_size`, use `cargo add page_size` to add it to your `Cargo.toml` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.only-rustc.stderr b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.only-rustc.stderr new file mode 100644 index 00000000000..34ed5c44d93 --- /dev/null +++ b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.only-rustc.stderr @@ -0,0 +1,11 @@ +error[E0433]: failed to resolve: use of unresolved module or unlinked crate `page_size` + --> $DIR/path-to-method-sugg-unresolved-expr.rs:5:21 + | +LL | let page_size = page_size::get(); + | ^^^^^^^^^ use of unresolved module or unlinked crate `page_size` + | + = help: you might be missing a crate named `page_size` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs index fb56b394493..7b4f62fea0c 100644 --- a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs +++ b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.rs @@ -1,4 +1,10 @@ +//@ revisions: only-rustc cargo-invoked +//@[only-rustc] unset-rustc-env:CARGO_CRATE_NAME +//@[cargo-invoked] rustc-env:CARGO_CRATE_NAME=foo fn main() { let page_size = page_size::get(); - //~^ ERROR failed to resolve: use of undeclared crate or module `page_size` + //~^ ERROR failed to resolve: use of unresolved module or unlinked crate `page_size` + //~| NOTE use of unresolved module or unlinked crate `page_size` + //@[cargo-invoked]~^^^ HELP if you wanted to use a crate named `page_size`, use `cargo add + //@[only-rustc]~^^^^ HELP you might be missing a crate named `page_size` } diff --git a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr b/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr deleted file mode 100644 index 3e03c17f3b1..00000000000 --- a/tests/ui/typeck/path-to-method-sugg-unresolved-expr.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0433]: failed to resolve: use of undeclared crate or module `page_size` - --> $DIR/path-to-method-sugg-unresolved-expr.rs:2:21 - | -LL | let page_size = page_size::get(); - | ^^^^^^^^^ use of undeclared crate or module `page_size` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0433`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index c97b9312076..d2a850d7dbf 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -507,22 +507,12 @@ LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures | | | not allowed in type signatures - | -help: use type parameters instead - | -LL | impl<T> BadTrait<T> for BadStruct<T> {} - | +++ ~ ~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions --> $DIR/typeck_type_placeholder_item.rs:162:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures - | -help: use type parameters instead - | -LL | fn impl_trait<T>() -> impl BadTrait<T> { - | +++ ~ error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/typeck_type_placeholder_item.rs:167:25 diff --git a/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr b/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr deleted file mode 100644 index 67527ce1ac4..00000000000 --- a/tests/ui/uninhabited/uninhabited-irrefutable.min_exhaustive_patterns.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error[E0005]: refutable pattern in local binding - --> $DIR/uninhabited-irrefutable.rs:31:9 - | -LL | let Foo::D(_y, _z) = x; - | ^^^^^^^^^^^^^^ pattern `Foo::A(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html -note: `Foo` defined here - --> $DIR/uninhabited-irrefutable.rs:20:6 - | -LL | enum Foo { - | ^^^ -LL | -LL | A(foo::SecretlyEmpty), - | - not covered - = note: pattern `Foo::A(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future - = note: the matched value is of type `Foo` -help: you might want to use `let else` to handle the variant that isn't matched - | -LL | let Foo::D(_y, _z) = x else { todo!() }; - | ++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/union/union-derive-eq.stderr b/tests/ui/union/union-derive-eq.current.stderr index b068edd6d69..151ceebe1ba 100644 --- a/tests/ui/union/union-derive-eq.stderr +++ b/tests/ui/union/union-derive-eq.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied - --> $DIR/union-derive-eq.rs:13:5 + --> $DIR/union-derive-eq.rs:21:5 | LL | #[derive(Eq)] | -- in this derive macro expansion diff --git a/tests/ui/union/union-derive-eq.next.stderr b/tests/ui/union/union-derive-eq.next.stderr new file mode 100644 index 00000000000..3952b1f1284 --- /dev/null +++ b/tests/ui/union/union-derive-eq.next.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `PartialEqNotEq: Eq` is not satisfied + --> $DIR/union-derive-eq.rs:21:5 + | +LL | #[derive(Eq)] + | -- in this derive macro expansion +LL | union U2 { +LL | a: PartialEqNotEq, + | ^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `PartialEqNotEq` + | + = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider annotating `PartialEqNotEq` with `#[derive(Eq)]` + | +LL + #[derive(Eq)] +LL | struct PartialEqNotEq; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/union/union-derive-eq.rs b/tests/ui/union/union-derive-eq.rs index e689f8c27d7..085262a72a1 100644 --- a/tests/ui/union/union-derive-eq.rs +++ b/tests/ui/union/union-derive-eq.rs @@ -1,9 +1,17 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + #[derive(Eq)] // OK union U1 { a: u8, } -impl PartialEq for U1 { fn eq(&self, rhs: &Self) -> bool { true } } +impl PartialEq for U1 { + fn eq(&self, rhs: &Self) -> bool { + true + } +} #[derive(PartialEq, Copy, Clone)] struct PartialEqNotEq; @@ -13,6 +21,10 @@ union U2 { a: PartialEqNotEq, //~ ERROR the trait bound `PartialEqNotEq: Eq` is not satisfied } -impl PartialEq for U2 { fn eq(&self, rhs: &Self) -> bool { true } } +impl PartialEq for U2 { + fn eq(&self, rhs: &Self) -> bool { + true + } +} fn main() {} diff --git a/tests/ui/unpretty/staged-api-invalid-path-108697.stderr b/tests/ui/unpretty/staged-api-invalid-path-108697.stderr index 9c6d1a042d7..e68e19c4dc9 100644 --- a/tests/ui/unpretty/staged-api-invalid-path-108697.stderr +++ b/tests/ui/unpretty/staged-api-invalid-path-108697.stderr @@ -1,4 +1,4 @@ -error: couldn't read $DIR/lol: No such file or directory (os error 2) +error: couldn't read `$DIR/lol`: No such file or directory (os error 2) --> $DIR/staged-api-invalid-path-108697.rs:8:1 | LL | mod foo; diff --git a/tests/ui/unresolved/unresolved-asterisk-imports.stderr b/tests/ui/unresolved/unresolved-asterisk-imports.stderr index ed01f3fdbea..e84f1975112 100644 --- a/tests/ui/unresolved/unresolved-asterisk-imports.stderr +++ b/tests/ui/unresolved/unresolved-asterisk-imports.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `not_existing_crate` --> $DIR/unresolved-asterisk-imports.rs:1:5 | LL | use not_existing_crate::*; - | ^^^^^^^^^^^^^^^^^^ you might be missing crate `not_existing_crate` + | ^^^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `not_existing_crate` | -help: consider importing the `not_existing_crate` crate +help: you might be missing a crate named `not_existing_crate`, add it to your project and import it in your code | LL + extern crate not_existing_crate; | diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs index ee520d65e6f..763e9496734 100644 --- a/tests/ui/unresolved/unresolved-import.rs +++ b/tests/ui/unresolved/unresolved-import.rs @@ -1,7 +1,7 @@ use foo::bar; //~^ ERROR unresolved import `foo` [E0432] -//~| NOTE you might be missing crate `foo` -//~| HELP consider importing the `foo` crate +//~| NOTE use of unresolved module or unlinked crate `foo` +//~| HELP you might be missing a crate named `foo` //~| SUGGESTION extern crate foo; use bar::Baz as x; diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr index a1ff2f19eb6..c65fe841001 100644 --- a/tests/ui/unresolved/unresolved-import.stderr +++ b/tests/ui/unresolved/unresolved-import.stderr @@ -2,9 +2,9 @@ error[E0432]: unresolved import `foo` --> $DIR/unresolved-import.rs:1:5 | LL | use foo::bar; - | ^^^ you might be missing crate `foo` + | ^^^ use of unresolved module or unlinked crate `foo` | -help: consider importing the `foo` crate +help: you might be missing a crate named `foo`, add it to your project and import it in your code | LL + extern crate foo; | diff --git a/tests/ui/use/use.rs b/tests/ui/use/use.rs index db031500a4a..25b8e529c43 100644 --- a/tests/ui/use/use.rs +++ b/tests/ui/use/use.rs @@ -3,7 +3,7 @@ #![allow(stable_features)] #![allow(unused_imports)] -#![feature(start, no_core, core)] +#![feature(no_core, core)] #![no_core] extern crate std; @@ -18,5 +18,4 @@ mod baz { pub use std::str as x; } -#[start] -pub fn start(_: isize, _: *const *const u8) -> isize { 0 } +fn main() {} diff --git a/tests/ui/wait-forked-but-failed-child.rs b/tests/ui/wait-forked-but-failed-child.rs index dd6a7fa0e65..04f1c1a65d5 100644 --- a/tests/ui/wait-forked-but-failed-child.rs +++ b/tests/ui/wait-forked-but-failed-child.rs @@ -1,6 +1,5 @@ //@ run-pass -//@ ignore-wasm32 no processes -//@ ignore-sgx no processes +//@ needs-subprocess //@ ignore-vxworks no 'ps' //@ ignore-fuchsia no 'ps' //@ ignore-nto no 'ps' diff --git a/tests/ui/wasm/wasm-bindgen-broken-error.rs b/tests/ui/wasm/wasm-bindgen-broken-error.rs new file mode 100644 index 00000000000..d985e879803 --- /dev/null +++ b/tests/ui/wasm/wasm-bindgen-broken-error.rs @@ -0,0 +1,28 @@ +//@ only-wasm32 +//@ revisions: v0_1_0 v0_2_87 v0_2_88 v0_3_0 v1_0_0 +//@[v0_1_0] check-fail +//@[v0_1_0] rustc-env:CARGO_PKG_VERSION_MAJOR=0 +//@[v0_1_0] rustc-env:CARGO_PKG_VERSION_MINOR=1 +//@[v0_1_0] rustc-env:CARGO_PKG_VERSION_PATCH=0 +//@[v0_2_87] check-fail +//@[v0_2_87] rustc-env:CARGO_PKG_VERSION_MAJOR=0 +//@[v0_2_87] rustc-env:CARGO_PKG_VERSION_MINOR=2 +//@[v0_2_87] rustc-env:CARGO_PKG_VERSION_PATCH=87 +//@[v0_2_88] check-pass +//@[v0_2_88] rustc-env:CARGO_PKG_VERSION_MAJOR=0 +//@[v0_2_88] rustc-env:CARGO_PKG_VERSION_MINOR=2 +//@[v0_2_88] rustc-env:CARGO_PKG_VERSION_PATCH=88 +//@[v0_3_0] check-pass +//@[v0_3_0] rustc-env:CARGO_PKG_VERSION_MAJOR=0 +//@[v0_3_0] rustc-env:CARGO_PKG_VERSION_MINOR=3 +//@[v0_3_0] rustc-env:CARGO_PKG_VERSION_PATCH=0 +//@[v1_0_0] check-pass +//@[v1_0_0] rustc-env:CARGO_PKG_VERSION_MAJOR=1 +//@[v1_0_0] rustc-env:CARGO_PKG_VERSION_MINOR=0 +//@[v1_0_0] rustc-env:CARGO_PKG_VERSION_PATCH=0 + +#![crate_name = "wasm_bindgen"] +//[v0_1_0]~^ ERROR: older versions of the `wasm-bindgen` crate +//[v0_2_87]~^^ ERROR: older versions of the `wasm-bindgen` crate + +fn main() {} diff --git a/tests/ui/wasm/wasm-bindgen-broken-error.v0_1_0.stderr b/tests/ui/wasm/wasm-bindgen-broken-error.v0_1_0.stderr new file mode 100644 index 00000000000..e1c1ec7ef33 --- /dev/null +++ b/tests/ui/wasm/wasm-bindgen-broken-error.v0_1_0.stderr @@ -0,0 +1,8 @@ +error: older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88 + --> $DIR/wasm-bindgen-broken-error.rs:24:1 + | +LL | #![crate_name = "wasm_bindgen"] + | ^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/wasm/wasm-bindgen-broken-error.v0_2_87.stderr b/tests/ui/wasm/wasm-bindgen-broken-error.v0_2_87.stderr new file mode 100644 index 00000000000..e1c1ec7ef33 --- /dev/null +++ b/tests/ui/wasm/wasm-bindgen-broken-error.v0_2_87.stderr @@ -0,0 +1,8 @@ +error: older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88 + --> $DIR/wasm-bindgen-broken-error.rs:24:1 + | +LL | #![crate_name = "wasm_bindgen"] + | ^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/wf/issue-87495.rs b/tests/ui/wf/issue-87495.rs index 5aab7431134..ce5c617bbbd 100644 --- a/tests/ui/wf/issue-87495.rs +++ b/tests/ui/wf/issue-87495.rs @@ -2,7 +2,7 @@ trait T { const CONST: (bool, dyn T); - //~^ ERROR: the trait `T` cannot be made into an object [E0038] + //~^ ERROR: the trait `T` is not dyn compatible [E0038] } fn main() {} diff --git a/tests/ui/wf/issue-87495.stderr b/tests/ui/wf/issue-87495.stderr index 5973fff3e00..7be327e61d1 100644 --- a/tests/ui/wf/issue-87495.stderr +++ b/tests/ui/wf/issue-87495.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `T` cannot be made into an object +error[E0038]: the trait `T` is not dyn compatible --> $DIR/issue-87495.rs:4:25 | LL | const CONST: (bool, dyn T); - | ^^^^^ `T` cannot be made into an object + | ^^^^^ `T` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/issue-87495.rs:4:11 | LL | trait T { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | const CONST: (bool, dyn T); | ^^^^^ ...because it contains this associated `const` = help: consider moving `CONST` to another trait diff --git a/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr index 38426545bc8..0b7f4cd4362 100644 --- a/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj-box.stderr @@ -1,49 +1,52 @@ -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:16:33 | LL | let t_box: Box<dyn Trait> = Box::new(S); - | ^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... - = help: only type `S` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `S` implements `Trait`; consider using it directly instead. = note: required for the cast from `Box<S>` to `Box<dyn Trait>` -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:17:15 | LL | takes_box(Box::new(S)); - | ^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... - = help: only type `S` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `S` implements `Trait`; consider using it directly instead. = note: required for the cast from `Box<S>` to `Box<(dyn Trait + 'static)>` -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:15:5 | LL | Box::new(S) as Box<dyn Trait>; - | ^^^^^^^^^^^ `Trait` cannot be made into an object + | ^^^^^^^^^^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-convert-dyn-incompat-trait-obj-box.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... - = help: only type `S` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `S` implements `Trait`; consider using it directly instead. = note: required for the cast from `Box<S>` to `Box<dyn Trait>` error: aborting due to 3 previous errors diff --git a/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr index 94259aa5b0a..3f50e1192cf 100644 --- a/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr +++ b/tests/ui/wf/wf-convert-dyn-incompat-trait-obj.stderr @@ -1,49 +1,52 @@ -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:16:25 | LL | let t: &dyn Trait = &S; - | ^^ `Trait` cannot be made into an object + | ^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... - = help: only type `S` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `S` implements `Trait`; consider using it directly instead. = note: required for the cast from `&S` to `&dyn Trait` -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:17:17 | LL | takes_trait(&S); - | ^^ `Trait` cannot be made into an object + | ^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... - = help: only type `S` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `S` implements `Trait`; consider using it directly instead. = note: required for the cast from `&S` to `&dyn Trait` -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:15:5 | LL | &S as &dyn Trait; - | ^^ `Trait` cannot be made into an object + | ^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-convert-dyn-incompat-trait-obj.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... - = help: only type `S` implements the trait, consider using it directly instead + | this trait is not dyn compatible... + = help: only type `S` implements `Trait`; consider using it directly instead. = note: required for the cast from `&S` to `&dyn Trait` error: aborting due to 3 previous errors diff --git a/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr index 6cd4ebf8412..8f68f9c5b6b 100644 --- a/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr +++ b/tests/ui/wf/wf-dyn-incompat-trait-obj-match.stderr @@ -12,40 +12,46 @@ LL | | } = note: expected reference `&S` found reference `&R` -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/wf-dyn-incompat-trait-obj-match.rs:26:21 | LL | Some(()) => &S, - | ^^ `Trait` cannot be made into an object + | ^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead: + | this trait is not dyn compatible... + = help: the following types implement `Trait`: S R + consider defining an enum where each variant holds one of these types, + implementing `Trait` for this new enum and using it instead = note: required for the cast from `&S` to `&dyn Trait` -error[E0038]: the trait `Trait` cannot be made into an object +error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/wf-dyn-incompat-trait-obj-match.rs:27:17 | LL | None => &R, - | ^^ `Trait` cannot be made into an object + | ^^ `Trait` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-dyn-incompat-trait-obj-match.rs:6:14 | LL | trait Trait: Sized {} | ----- ^^^^^ ...because it requires `Self: Sized` | | - | this trait cannot be made into an object... - = help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Trait` for this new enum and using it instead: + | this trait is not dyn compatible... + = help: the following types implement `Trait`: S R + consider defining an enum where each variant holds one of these types, + implementing `Trait` for this new enum and using it instead = note: required for the cast from `&R` to `&dyn Trait` error: aborting due to 3 previous errors diff --git a/tests/ui/wf/wf-dyn-incompatible.stderr b/tests/ui/wf/wf-dyn-incompatible.stderr index cf016b63c74..1803376aaa1 100644 --- a/tests/ui/wf/wf-dyn-incompatible.stderr +++ b/tests/ui/wf/wf-dyn-incompatible.stderr @@ -1,14 +1,15 @@ -error[E0038]: the trait `A` cannot be made into an object +error[E0038]: the trait `A` is not dyn compatible --> $DIR/wf-dyn-incompatible.rs:9:13 | LL | let _x: &dyn A; - | ^^^^^^ `A` cannot be made into an object + | ^^^^^^ `A` is not dyn compatible | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> +note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> --> $DIR/wf-dyn-incompatible.rs:5:23 | LL | trait A { - | - this trait cannot be made into an object... + | - this trait is not dyn compatible... LL | fn foo(&self, _x: &Self); | ^^^^^ ...because method `foo` references the `Self` type in this parameter = help: consider moving `foo` to another trait diff --git a/tests/ui/wf/wf-fn-where-clause.stderr b/tests/ui/wf/wf-fn-where-clause.stderr index 76671dedabf..d73376e9861 100644 --- a/tests/ui/wf/wf-fn-where-clause.stderr +++ b/tests/ui/wf/wf-fn-where-clause.stderr @@ -14,14 +14,15 @@ help: consider further restricting type parameter `U` with trait `Copy` LL | fn foo<T,U>() where T: ExtraCopy<U>, U: std::marker::Copy | ++++++++++++++++++++++ -error[E0038]: the trait `Copy` cannot be made into an object +error[E0038]: the trait `Copy` is not dyn compatible --> $DIR/wf-fn-where-clause.rs:12:16 | LL | fn bar() where Vec<dyn Copy>:, {} - | ^^^^^^^^^^^^^ `Copy` cannot be made into an object + | ^^^^^^^^^^^^^ `Copy` is not dyn compatible | - = note: the trait cannot be made into an object because it requires `Self: Sized` - = note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + = note: the trait is not dyn compatible because it requires `Self: Sized` + = note: for a trait to be dyn compatible it needs to allow building a vtable + for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> error[E0277]: the size for values of type `(dyn Copy + 'static)` cannot be known at compilation time --> $DIR/wf-fn-where-clause.rs:12:16 diff --git a/tests/ui/wf/wf-trait-fn-arg.stderr b/tests/ui/wf/wf-trait-fn-arg.current.stderr index 8b35f36fa68..d5dd36fad6d 100644 --- a/tests/ui/wf/wf-trait-fn-arg.stderr +++ b/tests/ui/wf/wf-trait-fn-arg.current.stderr @@ -1,14 +1,14 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied - --> $DIR/wf-trait-fn-arg.rs:10:23 + --> $DIR/wf-trait-fn-arg.rs:16:23 | LL | fn bar(&self, x: &Bar<Self>); | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | note: required by a bound in `Bar` - --> $DIR/wf-trait-fn-arg.rs:7:14 + --> $DIR/wf-trait-fn-arg.rs:11:15 | -LL | struct Bar<T:Eq+?Sized> { value: Box<T> } - | ^^ required by this bound in `Bar` +LL | struct Bar<T: Eq + ?Sized> { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | fn bar(&self, x: &Bar<Self>) where Self: Eq; diff --git a/tests/ui/wf/wf-trait-fn-arg.next.stderr b/tests/ui/wf/wf-trait-fn-arg.next.stderr new file mode 100644 index 00000000000..c55dc5c8a12 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-arg.next.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-arg.rs:16:23 + | +LL | fn bar(&self, x: &Bar<Self>); + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn bar(&self, x: &Bar<Self>) where Self: Eq; + | ++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-arg.rs b/tests/ui/wf/wf-trait-fn-arg.rs index 0445699427e..13a5b32828d 100644 --- a/tests/ui/wf/wf-trait-fn-arg.rs +++ b/tests/ui/wf/wf-trait-fn-arg.rs @@ -1,16 +1,22 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + // Check that we test WF conditions for fn arguments in a trait definition. #![feature(rustc_attrs)] #![allow(dead_code)] #![allow(unused_variables)] -struct Bar<T:Eq+?Sized> { value: Box<T> } +struct Bar<T: Eq + ?Sized> { + value: Box<T>, +} trait Foo { fn bar(&self, x: &Bar<Self>); - //~^ ERROR E0277 - // - // Here, Eq ought to be implemented. + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. } -fn main() { } +fn main() {} diff --git a/tests/ui/wf/wf-trait-fn-ret.stderr b/tests/ui/wf/wf-trait-fn-ret.current.stderr index 3d70f04def2..0ad786c2fd5 100644 --- a/tests/ui/wf/wf-trait-fn-ret.stderr +++ b/tests/ui/wf/wf-trait-fn-ret.current.stderr @@ -1,14 +1,14 @@ error[E0277]: the trait bound `Self: Eq` is not satisfied - --> $DIR/wf-trait-fn-ret.rs:10:23 + --> $DIR/wf-trait-fn-ret.rs:15:23 | LL | fn bar(&self) -> &Bar<Self>; | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` | note: required by a bound in `Bar` - --> $DIR/wf-trait-fn-ret.rs:7:14 + --> $DIR/wf-trait-fn-ret.rs:10:15 | -LL | struct Bar<T:Eq+?Sized> { value: Box<T> } - | ^^ required by this bound in `Bar` +LL | struct Bar<T: Eq + ?Sized> { + | ^^ required by this bound in `Bar` help: consider further restricting `Self` | LL | fn bar(&self) -> &Bar<Self> where Self: Eq; diff --git a/tests/ui/wf/wf-trait-fn-ret.next.stderr b/tests/ui/wf/wf-trait-fn-ret.next.stderr new file mode 100644 index 00000000000..b3dca17672d --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-ret.next.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-ret.rs:15:23 + | +LL | fn bar(&self) -> &Bar<Self>; + | ^^^^^^^^^ the trait `Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn bar(&self) -> &Bar<Self> where Self: Eq; + | ++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-ret.rs b/tests/ui/wf/wf-trait-fn-ret.rs index f49e4308770..c00f6dd10af 100644 --- a/tests/ui/wf/wf-trait-fn-ret.rs +++ b/tests/ui/wf/wf-trait-fn-ret.rs @@ -1,16 +1,21 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) // Check that we test WF conditions for fn return types in a trait definition. #![feature(rustc_attrs)] #![allow(dead_code)] #![allow(unused_variables)] -struct Bar<T:Eq+?Sized> { value: Box<T> } +struct Bar<T: Eq + ?Sized> { + value: Box<T>, +} trait Foo { fn bar(&self) -> &Bar<Self>; - //~^ ERROR E0277 - // - // Here, Eq ought to be implemented. + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. } -fn main() { } +fn main() {} diff --git a/tests/ui/wf/wf-trait-fn-where-clause.current.stderr b/tests/ui/wf/wf-trait-fn-where-clause.current.stderr new file mode 100644 index 00000000000..db5454d0f3c --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-where-clause.current.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-where-clause.rs:18:20 + | +LL | Bar<Self>: Copy; + | ^^^^ the trait `Eq` is not implemented for `Self` + | +note: required by a bound in `Bar` + --> $DIR/wf-trait-fn-where-clause.rs:10:15 + | +LL | struct Bar<T: Eq + ?Sized> { + | ^^ required by this bound in `Bar` +help: consider further restricting `Self` + | +LL | Bar<Self>: Copy, Self: Eq; + | ++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-where-clause.next.stderr b/tests/ui/wf/wf-trait-fn-where-clause.next.stderr new file mode 100644 index 00000000000..8c8a5fa3e70 --- /dev/null +++ b/tests/ui/wf/wf-trait-fn-where-clause.next.stderr @@ -0,0 +1,14 @@ +error[E0277]: the trait bound `Self: Eq` is not satisfied + --> $DIR/wf-trait-fn-where-clause.rs:18:20 + | +LL | Bar<Self>: Copy; + | ^^^^ the trait `Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | Bar<Self>: Copy, Self: Eq; + | ++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/wf-trait-fn-where-clause.rs b/tests/ui/wf/wf-trait-fn-where-clause.rs index 1d2427ff981..9e36682e449 100644 --- a/tests/ui/wf/wf-trait-fn-where-clause.rs +++ b/tests/ui/wf/wf-trait-fn-where-clause.rs @@ -1,17 +1,24 @@ -// Check that we test WF conditions for fn where clauses in a trait definition. +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +// Check that we test WF conditions for fn where clauses in a trait definition. #![allow(dead_code)] #![allow(unused_variables)] -struct Bar<T:Eq+?Sized> { value: Box<T> } +struct Bar<T: Eq + ?Sized> { + value: Box<T>, +} trait Foo { - fn bar(&self) where Self: Sized, Bar<Self>: Copy; - //~^ ERROR E0277 - // - // Here, Eq ought to be implemented. + fn bar(&self) + where + Self: Sized, + Bar<Self>: Copy; + //~^ ERROR E0277 + // + // Here, Eq ought to be implemented. } - -fn main() { } +fn main() {} diff --git a/tests/ui/wf/wf-trait-fn-where-clause.stderr b/tests/ui/wf/wf-trait-fn-where-clause.stderr deleted file mode 100644 index 0ad3b58e7c7..00000000000 --- a/tests/ui/wf/wf-trait-fn-where-clause.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: the trait bound `Self: Eq` is not satisfied - --> $DIR/wf-trait-fn-where-clause.rs:10:49 - | -LL | fn bar(&self) where Self: Sized, Bar<Self>: Copy; - | ^^^^ the trait `Eq` is not implemented for `Self` - | -note: required by a bound in `Bar` - --> $DIR/wf-trait-fn-where-clause.rs:7:14 - | -LL | struct Bar<T:Eq+?Sized> { value: Box<T> } - | ^^ required by this bound in `Bar` -help: consider further restricting `Self` - | -LL | fn bar(&self) where Self: Sized, Bar<Self>: Copy, Self: Eq; - | ++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr index 840df342ef9..d1de813a2d9 100644 --- a/tests/ui/where-clauses/where-clauses-method-unsatisfied.stderr +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr @@ -1,14 +1,17 @@ error[E0277]: the trait bound `Bar: Eq` is not satisfied - --> $DIR/where-clauses-method-unsatisfied.rs:18:7 + --> $DIR/where-clauses-method-unsatisfied.rs:24:7 | LL | x.equals(&x); | ^^^^^^ the trait `Eq` is not implemented for `Bar` | note: required by a bound in `Foo::<T>::equals` - --> $DIR/where-clauses-method-unsatisfied.rs:11:52 + --> $DIR/where-clauses-method-unsatisfied.rs:16:12 | -LL | fn equals(&self, u: &Foo<T>) -> bool where T : Eq { - | ^^ required by this bound in `Foo::<T>::equals` +LL | fn equals(&self, u: &Foo<T>) -> bool + | ------ required by a bound in this associated function +LL | where +LL | T: Eq, + | ^^ required by this bound in `Foo::<T>::equals` help: consider annotating `Bar` with `#[derive(Eq)]` | LL + #[derive(Eq)] diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr new file mode 100644 index 00000000000..d1de813a2d9 --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `Bar: Eq` is not satisfied + --> $DIR/where-clauses-method-unsatisfied.rs:24:7 + | +LL | x.equals(&x); + | ^^^^^^ the trait `Eq` is not implemented for `Bar` + | +note: required by a bound in `Foo::<T>::equals` + --> $DIR/where-clauses-method-unsatisfied.rs:16:12 + | +LL | fn equals(&self, u: &Foo<T>) -> bool + | ------ required by a bound in this associated function +LL | where +LL | T: Eq, + | ^^ required by this bound in `Foo::<T>::equals` +help: consider annotating `Bar` with `#[derive(Eq)]` + | +LL + #[derive(Eq)] +LL | struct Bar; // does not implement Eq + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs b/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs index a8ae0296407..34e9d9b57d1 100644 --- a/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.rs @@ -1,14 +1,20 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) // Test that a where clause attached to a method allows us to add // additional constraints to a parameter out of scope. struct Foo<T> { - value: T + value: T, } struct Bar; // does not implement Eq impl<T> Foo<T> { - fn equals(&self, u: &Foo<T>) -> bool where T : Eq { + fn equals(&self, u: &Foo<T>) -> bool + where + T: Eq, + { self.value == u.value } } diff --git a/tests/ui/where-clauses/where-clauses-unsatisfied.stderr b/tests/ui/where-clauses/where-clauses-unsatisfied.current.stderr index 205b82d49bf..485b9459ddd 100644 --- a/tests/ui/where-clauses/where-clauses-unsatisfied.stderr +++ b/tests/ui/where-clauses/where-clauses-unsatisfied.current.stderr @@ -1,14 +1,17 @@ error[E0277]: the trait bound `Struct: Eq` is not satisfied - --> $DIR/where-clauses-unsatisfied.rs:6:10 + --> $DIR/where-clauses-unsatisfied.rs:15:10 | LL | drop(equal(&Struct, &Struct)) | ^^^^^ the trait `Eq` is not implemented for `Struct` | note: required by a bound in `equal` - --> $DIR/where-clauses-unsatisfied.rs:1:45 + --> $DIR/where-clauses-unsatisfied.rs:7:8 | -LL | fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b } - | ^^ required by this bound in `equal` +LL | fn equal<T>(a: &T, b: &T) -> bool + | ----- required by a bound in this function +LL | where +LL | T: Eq, + | ^^ required by this bound in `equal` help: consider annotating `Struct` with `#[derive(Eq)]` | LL + #[derive(Eq)] diff --git a/tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr b/tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr new file mode 100644 index 00000000000..485b9459ddd --- /dev/null +++ b/tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr @@ -0,0 +1,23 @@ +error[E0277]: the trait bound `Struct: Eq` is not satisfied + --> $DIR/where-clauses-unsatisfied.rs:15:10 + | +LL | drop(equal(&Struct, &Struct)) + | ^^^^^ the trait `Eq` is not implemented for `Struct` + | +note: required by a bound in `equal` + --> $DIR/where-clauses-unsatisfied.rs:7:8 + | +LL | fn equal<T>(a: &T, b: &T) -> bool + | ----- required by a bound in this function +LL | where +LL | T: Eq, + | ^^ required by this bound in `equal` +help: consider annotating `Struct` with `#[derive(Eq)]` + | +LL + #[derive(Eq)] +LL | struct Struct; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/where-clauses/where-clauses-unsatisfied.rs b/tests/ui/where-clauses/where-clauses-unsatisfied.rs index 8b067d30a2a..48798e2a15d 100644 --- a/tests/ui/where-clauses/where-clauses-unsatisfied.rs +++ b/tests/ui/where-clauses/where-clauses-unsatisfied.rs @@ -1,4 +1,13 @@ -fn equal<T>(a: &T, b: &T) -> bool where T : Eq { a == b } +//@ revisions: current next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) + +fn equal<T>(a: &T, b: &T) -> bool +where + T: Eq, +{ + a == b +} struct Struct; diff --git a/triagebot.toml b/triagebot.toml index 5ee52bbf435..d09d5eceeb8 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1025,6 +1025,8 @@ users_on_vacation = [ "nnethercote", "spastorino", "workingjubilee", + "kobzol", + "jieyouxu", ] [[assign.warn_non_default_branch.exceptions]] |
