From 7de250f1e34ac18cf616179353a67019dfc2c0d6 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 1 Jan 2025 15:25:20 +0100 Subject: [PATCH 01/16] Stabilize const_slice_flatten Const-stabilizes `slice::as_flattened{,_mut}`: ```rust // core::slice impl [[T; N]] { pub const fn as_flattened(&self) -> &[T]; pub const fn as_flattened_mut(&mut self) -> &mut [T]; } ``` Tracking issue: https://github.com/rust-lang/rust/issues/95629 Requires separate libs-api FCP, as per https://github.com/rust-lang/rust/issues/95629#issuecomment-2566546257. Closes https://github.com/rust-lang/rust/issues/95629. --- library/core/src/slice/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index df9720698d32f..3ba1cbb129075 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4784,7 +4784,7 @@ impl [[T; N]] { /// assert!(empty_slice_of_arrays.as_flattened().is_empty()); /// ``` #[stable(feature = "slice_flatten", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")] + #[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")] pub const fn as_flattened(&self) -> &[T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") @@ -4821,7 +4821,7 @@ impl [[T; N]] { /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]); /// ``` #[stable(feature = "slice_flatten", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")] + #[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")] pub const fn as_flattened_mut(&mut self) -> &mut [T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") From 9cb74323aa9e17d910166994b824a9797f77d7a3 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Thu, 30 Jan 2025 15:03:50 +0100 Subject: [PATCH 02/16] Improve instant docs --- library/std/src/time.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 9f4f8a0d0880c..797c5ff24c006 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -96,11 +96,17 @@ use crate::sys_common::{FromInner, IntoInner}; /// use std::time::{Instant, Duration}; /// /// let now = Instant::now(); -/// let max_seconds = u64::MAX / 1_000_000_000; -/// let duration = Duration::new(max_seconds, 0); +/// let days_per_10_millennia = 365_2425; +/// let solar_seconds_per_day = 60 * 60 * 24; +/// let millenium_in_solar_seconds = 31_556_952_000; +/// assert_eq!(millenium_in_solar_seconds, days_per_10_millennia * solar_seconds_per_day / 10); +/// +/// let duration = Duration::new(millenium_in_solar_seconds, 0); /// println!("{:?}", now + duration); /// ``` /// +/// For cross-platform code, you can comfortably use durations of up to around one hundred years. +/// /// # Underlying System calls /// /// The following system calls are [currently] being used by `now()` to find out From ca58e23ede760152eaa6c6fb7b880a991ade0fd0 Mon Sep 17 00:00:00 2001 From: Tommaso Allevi Date: Fri, 31 Jan 2025 11:01:37 +0100 Subject: [PATCH 03/16] Update fs.rs --- library/std/src/fs.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index a5b0111adfb4a..5631c3e0156cf 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2505,6 +2505,7 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// * `from` does not exist. /// * The current process does not have the permission rights to read /// `from` or write `to`. +/// * The parent folder of `to` doesn't exists /// /// # Examples /// From 82af73dd4c58cd6bec5fb44cf02f7ac96b1ed48b Mon Sep 17 00:00:00 2001 From: Christopher Berner Date: Sun, 9 Feb 2025 13:54:50 -0800 Subject: [PATCH 04/16] Stabilize file_lock --- library/std/src/fs.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 0871a9e22d386..509b9388af5da 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -660,7 +660,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -669,7 +668,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn lock(&self) -> io::Result<()> { self.inner.lock() } @@ -708,7 +707,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -717,7 +715,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn lock_shared(&self) -> io::Result<()> { self.inner.lock_shared() } @@ -763,7 +761,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -772,7 +769,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn try_lock(&self) -> io::Result { self.inner.try_lock() } @@ -815,7 +812,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -824,7 +820,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn try_lock_shared(&self) -> io::Result { self.inner.try_lock_shared() } @@ -849,7 +845,6 @@ impl File { /// # Examples /// /// ```no_run - /// #![feature(file_lock)] /// use std::fs::File; /// /// fn main() -> std::io::Result<()> { @@ -859,7 +854,7 @@ impl File { /// Ok(()) /// } /// ``` - #[unstable(feature = "file_lock", issue = "130994")] + #[stable(feature = "file_lock", since = "CURRENT_RUSTC_VERSION")] pub fn unlock(&self) -> io::Result<()> { self.inner.unlock() } From 18d7ffa8fc82cd85382339a72b8acaa92c7a25b0 Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Sat, 15 Feb 2025 15:16:27 -0500 Subject: [PATCH 05/16] Prepare `./x setup` to handle more IDEs; make minor improvements * Order IDEs alphabetically so that manually searching for an IDE is easier, both when running `./x setup` and when editing the source code behind `./x setup` * Prepare for IDEs with spaces in their names * Allow explicitly typing 'none' for the IDE * Change capitalization of `Vscode` to the more standard `VsCode` * Make minor efficiency improvements * Add `'static` annotations where they apply --- src/bootstrap/src/core/build_steps/setup.rs | 66 +++++++++++---------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index fbd0dc3ec3021..a732008afdea2 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -523,19 +523,19 @@ undesirable, simply delete the `pre-push` file from .git/hooks." /// Handles editor-specific setup differences #[derive(Clone, Debug, Eq, PartialEq)] enum EditorKind { - Vscode, - Vim, Emacs, Helix, + Vim, + VsCode, } impl EditorKind { fn prompt_user() -> io::Result> { let prompt_str = "Available editors: -1. vscode -2. vim -3. emacs -4. helix +1. Emacs +2. Helix +3. Vim +4. VS Code Select which editor you would like to set up [default: None]: "; @@ -543,28 +543,39 @@ Select which editor you would like to set up [default: None]: "; loop { print!("{}", prompt_str); io::stdout().flush()?; - input.clear(); io::stdin().read_line(&mut input)?; - match input.trim().to_lowercase().as_str() { - "1" | "vscode" => return Ok(Some(EditorKind::Vscode)), - "2" | "vim" => return Ok(Some(EditorKind::Vim)), - "3" | "emacs" => return Ok(Some(EditorKind::Emacs)), - "4" | "helix" => return Ok(Some(EditorKind::Helix)), - "" => return Ok(None), + + let mut modified_input = input.to_lowercase(); + modified_input.retain(|ch| !ch.is_whitespace()); + match modified_input.as_str() { + "1" | "emacs" => return Ok(Some(EditorKind::Emacs)), + "2" | "helix" => return Ok(Some(EditorKind::Helix)), + "3" | "vim" => return Ok(Some(EditorKind::Vim)), + "4" | "vscode" => return Ok(Some(EditorKind::VsCode)), + "" | "none" => return Ok(None), _ => { eprintln!("ERROR: unrecognized option '{}'", input.trim()); eprintln!("NOTE: press Ctrl+C to exit"); } - }; + } + + input.clear(); } } /// A list of historical hashes of each LSP settings file /// New entries should be appended whenever this is updated so we can detect /// outdated vs. user-modified settings files. - fn hashes(&self) -> Vec<&str> { + fn hashes(&self) -> &'static [&'static str] { match self { - EditorKind::Vscode | EditorKind::Vim => vec![ + EditorKind::Emacs => &[ + "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0", + "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45", + ], + EditorKind::Helix => { + &["2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233"] + } + EditorKind::Vim | EditorKind::VsCode => &[ "ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8", "56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922", "af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0", @@ -576,13 +587,6 @@ Select which editor you would like to set up [default: None]: "; "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4", "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d", ], - EditorKind::Emacs => vec![ - "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0", - "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45", - ], - EditorKind::Helix => { - vec!["2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233"] - } } } @@ -592,29 +596,29 @@ Select which editor you would like to set up [default: None]: "; fn settings_short_path(&self) -> PathBuf { self.settings_folder().join(match self { - EditorKind::Vscode => "settings.json", - EditorKind::Vim => "coc-settings.json", EditorKind::Emacs => ".dir-locals.el", EditorKind::Helix => "languages.toml", + EditorKind::Vim => "coc-settings.json", + EditorKind::VsCode => "settings.json", }) } fn settings_folder(&self) -> PathBuf { match self { - EditorKind::Vscode => PathBuf::from(".vscode"), - EditorKind::Vim => PathBuf::from(".vim"), EditorKind::Emacs => PathBuf::new(), EditorKind::Helix => PathBuf::from(".helix"), + EditorKind::Vim => PathBuf::from(".vim"), + EditorKind::VsCode => PathBuf::from(".vscode"), } } - fn settings_template(&self) -> &str { + fn settings_template(&self) -> &'static str { match self { - EditorKind::Vscode | EditorKind::Vim => { - include_str!("../../../../etc/rust_analyzer_settings.json") - } EditorKind::Emacs => include_str!("../../../../etc/rust_analyzer_eglot.el"), EditorKind::Helix => include_str!("../../../../etc/rust_analyzer_helix.toml"), + EditorKind::Vim | EditorKind::VsCode => { + include_str!("../../../../etc/rust_analyzer_settings.json") + } } } From d9f125dcf20f11acea3a7c29c6a3f513350ed964 Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Sat, 15 Feb 2025 16:28:39 -0500 Subject: [PATCH 06/16] Add support for the Zed IDE to `./x setup` --- src/bootstrap/src/core/build_steps/setup.rs | 10 +++- src/etc/rust_analyzer_zed.json | 52 +++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/etc/rust_analyzer_zed.json diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index a732008afdea2..523f688bd914f 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -527,6 +527,7 @@ enum EditorKind { Helix, Vim, VsCode, + Zed, } impl EditorKind { @@ -536,6 +537,7 @@ impl EditorKind { 2. Helix 3. Vim 4. VS Code +5. Zed Select which editor you would like to set up [default: None]: "; @@ -552,6 +554,7 @@ Select which editor you would like to set up [default: None]: "; "2" | "helix" => return Ok(Some(EditorKind::Helix)), "3" | "vim" => return Ok(Some(EditorKind::Vim)), "4" | "vscode" => return Ok(Some(EditorKind::VsCode)), + "5" | "zed" => return Ok(Some(EditorKind::Zed)), "" | "none" => return Ok(None), _ => { eprintln!("ERROR: unrecognized option '{}'", input.trim()); @@ -587,6 +590,9 @@ Select which editor you would like to set up [default: None]: "; "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4", "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d", ], + EditorKind::Zed => { + &["bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c"] + } } } @@ -599,7 +605,7 @@ Select which editor you would like to set up [default: None]: "; EditorKind::Emacs => ".dir-locals.el", EditorKind::Helix => "languages.toml", EditorKind::Vim => "coc-settings.json", - EditorKind::VsCode => "settings.json", + EditorKind::VsCode | EditorKind::Zed => "settings.json", }) } @@ -609,6 +615,7 @@ Select which editor you would like to set up [default: None]: "; EditorKind::Helix => PathBuf::from(".helix"), EditorKind::Vim => PathBuf::from(".vim"), EditorKind::VsCode => PathBuf::from(".vscode"), + EditorKind::Zed => PathBuf::from(".zed"), } } @@ -619,6 +626,7 @@ Select which editor you would like to set up [default: None]: "; EditorKind::Vim | EditorKind::VsCode => { include_str!("../../../../etc/rust_analyzer_settings.json") } + EditorKind::Zed => include_str!("../../../../etc/rust_analyzer_zed.json"), } } diff --git a/src/etc/rust_analyzer_zed.json b/src/etc/rust_analyzer_zed.json new file mode 100644 index 0000000000000..469ea0506218f --- /dev/null +++ b/src/etc/rust_analyzer_zed.json @@ -0,0 +1,52 @@ +{ + "lsp": { + "rust-analyzer": { + "initialization_options": { + "cargo": { + "buildScripts": { + "enable": true, + "invocationLocation": "root", + "invocationStrategy": "once", + "overrideCommand": ["python3", "x.py", "check", "--json-output"] + }, + "extraEnv": { + "RUSTC_BOOTSTRAP": "1" + }, + "sysrootSrc": "./library" + }, + "check": { + "invocationLocation": "root", + "invocationStrategy": "once", + "overrideCommand": ["python3", "x.py", "check", "--json-output"] + }, + "linkedProjects": [ + "Cargo.toml", + "library/Cargo.toml", + "src/tools/x/Cargo.toml", + "src/bootstrap/Cargo.toml", + "src/tools/rust-analyzer/Cargo.toml", + "compiler/rustc_codegen_cranelift/Cargo.toml", + "compiler/rustc_codegen_gcc/Cargo.toml" + ], + "procMacro": { + "enable": true, + "server": "${workspaceFolder}/build/host/stage0/libexec/rust-analyzer-proc-macro-srv" + }, + "rustc": { + "source": "./Cargo.toml" + }, + "rustfmt": { + "overrideCommand": [ + "${workspaceFolder}/build/host/rustfmt/bin/rustfmt", + "--edition=2021" + ] + }, + "server": { + "extraEnv": { + "RUSTUP_TOOLCHAIN": "nightly" + } + } + } + } + } +} From 841768422827b76b1b52abea9fd46c451e6aa613 Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Sat, 15 Feb 2025 18:30:50 -0500 Subject: [PATCH 07/16] Check all IDE config hashes in `./x test bootstrap`, update Helix hash --- src/bootstrap/src/core/build_steps/setup.rs | 17 ++++++++++++--- .../src/core/build_steps/setup/tests.rs | 21 +++++++++++-------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index 523f688bd914f..f25dfaab0f115 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -531,6 +531,16 @@ enum EditorKind { } impl EditorKind { + // Used in `./tests.rs`. + #[allow(dead_code)] + pub const ALL: &[EditorKind] = &[ + EditorKind::Emacs, + EditorKind::Helix, + EditorKind::Vim, + EditorKind::VsCode, + EditorKind::Zed, + ]; + fn prompt_user() -> io::Result> { let prompt_str = "Available editors: 1. Emacs @@ -575,9 +585,10 @@ Select which editor you would like to set up [default: None]: "; "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0", "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45", ], - EditorKind::Helix => { - &["2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233"] - } + EditorKind::Helix => &[ + "2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233", + "6736d61409fbebba0933afd2e4c44ff2f97c1cb36cf0299a7f4a7819b8775040", + ], EditorKind::Vim | EditorKind::VsCode => &[ "ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8", "56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922", diff --git a/src/bootstrap/src/core/build_steps/setup/tests.rs b/src/bootstrap/src/core/build_steps/setup/tests.rs index f3d4b6aa4db6e..e8f83ff75e404 100644 --- a/src/bootstrap/src/core/build_steps/setup/tests.rs +++ b/src/bootstrap/src/core/build_steps/setup/tests.rs @@ -5,13 +5,16 @@ use crate::utils::helpers::hex_encode; #[test] fn check_matching_settings_hash() { - let editor = EditorKind::Vscode; - let mut hasher = sha2::Sha256::new(); - hasher.update(&editor.settings_template()); - let hash = hex_encode(hasher.finalize().as_slice()); - assert_eq!( - &hash, - editor.hashes().last().unwrap(), - "Update `EditorKind::hashes()` with the new hash of `src/etc/rust_analyzer_settings.json`" - ); + for editor in EditorKind::ALL { + let mut hasher = sha2::Sha256::new(); + hasher.update(&editor.settings_template()); + let hash = hex_encode(hasher.finalize().as_slice()); + assert_eq!( + &hash, + editor.hashes().last().unwrap(), + "Update `EditorKind::hashes()` with the new hash of `{}` for `EditorKind::{:?}`", + editor.settings_template(), + editor, + ); + } } From 410331c74c3dbb360633ca6127caaf5edca7d89e Mon Sep 17 00:00:00 2001 From: "Chai T. Rex" Date: Mon, 17 Feb 2025 23:48:39 -0500 Subject: [PATCH 08/16] Add Zed to dev guide suggested workflows page --- src/doc/rustc-dev-guide/src/building/suggested.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 2c6c3fe1df84b..5c041d6cb70f9 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -154,6 +154,16 @@ You can run `./x setup editor` and select `helix`, which will prompt you to create `languages.toml` with the recommended configuration for Helix. The recommended settings live at [`src/etc/rust_analyzer_helix.toml`]. +### Zed + +Zed comes with built-in LSP and rust-analyzer support. +It can be configured through `.zed/settings.json`, as described +[here](https://zed.dev/docs/configuring-languages). Selecting `zed` +in `./x setup editor` will prompt you to create a `.zed/settings.json` +file which will configure Zed with the recommended configuration. The +recommended `rust-analyzer` settings live +at [`src/etc/rust_analyzer_zed.json`]. + ## Check, check, and check again When doing simple refactoring, it can be useful to run `./x check` @@ -381,4 +391,5 @@ load this completion. [`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json [`src/etc/rust_analyzer_eglot.el`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_eglot.el [`src/etc/rust_analyzer_helix.toml`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_helix.toml +[`src/etc/rust_analyzer_zed.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_zed.json [`src/etc/pre-push.sh`]: https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh From aecde199adeed94f79c612bb380e76e8775a6653 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 18 Feb 2025 10:28:36 -0600 Subject: [PATCH 09/16] docs(dev): Remove reference to features_untracked This was removed in #114723 --- src/doc/rustc-dev-guide/src/implementing_new_features.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index 5b67ccd7f4c5e..c77b872cf5c1a 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -167,9 +167,7 @@ a new unstable feature: 1. Prevent usage of the new feature unless the feature gate is set. You can check it in most places in the compiler using the - expression `tcx.features().$feature_name` (or - `sess.features_untracked().$feature_name` if the - tcx is unavailable) + expression `tcx.features().$feature_name` If the feature gate is not set, you should either maintain the pre-feature behavior or raise an error, depending on From 5e92241b618714adaa3894afc992b648ba5889a8 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Tue, 18 Feb 2025 10:35:13 -0600 Subject: [PATCH 10/16] docs(dev): Access features as functions, not members This was changed in #132027 --- src/doc/rustc-dev-guide/src/implementing_new_features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index c77b872cf5c1a..fda38ef4fc01a 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -167,7 +167,7 @@ a new unstable feature: 1. Prevent usage of the new feature unless the feature gate is set. You can check it in most places in the compiler using the - expression `tcx.features().$feature_name` + expression `tcx.features().$feature_name()` If the feature gate is not set, you should either maintain the pre-feature behavior or raise an error, depending on From 6eb48824dac44b466ca03fe67760a63d8a45d1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2025 17:34:16 +0000 Subject: [PATCH 11/16] Don't mention `FromResidual` on bad `?` Unless `try_trait_v2` is enabled, don't mention that `FromResidual` isn't implemented for a specific type when the implicit `From` conversion of a `?` fails. For the end user on stable, `?` might as well be a compiler intrinsic, so we remove that note to avoid further confusion and allowing other parts of the error to be more prominent. ``` error[E0277]: `?` couldn't convert the error to `u8` --> $DIR/bad-interconversion.rs:4:20 | LL | fn result_to_result() -> Result { | --------------- expected `u8` because of this LL | Ok(Err(123_i32)?) | ------------^ the trait `From` is not implemented for `u8` | | | this can't be annotated with `?` because it has type `Result<_, i32>` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait = help: the following other types implement trait `From`: `u8` implements `From` `u8` implements `From` ``` --- .../src/error_reporting/traits/suggestions.rs | 8 ++++++++ tests/ui/traits/question-mark-result-err-mismatch.rs | 1 + tests/ui/traits/question-mark-result-err-mismatch.stderr | 6 +++--- tests/ui/try-block/try-block-bad-type.stderr | 1 - tests/ui/try-trait/bad-interconversion.stderr | 1 - tests/ui/try-trait/issue-32709.stderr | 1 - 6 files changed, 12 insertions(+), 6 deletions(-) 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 527d2e54e4327..94d652a0e98f7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3293,6 +3293,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut parent_trait_pred = self.resolve_vars_if_possible(data.derived.parent_trait_pred); let parent_def_id = parent_trait_pred.def_id(); + if tcx.is_diagnostic_item(sym::FromResidual, parent_def_id) + && !tcx.features().enabled(sym::try_trait_v2) + { + // If `#![feature(try_trait_v2)]` is not enabled, then there's no point on + // talking about `FromResidual>`, as the end user has nothing they + // can do about it. As far as they are concerned, `?` is compiler magic. + return; + } let self_ty_str = tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path()); let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string(); diff --git a/tests/ui/traits/question-mark-result-err-mismatch.rs b/tests/ui/traits/question-mark-result-err-mismatch.rs index 0ca18b5b0ddce..df1d5105a34a1 100644 --- a/tests/ui/traits/question-mark-result-err-mismatch.rs +++ b/tests/ui/traits/question-mark-result-err-mismatch.rs @@ -1,3 +1,4 @@ +#![feature(try_trait_v2)] fn foo() -> Result { //~ NOTE expected `String` because of this let test = String::from("one,two"); let x = test diff --git a/tests/ui/traits/question-mark-result-err-mismatch.stderr b/tests/ui/traits/question-mark-result-err-mismatch.stderr index bad325a672042..0f83c9e73a314 100644 --- a/tests/ui/traits/question-mark-result-err-mismatch.stderr +++ b/tests/ui/traits/question-mark-result-err-mismatch.stderr @@ -1,5 +1,5 @@ error[E0277]: `?` couldn't convert the error to `String` - --> $DIR/question-mark-result-err-mismatch.rs:14:22 + --> $DIR/question-mark-result-err-mismatch.rs:15:22 | LL | fn foo() -> Result { | ---------------------- expected `String` because of this @@ -17,7 +17,7 @@ LL | .map(|()| "")?; = note: required for `Result` to implement `FromResidual>` error[E0277]: `?` couldn't convert the error to `String` - --> $DIR/question-mark-result-err-mismatch.rs:28:25 + --> $DIR/question-mark-result-err-mismatch.rs:29:25 | LL | fn bar() -> Result<(), String> { | ------------------ expected `String` because of this @@ -40,7 +40,7 @@ LL | .map_err(|_| ())?; = note: required for `Result<(), String>` to implement `FromResidual>` error[E0277]: `?` couldn't convert the error to `String` - --> $DIR/question-mark-result-err-mismatch.rs:48:11 + --> $DIR/question-mark-result-err-mismatch.rs:49:11 | LL | fn baz() -> Result { | ---------------------- expected `String` because of this diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr index c67ad762a83b9..818ab499306f0 100644 --- a/tests/ui/try-block/try-block-bad-type.stderr +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -10,7 +10,6 @@ LL | Err("")?; = help: the trait `From<&str>` is not implemented for `TryFromSliceError` but trait `From` is implemented for it = help: for that trait implementation, expected `Infallible`, found `&str` - = note: required for `Result` to implement `FromResidual>` error[E0271]: type mismatch resolving ` as Try>::Output == &str` --> $DIR/try-block-bad-type.rs:12:9 diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index bb5e5646ad294..45422be946e82 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -12,7 +12,6 @@ LL | Ok(Err(123_i32)?) = help: the following other types implement trait `From`: `u8` implements `From` `u8` implements `From` - = note: required for `Result` to implement `FromResidual>` error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` --> $DIR/bad-interconversion.rs:9:12 diff --git a/tests/ui/try-trait/issue-32709.stderr b/tests/ui/try-trait/issue-32709.stderr index 475bd1ff3ac57..20454e12de558 100644 --- a/tests/ui/try-trait/issue-32709.stderr +++ b/tests/ui/try-trait/issue-32709.stderr @@ -19,7 +19,6 @@ LL | Err(5)?; `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>` `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>` and 4 others - = note: required for `Result` to implement `FromResidual>` error: aborting due to 1 previous error From d9b91de00c3716e577aeb02929bee69f8028f3a0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 19 Feb 2025 00:56:54 +1100 Subject: [PATCH 12/16] coverage: Add some more cases to `tests/coverage/holes.rs` --- tests/coverage/holes.cov-map | 31 +++++++++++++++----------- tests/coverage/holes.coverage | 41 +++++++++++++++++++++++++++++++---- tests/coverage/holes.rs | 33 ++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 17 deletions(-) diff --git a/tests/coverage/holes.cov-map b/tests/coverage/holes.cov-map index 3c740d80ea05a..3deacbc8e1287 100644 --- a/tests/coverage/holes.cov-map +++ b/tests/coverage/holes.cov-map @@ -1,52 +1,57 @@ Function name: ::_method (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 25, 09, 00, 1d] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 2b, 09, 00, 1d] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 37, 9) to (start + 0, 29) +- Code(Zero) at (prev + 43, 9) to (start + 0, 29) Highest counter ID seen: (none) Function name: holes::main -Raw bytes (44): 0x[01, 01, 00, 08, 01, 08, 01, 06, 11, 01, 0f, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 01, 02] +Raw bytes (69): 0x[01, 01, 00, 0d, 01, 08, 01, 01, 12, 01, 05, 05, 00, 12, 01, 07, 09, 00, 11, 01, 09, 05, 00, 12, 01, 04, 05, 00, 12, 01, 07, 05, 00, 12, 01, 06, 05, 00, 12, 01, 04, 05, 00, 12, 01, 04, 05, 00, 12, 01, 06, 05, 03, 0f, 01, 0a, 05, 03, 0f, 01, 0a, 05, 0c, 0d, 01, 0f, 0e, 05, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 -Number of file 0 mappings: 8 -- Code(Counter(0)) at (prev + 8, 1) to (start + 6, 17) -- Code(Counter(0)) at (prev + 15, 5) to (start + 0, 18) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 18) +- Code(Counter(0)) at (prev + 5, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 7, 9) to (start + 0, 17) +- Code(Counter(0)) at (prev + 9, 5) to (start + 0, 18) - Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) - Code(Counter(0)) at (prev + 7, 5) to (start + 0, 18) - Code(Counter(0)) at (prev + 6, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) +- Code(Counter(0)) at (prev + 4, 5) to (start + 0, 18) - Code(Counter(0)) at (prev + 6, 5) to (start + 3, 15) - Code(Counter(0)) at (prev + 10, 5) to (start + 3, 15) -- Code(Counter(0)) at (prev + 10, 5) to (start + 1, 2) +- Code(Counter(0)) at (prev + 10, 5) to (start + 12, 13) +- Code(Counter(0)) at (prev + 15, 14) to (start + 5, 2) Highest counter ID seen: c0 Function name: holes::main::_unused_fn (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 19, 05, 00, 17] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 1f, 05, 00, 17] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 25, 5) to (start + 0, 23) +- Code(Zero) at (prev + 31, 5) to (start + 0, 23) Highest counter ID seen: (none) Function name: holes::main::{closure#0} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 12, 09, 02, 0a] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 18, 09, 02, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 18, 9) to (start + 2, 10) +- Code(Zero) at (prev + 24, 9) to (start + 2, 10) Highest counter ID seen: (none) Function name: holes::main::{closure#1} (unused) -Raw bytes (9): 0x[01, 01, 00, 01, 00, 3d, 09, 02, 0a] +Raw bytes (9): 0x[01, 01, 00, 01, 00, 4b, 09, 02, 0a] Number of files: 1 - file 0 => global file 1 Number of expressions: 0 Number of file 0 mappings: 1 -- Code(Zero) at (prev + 61, 9) to (start + 2, 10) +- Code(Zero) at (prev + 75, 9) to (start + 2, 10) Highest counter ID seen: (none) diff --git a/tests/coverage/holes.coverage b/tests/coverage/holes.coverage index 6e65435f7e3fd..1b45c12156ae7 100644 --- a/tests/coverage/holes.coverage +++ b/tests/coverage/holes.coverage @@ -7,10 +7,16 @@ LL| | LL| 1|fn main() { LL| 1| black_box(()); - LL| 1| - LL| 1| // Splitting this across multiple lines makes it easier to see where the - LL| 1| // coverage mapping regions begin and end. - LL| 1| #[rustfmt::skip] + LL| | + LL| | static MY_STATIC: () = (); + LL| | + LL| 1| black_box(()); + LL| | + LL| | const MY_CONST: () = (); + LL| | + LL| | // Splitting this across multiple lines makes it easier to see where the + LL| | // coverage mapping regions begin and end. + LL| | #[rustfmt::skip] LL| 1| let _closure = LL| | | LL| | _arg: (), @@ -39,6 +45,14 @@ LL| | LL| 1| black_box(()); LL| | + LL| | trait MyTrait {} + LL| | + LL| 1| black_box(()); + LL| | + LL| | impl MyTrait for MyStruct {} + LL| | + LL| 1| black_box(()); + LL| | LL| | macro_rules! _my_macro { LL| | () => {}; LL| | } @@ -64,5 +78,24 @@ LL| | ; LL| | LL| 1| black_box(()); + LL| 1| + LL| 1| // This tests the edge case of a const block nested inside an "anon const", + LL| 1| // such as the length of an array literal. Handling this case requires + LL| 1| // `nested_filter::OnlyBodies` or equivalent. + LL| 1| #[rustfmt::skip] + LL| 1| let _const_block_inside_anon_const = + LL| 1| [ + LL| 1| 0 + LL| 1| ; + LL| 1| 7 + LL| 1| + + LL| 1| const + LL| | { + LL| | 3 + LL| 1| } + LL| 1| ] + LL| 1| ; + LL| 1| + LL| 1| black_box(()); LL| 1|} diff --git a/tests/coverage/holes.rs b/tests/coverage/holes.rs index b3a71e759c830..7f6671772c323 100644 --- a/tests/coverage/holes.rs +++ b/tests/coverage/holes.rs @@ -8,6 +8,12 @@ use core::hint::black_box; fn main() { black_box(()); + static MY_STATIC: () = (); + + black_box(()); + + const MY_CONST: () = (); + // Splitting this across multiple lines makes it easier to see where the // coverage mapping regions begin and end. #[rustfmt::skip] @@ -39,6 +45,14 @@ fn main() { black_box(()); + trait MyTrait {} + + black_box(()); + + impl MyTrait for MyStruct {} + + black_box(()); + macro_rules! _my_macro { () => {}; } @@ -64,4 +78,23 @@ fn main() { ; black_box(()); + + // This tests the edge case of a const block nested inside an "anon const", + // such as the length of an array literal. Handling this case requires + // `nested_filter::OnlyBodies` or equivalent. + #[rustfmt::skip] + let _const_block_inside_anon_const = + [ + 0 + ; + 7 + + + const + { + 3 + } + ] + ; + + black_box(()); } From 51f704f0ff22965d6f21cc7e6888d55e5141932d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 19 Feb 2025 00:54:47 +1100 Subject: [PATCH 13/16] coverage: Get hole spans from nested items without fully visiting them It turns out that this visitor doesn't actually need `nested_filter::All` to handle nested items; it just needs to override `visit_nested_item` and look up the item's span. --- .../rustc_mir_transform/src/coverage/mod.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 264995efe8fa7..774f47a35aa46 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -352,19 +352,20 @@ fn extract_hole_spans_from_hir<'tcx>( } impl<'hir, F: FnMut(Span)> Visitor<'hir> for HolesVisitor<'hir, F> { - /// - We need `NestedFilter::INTRA = true` so that `visit_item` will be called. - /// - Bodies of nested items don't actually get visited, because of the - /// `visit_item` override. - /// - For nested bodies that are not part of an item, we do want to visit any - /// items contained within them. - type NestedFilter = nested_filter::All; + /// We have special handling for nested items, but we still want to + /// traverse into nested bodies of things that are not considered items, + /// such as "anon consts" (e.g. array lengths). + type NestedFilter = nested_filter::OnlyBodies; fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { self.tcx } - fn visit_item(&mut self, item: &'hir hir::Item<'hir>) { - (self.visit_hole_span)(item.span); + /// We override `visit_nested_item` instead of `visit_item` because we + /// only need the item's span, not the item itself. + fn visit_nested_item(&mut self, id: hir::ItemId) -> Self::Result { + let span = self.tcx.def_span(id.owner_id.def_id); + (self.visit_hole_span)(span); // Having visited this item, we don't care about its children, // so don't call `walk_item`. } From d38f6880c029cd71a4ce1bc6be783741767d10c3 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 19 Feb 2025 01:22:28 +1100 Subject: [PATCH 14/16] coverage: Make `HolesVisitor::visit_hole_span` a regular method --- .../rustc_mir_transform/src/coverage/mod.rs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 774f47a35aa46..1ccae0fd7fe95 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -346,18 +346,19 @@ fn extract_hole_spans_from_hir<'tcx>( body_span: Span, // Usually `hir_body.value.span`, but not always hir_body: &hir::Body<'tcx>, ) -> Vec { - struct HolesVisitor<'hir, F> { - tcx: TyCtxt<'hir>, - visit_hole_span: F, + struct HolesVisitor<'tcx> { + tcx: TyCtxt<'tcx>, + body_span: Span, + hole_spans: Vec, } - impl<'hir, F: FnMut(Span)> Visitor<'hir> for HolesVisitor<'hir, F> { + impl<'tcx> Visitor<'tcx> for HolesVisitor<'tcx> { /// We have special handling for nested items, but we still want to /// traverse into nested bodies of things that are not considered items, /// such as "anon consts" (e.g. array lengths). type NestedFilter = nested_filter::OnlyBodies; - fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt { + fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { self.tcx } @@ -365,17 +366,17 @@ fn extract_hole_spans_from_hir<'tcx>( /// only need the item's span, not the item itself. fn visit_nested_item(&mut self, id: hir::ItemId) -> Self::Result { let span = self.tcx.def_span(id.owner_id.def_id); - (self.visit_hole_span)(span); + self.visit_hole_span(span); // Having visited this item, we don't care about its children, // so don't call `walk_item`. } // We override `visit_expr` instead of the more specific expression // visitors, so that we have direct access to the expression span. - fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) { + fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) { match expr.kind { hir::ExprKind::Closure(_) | hir::ExprKind::ConstBlock(_) => { - (self.visit_hole_span)(expr.span); + self.visit_hole_span(expr.span); // Having visited this expression, we don't care about its // children, so don't call `walk_expr`. } @@ -385,18 +386,17 @@ fn extract_hole_spans_from_hir<'tcx>( } } } - - let mut hole_spans = vec![]; - let mut visitor = HolesVisitor { - tcx, - visit_hole_span: |hole_span| { + impl HolesVisitor<'_> { + fn visit_hole_span(&mut self, hole_span: Span) { // Discard any holes that aren't directly visible within the body span. - if body_span.contains(hole_span) && body_span.eq_ctxt(hole_span) { - hole_spans.push(hole_span); + if self.body_span.contains(hole_span) && self.body_span.eq_ctxt(hole_span) { + self.hole_spans.push(hole_span); } - }, - }; + } + } + + let mut visitor = HolesVisitor { tcx, body_span, hole_spans: vec![] }; visitor.visit_body(hir_body); - hole_spans + visitor.hole_spans } From 73b6482ead710656c14fbb86011aa0e7d65461fd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 18 Feb 2025 14:21:29 +0100 Subject: [PATCH 15/16] x86_win64 ABI: do not use xmm0 with softfloat ABI --- .../rustc_target/src/callconv/x86_win64.rs | 16 +++++--- tests/assembly/x86_64-windows-i128-abi.rs | 26 +++++++++++++ tests/codegen/i128-x86-callconv.rs | 38 +++++++++++-------- 3 files changed, 59 insertions(+), 21 deletions(-) create mode 100644 tests/assembly/x86_64-windows-i128-abi.rs diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs index 23ef2cf828409..2ef5127de04ae 100644 --- a/compiler/rustc_target/src/callconv/x86_win64.rs +++ b/compiler/rustc_target/src/callconv/x86_win64.rs @@ -1,11 +1,11 @@ use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind, Size}; use crate::callconv::{ArgAbi, FnAbi, Reg}; -use crate::spec::HasTargetSpec; +use crate::spec::{HasTargetSpec, RustcAbi}; // Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing -pub(crate) fn compute_abi_info(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { +pub(crate) fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| { match a.layout.backend_repr { BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {} @@ -24,10 +24,14 @@ pub(crate) fn compute_abi_info(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi< } BackendRepr::Scalar(scalar) => { 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); + if cx.target_spec().rustc_abi == Some(RustcAbi::X86Softfloat) { + // Use the native `i128` LLVM type for the softfloat ABI -- in other words, adjust nothing. + } else { + // `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)) { diff --git a/tests/assembly/x86_64-windows-i128-abi.rs b/tests/assembly/x86_64-windows-i128-abi.rs new file mode 100644 index 0000000000000..d2aefb7daa640 --- /dev/null +++ b/tests/assembly/x86_64-windows-i128-abi.rs @@ -0,0 +1,26 @@ +//@ assembly-output: emit-asm +//@ add-core-stubs +//@ revisions: msvc softfloat +//@ compile-flags: -Copt-level=3 +//@[msvc] compile-flags: --target x86_64-pc-windows-msvc +//@[msvc] needs-llvm-components: x86 +//@[softfloat] compile-flags: --target x86_64-unknown-uefi +//@[softfloat] needs-llvm-components: x86 + +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +// CHECK-LABEL: ret_i128 +// Hardfloat targets return via xmm0, softfloat targets via rax and rdx. +// msvc: movaps {{.*}}, %xmm0 +// softfloat: movq (%[[INPUT:.*]]), %rax +// softfloat-NEXT: movq 8(%[[INPUT]]), %rdx +// CHECK-NEXT: retq +#[no_mangle] +pub extern "C" fn ret_i128(x: &i128) -> i128 { + *x +} diff --git a/tests/codegen/i128-x86-callconv.rs b/tests/codegen/i128-x86-callconv.rs index 9a9c9002fc026..41c30c09c1ac4 100644 --- a/tests/codegen/i128-x86-callconv.rs +++ b/tests/codegen/i128-x86-callconv.rs @@ -4,13 +4,18 @@ //@ compile-flags: -Copt-level=1 //@ add-core-stubs -//@ revisions: MSVC MINGW +//@ revisions: MSVC MINGW softfloat //@ [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 +// Use `WIN` as a common prefix for MSVC and MINGW but *not* the softfloat test. //@ [MSVC] filecheck-flags: --check-prefix=WIN +//@ [MINGW] needs-llvm-components: x86 +//@ [MINGW] compile-flags: --target x86_64-pc-windows-gnu //@ [MINGW] filecheck-flags: --check-prefix=WIN +// The `x86_64-unknown-uefi` target also uses the Windows calling convention, +// but does not have SSE registers available. +//@ [softfloat] needs-llvm-components: x86 +//@ [softfloat] compile-flags: --target x86_64-unknown-uefi #![crate_type = "lib"] #![no_std] @@ -28,24 +33,26 @@ extern "C" { 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 + // a pointer to that allocation. The softfloat ABI works the same. + // CHECK-SAME: %_arg0, ptr{{.*}} %arg1) + // CHECK: [[PASS:%[_0-9]+]] = alloca [16 x i8], align 16 + // CHECK: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1 + // CHECK: store i128 [[LOADED]], ptr [[PASS]] + // CHECK: 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( + // WIN-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]] + // The softfloat ABI returns this indirectly. + // softfloat-LABEL: i128 @ret(i32{{.*}} %_arg0, ptr{{.*}} %arg1) arg1 } @@ -57,6 +64,7 @@ pub extern "C" fn forward(dst: *mut i128) { // WIN: [[RETURNED:%[_0-9]+]] = tail call <16 x i8> @extern_ret() // WIN: store <16 x i8> [[RETURNED]], ptr %dst // WIN: ret void + // softfloat: [[RETURNED:%[_0-9]+]] = tail call {{.*}}i128 @extern_ret() unsafe { *dst = extern_ret() }; } @@ -70,10 +78,10 @@ struct RetAggregate { 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 + // CHECK-SAME: ptr{{.*}}sret([32 x i8]){{.*}}[[RET:%[_0-9]+]], i32{{.*}}%_arg0, ptr{{.*}}%arg1) + // CHECK: [[LOADED:%[_0-9]+]] = load i128, ptr %arg1 + // CHECK: [[GEP:%[_0-9]+]] = getelementptr{{.*}}, ptr [[RET]] + // CHECK: store i128 [[LOADED]], ptr [[GEP]] + // CHECK: ret void RetAggregate { a: 1, b: arg1 } } From 3ad847779ec12875a96c563dadb63493b28856c0 Mon Sep 17 00:00:00 2001 From: Tommaso Allevi Date: Wed, 19 Feb 2025 09:17:18 +0100 Subject: [PATCH 16/16] Update library/std/src/fs.rs Co-authored-by: Amanieu d'Antras --- library/std/src/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 5631c3e0156cf..2aa00c0c29483 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -2505,7 +2505,7 @@ pub fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> /// * `from` does not exist. /// * The current process does not have the permission rights to read /// `from` or write `to`. -/// * The parent folder of `to` doesn't exists +/// * The parent directory of `to` doesn't exist. /// /// # Examples ///