From e0421f8f61cbc6e84c3cabf22999424f4eb0e9f4 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 14 May 2025 07:31:56 +0000 Subject: [PATCH 01/15] replace `cc_detect::cc2ar` with `cc::try_get_archiver` Signed-off-by: onur-ozkan --- src/bootstrap/src/utils/cc_detect.rs | 34 +------ src/bootstrap/src/utils/cc_detect/tests.rs | 113 --------------------- 2 files changed, 2 insertions(+), 145 deletions(-) diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index ceac24d4315c7..5c9e30706ee0d 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -22,43 +22,13 @@ //! everything. use std::collections::HashSet; +use std::iter; use std::path::{Path, PathBuf}; -use std::{env, iter}; use crate::core::config::TargetSelection; use crate::utils::exec::{BootstrapCommand, command}; use crate::{Build, CLang, GitRepo}; -/// Finds archiver tool for the given target if possible. -/// FIXME(onur-ozkan): This logic should be replaced by calling into the `cc` crate. -fn cc2ar(cc: &Path, target: TargetSelection, default_ar: PathBuf) -> Option { - if let Some(ar) = env::var_os(format!("AR_{}", target.triple.replace('-', "_"))) { - Some(PathBuf::from(ar)) - } else if let Some(ar) = env::var_os("AR") { - Some(PathBuf::from(ar)) - } else if target.is_msvc() { - None - } else if target.contains("musl") || target.contains("openbsd") { - Some(PathBuf::from("ar")) - } else if target.contains("vxworks") { - Some(PathBuf::from("wr-ar")) - } else if target.contains("-nto-") { - if target.starts_with("i586") { - Some(PathBuf::from("ntox86-ar")) - } else if target.starts_with("aarch64") { - Some(PathBuf::from("ntoaarch64-ar")) - } else if target.starts_with("x86_64") { - Some(PathBuf::from("ntox86_64-ar")) - } else { - panic!("Unknown architecture, cannot determine archiver for Neutrino QNX"); - } - } else if target.contains("android") || target.contains("-wasi") { - Some(cc.parent().unwrap().join(PathBuf::from("llvm-ar"))) - } else { - Some(default_ar) - } -} - /// Creates and configures a new [`cc::Build`] instance for the given target. fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build { let mut cfg = cc::Build::new(); @@ -140,7 +110,7 @@ pub fn find_target(build: &Build, target: TargetSelection) { let ar = if let ar @ Some(..) = config.and_then(|c| c.ar.clone()) { ar } else { - cc2ar(compiler.path(), target, PathBuf::from(cfg.get_archiver().get_program())) + cfg.try_get_archiver().map(|c| PathBuf::from(c.get_program())).ok() }; build.cc.borrow_mut().insert(target, compiler.clone()); diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs index 43d61ce02c5af..225fb7619b55a 100644 --- a/src/bootstrap/src/utils/cc_detect/tests.rs +++ b/src/bootstrap/src/utils/cc_detect/tests.rs @@ -5,119 +5,6 @@ use super::*; use crate::core::config::{Target, TargetSelection}; use crate::{Build, Config, Flags}; -#[test] -fn test_cc2ar_env_specific() { - let triple = "x86_64-unknown-linux-gnu"; - let key = "AR_x86_64_unknown_linux_gnu"; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::set_var(key, "custom-ar") }; - let target = TargetSelection::from_user(triple); - let cc = Path::new("/usr/bin/clang"); - let default_ar = PathBuf::from("default-ar"); - let result = cc2ar(cc, target, default_ar); - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var(key) }; - assert_eq!(result, Some(PathBuf::from("custom-ar"))); -} - -#[test] -fn test_cc2ar_musl() { - let triple = "x86_64-unknown-linux-musl"; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR_x86_64_unknown_linux_musl") }; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR") }; - let target = TargetSelection::from_user(triple); - let cc = Path::new("/usr/bin/clang"); - let default_ar = PathBuf::from("default-ar"); - let result = cc2ar(cc, target, default_ar); - assert_eq!(result, Some(PathBuf::from("ar"))); -} - -#[test] -fn test_cc2ar_openbsd() { - let triple = "x86_64-unknown-openbsd"; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR_x86_64_unknown_openbsd") }; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR") }; - let target = TargetSelection::from_user(triple); - let cc = Path::new("/usr/bin/cc"); - let default_ar = PathBuf::from("default-ar"); - let result = cc2ar(cc, target, default_ar); - assert_eq!(result, Some(PathBuf::from("ar"))); -} - -#[test] -fn test_cc2ar_vxworks() { - let triple = "armv7-wrs-vxworks"; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR_armv7_wrs_vxworks") }; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR") }; - let target = TargetSelection::from_user(triple); - let cc = Path::new("/usr/bin/clang"); - let default_ar = PathBuf::from("default-ar"); - let result = cc2ar(cc, target, default_ar); - assert_eq!(result, Some(PathBuf::from("wr-ar"))); -} - -#[test] -fn test_cc2ar_nto_i586() { - let triple = "i586-unknown-nto-something"; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR_i586_unknown_nto_something") }; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR") }; - let target = TargetSelection::from_user(triple); - let cc = Path::new("/usr/bin/clang"); - let default_ar = PathBuf::from("default-ar"); - let result = cc2ar(cc, target, default_ar); - assert_eq!(result, Some(PathBuf::from("ntox86-ar"))); -} - -#[test] -fn test_cc2ar_nto_aarch64() { - let triple = "aarch64-unknown-nto-something"; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR_aarch64_unknown_nto_something") }; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR") }; - let target = TargetSelection::from_user(triple); - let cc = Path::new("/usr/bin/clang"); - let default_ar = PathBuf::from("default-ar"); - let result = cc2ar(cc, target, default_ar); - assert_eq!(result, Some(PathBuf::from("ntoaarch64-ar"))); -} - -#[test] -fn test_cc2ar_nto_x86_64() { - let triple = "x86_64-unknown-nto-something"; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR_x86_64_unknown_nto_something") }; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR") }; - let target = TargetSelection::from_user(triple); - let cc = Path::new("/usr/bin/clang"); - let default_ar = PathBuf::from("default-ar"); - let result = cc2ar(cc, target, default_ar); - assert_eq!(result, Some(PathBuf::from("ntox86_64-ar"))); -} - -#[test] -#[should_panic(expected = "Unknown architecture, cannot determine archiver for Neutrino QNX")] -fn test_cc2ar_nto_unknown() { - let triple = "powerpc-unknown-nto-something"; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR_powerpc_unknown_nto_something") }; - // SAFETY: bootstrap tests run on a single thread - unsafe { env::remove_var("AR") }; - let target = TargetSelection::from_user(triple); - let cc = Path::new("/usr/bin/clang"); - let default_ar = PathBuf::from("default-ar"); - let _ = cc2ar(cc, target, default_ar); -} - #[test] fn test_ndk_compiler_c() { let ndk_path = PathBuf::from("/ndk"); From 5027ee27de1f633de12a23539c21db2873fc301a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 16 May 2025 18:08:20 +0000 Subject: [PATCH 02/15] bump bootstrap cc-rs to `1.2.23` Signed-off-by: onur-ozkan --- src/bootstrap/Cargo.lock | 4 ++-- src/bootstrap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index 05ab1b6eddefb..06ca8580896fa 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -89,9 +89,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.17" +version = "1.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" dependencies = [ "shlex", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index e34de924cc18a..b1466e4f15309 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -32,7 +32,7 @@ test = false # Most of the time updating these dependencies requires modifications to the # bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565); # otherwise, some targets will fail. That's why these dependencies are explicitly pinned. -cc = "=1.2.17" +cc = "=1.2.23" cmake = "=0.1.54" build_helper = { path = "../build_helper" } From fe0663c33d24c903812ec0fe58b94d68aa275b98 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Sun, 18 May 2025 15:53:03 +0800 Subject: [PATCH 03/15] Add test sugg-field-in-format-string-issue-141136 Signed-off-by: xizheyin --- ...ugg-field-in-format-string-issue-141136.rs | 14 ++++++ ...field-in-format-string-issue-141136.stderr | 46 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.rs create mode 100644 tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr diff --git a/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.rs b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.rs new file mode 100644 index 0000000000000..e0c2f49604617 --- /dev/null +++ b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.rs @@ -0,0 +1,14 @@ +struct Foo { + x: i32 +} + +impl Foo { + fn foo(&self) { + let _ = format!("{x}"); //~ ERROR cannot find value `x` in this scope [E0425] + let _ = format!("{x }"); //~ ERROR cannot find value `x` in this scope [E0425] + let _ = format!("{ x}"); //~ ERROR invalid format string: expected `}`, found `x` + let _ = format!("{}", x); //~ ERROR cannot find value `x` in this scope [E0425] + } +} + +fn main(){} diff --git a/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr new file mode 100644 index 0000000000000..4bdefa70a0004 --- /dev/null +++ b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr @@ -0,0 +1,46 @@ +error: invalid format string: expected `}`, found `x` + --> $DIR/sugg-field-in-format-string-issue-141136.rs:9:28 + | +LL | let _ = format!("{ x}"); + | - ^ expected `}` in format string + | | + | because of this opening brace + | + = note: if you intended to print `{`, you can escape it using `{{` + +error[E0425]: cannot find value `x` in this scope + --> $DIR/sugg-field-in-format-string-issue-141136.rs:7:27 + | +LL | let _ = format!("{x}"); + | ^ + | +help: you might have meant to use the available field + | +LL | let _ = format!("{self.x}"); + | +++++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/sugg-field-in-format-string-issue-141136.rs:8:27 + | +LL | let _ = format!("{x }"); + | ^^ + | +help: you might have meant to use the available field + | +LL | let _ = format!("{self.x }"); + | +++++ + +error[E0425]: cannot find value `x` in this scope + --> $DIR/sugg-field-in-format-string-issue-141136.rs:10:31 + | +LL | let _ = format!("{}", x); + | ^ + | +help: you might have meant to use the available field + | +LL | let _ = format!("{}", self.x); + | +++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0425`. From 9de7fff0d8ab72fb57dea6255fc10fe35219db72 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Sun, 18 May 2025 16:14:48 +0800 Subject: [PATCH 04/15] Suggest use `"{}", self.x` instead of `{self.x}` when resolve `x` as field of `self` Signed-off-by: xizheyin --- .../rustc_resolve/src/late/diagnostics.rs | 30 +++++++++++++++---- ...field-in-format-string-issue-141136.stderr | 10 ++----- ...e-with-name-similar-to-struct-field.stderr | 12 ++------ 3 files changed, 28 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b538be34f31f1..30c2125d0b66a 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -751,12 +751,30 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { match candidate { AssocSuggestion::Field(field_span) => { if self_is_available { - err.span_suggestion_verbose( - span.shrink_to_lo(), - "you might have meant to use the available field", - format!("{pre}self."), - Applicability::MachineApplicable, - ); + let source_map = self.r.tcx.sess.source_map(); + // check if the field is used in a format string, such as `"{x}"` + let field_is_format_named_arg = + source_map.span_to_source(span, |s, start, _| { + if let Some(expanded_expr) = s.get(start - 1..start) + && expanded_expr.starts_with("{") + { + Ok(true) + } else { + Ok(false) + } + }); + if let Ok(true) = field_is_format_named_arg { + err.help( + format!("you might have meant to use the available field in a format string: `\"{{}}\", self.{}`", segment.ident.name), + ); + } else { + err.span_suggestion_verbose( + span.shrink_to_lo(), + "you might have meant to use the available field", + format!("{pre}self."), + Applicability::MachineApplicable, + ); + } } else { err.span_label(field_span, "a field by that name exists in `Self`"); } diff --git a/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr index 4bdefa70a0004..795de38d0279c 100644 --- a/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr +++ b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr @@ -14,10 +14,7 @@ error[E0425]: cannot find value `x` in this scope LL | let _ = format!("{x}"); | ^ | -help: you might have meant to use the available field - | -LL | let _ = format!("{self.x}"); - | +++++ + = help: you might have meant to use the available field in a format string: `"{}", self.x` error[E0425]: cannot find value `x` in this scope --> $DIR/sugg-field-in-format-string-issue-141136.rs:8:27 @@ -25,10 +22,7 @@ error[E0425]: cannot find value `x` in this scope LL | let _ = format!("{x }"); | ^^ | -help: you might have meant to use the available field - | -LL | let _ = format!("{self.x }"); - | +++++ + = help: you might have meant to use the available field in a format string: `"{}", self.x` error[E0425]: cannot find value `x` in this scope --> $DIR/sugg-field-in-format-string-issue-141136.rs:10:31 diff --git a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr index 5832cb69a3dd8..1ecbfee17bc70 100644 --- a/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr +++ b/tests/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr @@ -20,17 +20,9 @@ error[E0425]: cannot find value `config` in this scope --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:15:20 | LL | println!("{config}"); - | ^^^^^^ - | -help: you might have meant to use the available field - | -LL | println!("{self.config}"); - | +++++ -help: a local variable with a similar name exists - | -LL - println!("{config}"); -LL + println!("{cofig}"); + | ^^^^^^ help: a local variable with a similar name exists: `cofig` | + = help: you might have meant to use the available field in a format string: `"{}", self.config` error[E0425]: cannot find value `bah` in this scope --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:33:9 From 4ec991989af4662104fdbafc43b12232887fa0b4 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 20 May 2025 14:10:17 +0800 Subject: [PATCH 05/15] Add println! test for sugg-field-in-format-string-issue-141136 Signed-off-by: xizheyin --- .../sugg-field-in-format-string-issue-141136.rs | 1 + .../sugg-field-in-format-string-issue-141136.stderr | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.rs b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.rs index e0c2f49604617..d2aa61186bcd0 100644 --- a/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.rs +++ b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.rs @@ -8,6 +8,7 @@ impl Foo { let _ = format!("{x }"); //~ ERROR cannot find value `x` in this scope [E0425] let _ = format!("{ x}"); //~ ERROR invalid format string: expected `}`, found `x` let _ = format!("{}", x); //~ ERROR cannot find value `x` in this scope [E0425] + println!("{x}"); //~ ERROR cannot find value `x` in this scope [E0425] } } diff --git a/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr index 795de38d0279c..0a84848081d5c 100644 --- a/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr +++ b/tests/ui/resolve/suggestions/sugg-field-in-format-string-issue-141136.stderr @@ -35,6 +35,14 @@ help: you might have meant to use the available field LL | let _ = format!("{}", self.x); | +++++ -error: aborting due to 4 previous errors +error[E0425]: cannot find value `x` in this scope + --> $DIR/sugg-field-in-format-string-issue-141136.rs:11:20 + | +LL | println!("{x}"); + | ^ + | + = help: you might have meant to use the available field in a format string: `"{}", self.x` + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0425`. From 37260e1c5b920baf12ec0dd6755751d1783e27ed Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 20 May 2025 10:22:08 +0000 Subject: [PATCH 06/15] Allow trailing comma after argument in query definition --- compiler/rustc_macros/src/query.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index ee377277017a5..2196f71299a53 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -51,6 +51,7 @@ impl Parse for Query { let key = Pat::parse_single(&arg_content)?; arg_content.parse::()?; let arg = arg_content.parse()?; + let _ = arg_content.parse::>()?; let result = input.parse()?; // Parse the query modifiers From a3cf6f640828647e34afe96a626b3b4f6bbb22b1 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 27 Feb 2025 22:00:15 +0000 Subject: [PATCH 07/15] Add `std::os::unix::process::CommandExt::chroot` to safely chroot a child process This adds a `chroot` method to the `CommandExt` extension trait for the `Command` builder, to set a directory to chroot into. This will chroot the child process into that directory right before calling chdir for the `Command`'s working directory. To avoid allowing a process to have a working directory outside of the chroot, if the `Command` does not yet have a working directory set, `chroot` will set its working directory to "/". --- library/std/src/os/unix/process.rs | 16 ++++++++++++++++ library/std/src/sys/process/unix/common.rs | 13 +++++++++++++ library/std/src/sys/process/unix/unix.rs | 10 ++++++++++ library/std/src/sys/process/unix/vxworks.rs | 6 ++++++ 4 files changed, 45 insertions(+) diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 7c3fa7d6507e7..27866badfbe58 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -8,6 +8,7 @@ use cfg_if::cfg_if; use crate::ffi::OsStr; use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; +use crate::path::Path; use crate::sealed::Sealed; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::{io, process, sys}; @@ -197,6 +198,16 @@ pub trait CommandExt: Sealed { /// ``` #[stable(feature = "process_set_process_group", since = "1.64.0")] fn process_group(&mut self, pgroup: i32) -> &mut process::Command; + + /// Set the root of the child process. This calls `chroot` in the child process before executing + /// the command. + /// + /// This happens before changing to the directory specified with `Command::current_dir`, and + /// that directory will be relative to the new root. If no directory has been specified with + /// `Command::current_dir`, this will set the directory to `/`, to avoid leaving the current + /// directory outside the chroot. + #[unstable(feature = "process_chroot", issue = "none")] + fn chroot>(&mut self, dir: P) -> &mut process::Command; } #[stable(feature = "rust1", since = "1.0.0")] @@ -242,6 +253,11 @@ impl CommandExt for process::Command { self.as_inner_mut().pgroup(pgroup); self } + + fn chroot>(&mut self, dir: P) -> &mut process::Command { + self.as_inner_mut().chroot(dir.as_ref()); + self + } } /// Unix-specific extensions to [`process::ExitStatus`] and diff --git a/library/std/src/sys/process/unix/common.rs b/library/std/src/sys/process/unix/common.rs index a9c2510e6d454..e205a8390052f 100644 --- a/library/std/src/sys/process/unix/common.rs +++ b/library/std/src/sys/process/unix/common.rs @@ -88,6 +88,7 @@ pub struct Command { program_kind: ProgramKind, cwd: Option, + chroot: Option, uid: Option, gid: Option, saw_nul: bool, @@ -182,6 +183,7 @@ impl Command { program_kind, env: Default::default(), cwd: None, + chroot: None, uid: None, gid: None, saw_nul, @@ -206,6 +208,7 @@ impl Command { program_kind, env: Default::default(), cwd: None, + chroot: None, uid: None, gid: None, saw_nul, @@ -254,6 +257,12 @@ impl Command { pub fn pgroup(&mut self, pgroup: pid_t) { self.pgroup = Some(pgroup); } + pub fn chroot(&mut self, dir: &Path) { + self.chroot = Some(os2c(dir.as_os_str(), &mut self.saw_nul)); + if self.cwd.is_none() { + self.cwd(&OsStr::new("/")); + } + } #[cfg(target_os = "linux")] pub fn create_pidfd(&mut self, val: bool) { @@ -326,6 +335,10 @@ impl Command { pub fn get_pgroup(&self) -> Option { self.pgroup } + #[allow(dead_code)] + pub fn get_chroot(&self) -> Option<&CStr> { + self.chroot.as_deref() + } pub fn get_closures(&mut self) -> &mut Vec io::Result<()> + Send + Sync>> { &mut self.closures diff --git a/library/std/src/sys/process/unix/unix.rs b/library/std/src/sys/process/unix/unix.rs index 1b3bd2de265da..4f595ac9a1c5f 100644 --- a/library/std/src/sys/process/unix/unix.rs +++ b/library/std/src/sys/process/unix/unix.rs @@ -323,6 +323,15 @@ impl Command { cvt(libc::setuid(u as uid_t))?; } } + if let Some(chroot) = self.get_chroot() { + #[cfg(not(target_os = "fuchsia"))] + cvt(libc::chroot(chroot.as_ptr()))?; + #[cfg(target_os = "fuchsia")] + return Err(io::const_error!( + io::ErrorKind::Unsupported, + "chroot not supported by fuchsia" + )); + } if let Some(cwd) = self.get_cwd() { cvt(libc::chdir(cwd.as_ptr()))?; } @@ -447,6 +456,7 @@ impl Command { || (self.env_saw_path() && !self.program_is_path()) || !self.get_closures().is_empty() || self.get_groups().is_some() + || self.get_chroot().is_some() { return Ok(None); } diff --git a/library/std/src/sys/process/unix/vxworks.rs b/library/std/src/sys/process/unix/vxworks.rs index fab3b36ebf3fa..f33b4a375da83 100644 --- a/library/std/src/sys/process/unix/vxworks.rs +++ b/library/std/src/sys/process/unix/vxworks.rs @@ -27,6 +27,12 @@ impl Command { "nul byte found in provided data", )); } + if self.get_chroot().is_some() { + return Err(io::const_error!( + ErrorKind::Unsupported, + "chroot not supported by vxworks", + )); + } let (ours, theirs) = self.setup_io(default, needs_stdin)?; let mut p = Process { pid: 0, status: None }; From c3b750ce0f6d1b40874f88b552d271abea3a3dde Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 20 May 2025 17:59:18 +0200 Subject: [PATCH 08/15] `CommandExt::chroot`: Document difference to underlying `chroot` --- library/std/src/os/unix/process.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 27866badfbe58..8d238aa583519 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -203,9 +203,11 @@ pub trait CommandExt: Sealed { /// the command. /// /// This happens before changing to the directory specified with `Command::current_dir`, and - /// that directory will be relative to the new root. If no directory has been specified with - /// `Command::current_dir`, this will set the directory to `/`, to avoid leaving the current - /// directory outside the chroot. + /// that directory will be relative to the new root. + /// + /// If no directory has been specified with `Command::current_dir`, this will set the directory + /// to `/`, to avoid leaving the current directory outside the chroot. (This is an intentional + /// difference from the underlying `chroot` system call.) #[unstable(feature = "process_chroot", issue = "none")] fn chroot>(&mut self, dir: P) -> &mut process::Command; } From 17fdf19c9cd566987c3f96f69ac60d4741e05b07 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 20 May 2025 18:04:53 +0200 Subject: [PATCH 09/15] `CommandExt::chroot`: Add tracking issue --- library/std/src/os/unix/process.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 8d238aa583519..659b354483458 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -208,7 +208,7 @@ pub trait CommandExt: Sealed { /// If no directory has been specified with `Command::current_dir`, this will set the directory /// to `/`, to avoid leaving the current directory outside the chroot. (This is an intentional /// difference from the underlying `chroot` system call.) - #[unstable(feature = "process_chroot", issue = "none")] + #[unstable(feature = "process_chroot", issue = "141298")] fn chroot>(&mut self, dir: P) -> &mut process::Command; } From ed01a205144f53741534611a74d40487f611cdea Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 20 May 2025 17:27:38 -0700 Subject: [PATCH 10/15] typeck: catch `continue`s pointing to blocks This taints the typeck results with errors if a `continue` is found not pointing to a loop, which fixes an ICE. A few things were going wrong here. First, since this wasn't caught in typeck, we'd end up building the THIR and then running liveness lints on ill-formed HIR. Since liveness assumes all `continue`s point to loops, it wasn't setting a live node for the `continue`'s destination. However, the fallback for this was faulty; it would create a new live node to represent the erroneous state after the analysis's RWU table had already been built. This would ICE if the new live node was used in operations, such as merging results from the arms of a match. I've removed this error-recovery since it was buggy, and we should really catch bad labels before liveness. I've also replaced an outdated comment about when liveness lints are run. At this point, I think the call to `check_liveness` could be moved elsewhere, but if it can be run when the typeck results are tainted by errors, it'll need some slight refactoring so it can bail out in that case. In lieu of that, I've added an assertion. --- compiler/rustc_hir_typeck/src/expr.rs | 34 +++++++++++---- compiler/rustc_mir_build/src/builder/mod.rs | 3 +- compiler/rustc_passes/src/liveness.rs | 10 +++-- tests/crashes/113379.rs | 7 --- tests/crashes/121623.rs | 8 ---- .../continue-pointing-to-block-ice-113379.rs | 12 ++++++ ...ntinue-pointing-to-block-ice-113379.stderr | 43 +++++++++++++++++++ .../continue-pointing-to-block-ice-121623.rs | 11 +++++ ...ntinue-pointing-to-block-ice-121623.stderr | 14 ++++++ 9 files changed, 113 insertions(+), 29 deletions(-) delete mode 100644 tests/crashes/113379.rs delete mode 100644 tests/crashes/121623.rs create mode 100644 tests/ui/label/continue-pointing-to-block-ice-113379.rs create mode 100644 tests/ui/label/continue-pointing-to-block-ice-113379.stderr create mode 100644 tests/ui/label/continue-pointing-to-block-ice-121623.rs create mode 100644 tests/ui/label/continue-pointing-to-block-ice-121623.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2c28ffd1fe3df..a1a33885b944c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -532,14 +532,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Break(destination, ref expr_opt) => { self.check_expr_break(destination, expr_opt.as_deref(), expr) } - ExprKind::Continue(destination) => { - if destination.target_id.is_ok() { - tcx.types.never - } else { - // There was an error; make type-check fail. - Ty::new_misc_error(tcx) - } - } + ExprKind::Continue(destination) => self.check_expr_continue(destination, expr), ExprKind::Ret(ref expr_opt) => self.check_expr_return(expr_opt.as_deref(), expr), ExprKind::Become(call) => self.check_expr_become(call, expr), ExprKind::Let(let_expr) => self.check_expr_let(let_expr, expr.hir_id), @@ -989,6 +982,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn check_expr_continue( + &self, + destination: hir::Destination, + expr: &'tcx hir::Expr<'tcx>, + ) -> Ty<'tcx> { + if let Ok(target_id) = destination.target_id { + if let hir::Node::Expr(hir::Expr { kind: ExprKind::Loop(..), .. }) = + self.tcx.hir_node(target_id) + { + self.tcx.types.never + } else { + // Liveness linting assumes `continue`s all point to loops. We'll report an error + // in `check_mod_loops`, but make sure we don't run liveness (#113379, #121623). + let guar = self.dcx().span_delayed_bug( + expr.span, + "found `continue` not pointing to loop, but no error reported", + ); + Ty::new_error(self.tcx, guar) + } + } else { + // There was an error; make type-check fail. + Ty::new_misc_error(self.tcx) + } + } + fn check_expr_return( &self, expr_opt: Option<&'tcx hir::Expr<'tcx>>, diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index 9cf051a8760be..8400709740f05 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -66,8 +66,7 @@ pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { } }; - // this must run before MIR dump, because - // "not all control paths return a value" is reported here. + // Checking liveness after building the THIR ensures there were no typeck errors. // // maybe move the check to a MIR pass? tcx.ensure_ok().check_liveness(def); diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 4e9b7fd44d4b8..763d9fda80494 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -122,7 +122,6 @@ enum LiveNodeKind { VarDefNode(Span, HirId), ClosureNode, ExitNode, - ErrNode, } fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { @@ -133,7 +132,6 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { VarDefNode(s, _) => format!("Var def node [{}]", sm.span_to_diagnostic_string(s)), ClosureNode => "Closure node".to_owned(), ExitNode => "Exit node".to_owned(), - ErrNode => "Error node".to_owned(), } } @@ -492,6 +490,9 @@ struct Liveness<'a, 'tcx> { impl<'a, 'tcx> Liveness<'a, 'tcx> { fn new(ir: &'a mut IrMaps<'tcx>, body_owner: LocalDefId) -> Liveness<'a, 'tcx> { let typeck_results = ir.tcx.typeck(body_owner); + // Liveness linting runs after building the THIR. We make several assumptions based on + // typeck succeeding, e.g. that breaks and continues are well-formed. + assert!(typeck_results.tainted_by_errors.is_none()); // FIXME(#132279): we're in a body here. let typing_env = ty::TypingEnv::non_body_analysis(ir.tcx, body_owner); let closure_min_captures = typeck_results.closure_min_captures.get(&body_owner); @@ -976,8 +977,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Now that we know the label we're going to, // look it up in the continue loop nodes table self.cont_ln.get(&sc).cloned().unwrap_or_else(|| { - self.ir.tcx.dcx().span_delayed_bug(expr.span, "continue to unknown label"); - self.ir.add_live_node(ErrNode) + // Liveness linting happens after building the THIR. Bad labels should already + // have been caught. + span_bug!(expr.span, "continue to unknown label"); }) } diff --git a/tests/crashes/113379.rs b/tests/crashes/113379.rs deleted file mode 100644 index 7163cbc39342d..0000000000000 --- a/tests/crashes/113379.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #113379 - -async fn f999() -> Vec { - 'b: { - continue 'b; - } -} diff --git a/tests/crashes/121623.rs b/tests/crashes/121623.rs deleted file mode 100644 index 3c01a7f452ca7..0000000000000 --- a/tests/crashes/121623.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #121623 -fn main() { - match () { - _ => 'b: { - continue 'b; - } - } -} diff --git a/tests/ui/label/continue-pointing-to-block-ice-113379.rs b/tests/ui/label/continue-pointing-to-block-ice-113379.rs new file mode 100644 index 0000000000000..8a6a9cc840986 --- /dev/null +++ b/tests/ui/label/continue-pointing-to-block-ice-113379.rs @@ -0,0 +1,12 @@ +//! Regression test for ICE #113379. Liveness linting assumes that `continue`s all point to loops. +//! This tests that if a `continue` points to a block, we don't run liveness lints. + +async fn f999() -> Vec { + //~^ ERROR `async fn` is not permitted in Rust 2015 + 'b: { + //~^ ERROR mismatched types + continue 'b; + //~^ ERROR `continue` pointing to a labeled block + } +} +//~^ ERROR `main` function not found diff --git a/tests/ui/label/continue-pointing-to-block-ice-113379.stderr b/tests/ui/label/continue-pointing-to-block-ice-113379.stderr new file mode 100644 index 0000000000000..ada6305ec999b --- /dev/null +++ b/tests/ui/label/continue-pointing-to-block-ice-113379.stderr @@ -0,0 +1,43 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/continue-pointing-to-block-ice-113379.rs:4:1 + | +LL | async fn f999() -> Vec { + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2024` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error[E0601]: `main` function not found in crate `continue_pointing_to_block_ice_113379` + --> $DIR/continue-pointing-to-block-ice-113379.rs:11:2 + | +LL | } + | ^ consider adding a `main` function to `$DIR/continue-pointing-to-block-ice-113379.rs` + +error[E0696]: `continue` pointing to a labeled block + --> $DIR/continue-pointing-to-block-ice-113379.rs:8:9 + | +LL | / 'b: { +LL | | +LL | | continue 'b; + | | ^^^^^^^^^^^ labeled blocks cannot be `continue`'d +LL | | +LL | | } + | |_____- labeled block the `continue` points to + +error[E0308]: mismatched types + --> $DIR/continue-pointing-to-block-ice-113379.rs:6:5 + | +LL | / 'b: { +LL | | +LL | | continue 'b; +LL | | +LL | | } + | |_____^ expected `Vec`, found `()` + | + = note: expected struct `Vec` + found unit type `()` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0601, E0670, E0696. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/label/continue-pointing-to-block-ice-121623.rs b/tests/ui/label/continue-pointing-to-block-ice-121623.rs new file mode 100644 index 0000000000000..7047f7a309aaf --- /dev/null +++ b/tests/ui/label/continue-pointing-to-block-ice-121623.rs @@ -0,0 +1,11 @@ +//! Regression test for ICE #121623. Liveness linting assumes that `continue`s all point to loops. +//! This tests that if a `continue` points to a block, we don't run liveness lints. + +fn main() { + match () { + _ => 'b: { + continue 'b; + //~^ ERROR `continue` pointing to a labeled block + } + } +} diff --git a/tests/ui/label/continue-pointing-to-block-ice-121623.stderr b/tests/ui/label/continue-pointing-to-block-ice-121623.stderr new file mode 100644 index 0000000000000..a484fb629d181 --- /dev/null +++ b/tests/ui/label/continue-pointing-to-block-ice-121623.stderr @@ -0,0 +1,14 @@ +error[E0696]: `continue` pointing to a labeled block + --> $DIR/continue-pointing-to-block-ice-121623.rs:7:13 + | +LL | _ => 'b: { + | ______________- +LL | | continue 'b; + | | ^^^^^^^^^^^ labeled blocks cannot be `continue`'d +LL | | +LL | | } + | |_________- labeled block the `continue` points to + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0696`. From 5c4eb87dbefaf8f00623574c9386df235fb95411 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 19 May 2025 18:07:32 +0300 Subject: [PATCH 11/15] add missing PATH Signed-off-by: onur-ozkan --- src/ci/docker/host-x86_64/arm-android/Dockerfile | 1 + src/ci/docker/host-x86_64/dist-android/Dockerfile | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile index aade95882685f..bc311be05808d 100644 --- a/src/ci/docker/host-x86_64/arm-android/Dockerfile +++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile @@ -28,6 +28,7 @@ RUN /scripts/android-sdk.sh ENV PATH=$PATH:/android/sdk/emulator ENV PATH=$PATH:/android/sdk/tools ENV PATH=$PATH:/android/sdk/platform-tools +ENV PATH=$PATH:/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin ENV TARGETS=arm-linux-androideabi diff --git a/src/ci/docker/host-x86_64/dist-android/Dockerfile b/src/ci/docker/host-x86_64/dist-android/Dockerfile index 95fed6ee767b0..7b73326e35900 100644 --- a/src/ci/docker/host-x86_64/dist-android/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-android/Dockerfile @@ -22,6 +22,8 @@ ENV RUST_CONFIGURE_ARGS \ --android-ndk=/android/ndk/ \ --disable-docs +ENV PATH=$PATH:/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin + ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS COPY scripts/sccache.sh /scripts/ From 348c1b0d886960a57a866e537458dae6bf75ec23 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Tue, 20 May 2025 23:00:24 +0200 Subject: [PATCH 12/15] Apply suggestions from code review Link `Command::current_dir`. Co-authored-by: Amanieu d'Antras --- library/std/src/os/unix/process.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index 659b354483458..57ce3c5a4bf4a 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -202,12 +202,12 @@ pub trait CommandExt: Sealed { /// Set the root of the child process. This calls `chroot` in the child process before executing /// the command. /// - /// This happens before changing to the directory specified with `Command::current_dir`, and - /// that directory will be relative to the new root. + /// This happens before changing to the directory specified with + /// [`process::Command::current_dir`], and that directory will be relative to the new root. /// - /// If no directory has been specified with `Command::current_dir`, this will set the directory - /// to `/`, to avoid leaving the current directory outside the chroot. (This is an intentional - /// difference from the underlying `chroot` system call.) + /// If no directory has been specified with [`process::Command::current_dir`], this will set the + /// directory to `/`, to avoid leaving the current directory outside the chroot. (This is an + /// intentional difference from the underlying `chroot` system call.) #[unstable(feature = "process_chroot", issue = "141298")] fn chroot>(&mut self, dir: P) -> &mut process::Command; } From 6ac8e512839677f673bd5cd2d5d6892b2bb9f71c Mon Sep 17 00:00:00 2001 From: Ell Date: Wed, 21 May 2025 10:07:17 +0300 Subject: [PATCH 13/15] Allow x perf to find rustc.exe on Windows --- src/bootstrap/src/core/build_steps/perf.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs index 7f4e88bd73c6f..71cdb665ed47e 100644 --- a/src/bootstrap/src/core/build_steps/perf.rs +++ b/src/bootstrap/src/core/build_steps/perf.rs @@ -1,3 +1,4 @@ +use std::env::consts::EXE_EXTENSION; use std::fmt::{Display, Formatter}; use crate::core::build_steps::compile::{Std, Sysroot}; @@ -160,7 +161,10 @@ Consider setting `rust.debuginfo-level = 1` in `bootstrap.toml`."#); } let sysroot = builder.ensure(Sysroot::new(compiler)); - let rustc = sysroot.join("bin/rustc"); + let mut rustc = sysroot.clone(); + rustc.push("bin"); + rustc.push("rustc"); + rustc.set_extension(EXE_EXTENSION); let rustc_perf_dir = builder.build.tempdir().join("rustc-perf"); let results_dir = rustc_perf_dir.join("results"); From 84f67a5e51bf1695a0c368a9f44a15f15cdf6b9e Mon Sep 17 00:00:00 2001 From: xizheyin Date: Wed, 21 May 2025 16:19:51 +0800 Subject: [PATCH 14/15] Downgrade the confident of suggestion `available field in format string` and optimize expression Signed-off-by: xizheyin --- compiler/rustc_resolve/src/late/diagnostics.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 30c2125d0b66a..80d7a4dd47ac8 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -753,15 +753,9 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if self_is_available { let source_map = self.r.tcx.sess.source_map(); // check if the field is used in a format string, such as `"{x}"` - let field_is_format_named_arg = - source_map.span_to_source(span, |s, start, _| { - if let Some(expanded_expr) = s.get(start - 1..start) - && expanded_expr.starts_with("{") - { - Ok(true) - } else { - Ok(false) - } + let field_is_format_named_arg = source_map + .span_to_source(span, |s, start, _| { + Ok(s.get(start - 1..start) == Some("{")) }); if let Ok(true) = field_is_format_named_arg { err.help( @@ -772,7 +766,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span.shrink_to_lo(), "you might have meant to use the available field", format!("{pre}self."), - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } } else { From 1cc0e38fdc4d2ec8c9c130d7ffc9c30d100885a2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 21 May 2025 13:28:08 +1000 Subject: [PATCH 15/15] Avoid creating an empty identifer in `Symbol::to_ident_string`. Because that causes an assertion failure in debug builds. Fixes #140884. --- compiler/rustc_span/src/symbol.rs | 3 ++- tests/crashes/140884.rs | 6 ------ .../ui/extern/extern-empty-string-issue-140884.rs | 3 +++ .../extern-empty-string-issue-140884.stderr | 15 +++++++++++++++ 4 files changed, 20 insertions(+), 7 deletions(-) delete mode 100644 tests/crashes/140884.rs create mode 100644 tests/ui/extern/extern-empty-string-issue-140884.rs create mode 100644 tests/ui/extern/extern-empty-string-issue-140884.stderr diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index efae6250b0720..fbe3b4ca6f5f6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2592,7 +2592,8 @@ impl Symbol { /// (`token_to_string`, `Ident::to_string`), except that symbols don't keep the rawness flag /// or edition, so we have to guess the rawness using the global edition. pub fn to_ident_string(self) -> String { - Ident::with_dummy_span(self).to_string() + // Avoid creating an empty identifier, because that asserts in debug builds. + if self == kw::Empty { String::new() } else { Ident::with_dummy_span(self).to_string() } } } diff --git a/tests/crashes/140884.rs b/tests/crashes/140884.rs deleted file mode 100644 index 6840760933a39..0000000000000 --- a/tests/crashes/140884.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #140884 -//@ needs-rustc-debug-assertions - -fn a() { - extern "" {} -} diff --git a/tests/ui/extern/extern-empty-string-issue-140884.rs b/tests/ui/extern/extern-empty-string-issue-140884.rs new file mode 100644 index 0000000000000..10291513d34d2 --- /dev/null +++ b/tests/ui/extern/extern-empty-string-issue-140884.rs @@ -0,0 +1,3 @@ +extern "" {} //~ ERROR invalid ABI: found `` + +fn main() {} diff --git a/tests/ui/extern/extern-empty-string-issue-140884.stderr b/tests/ui/extern/extern-empty-string-issue-140884.stderr new file mode 100644 index 0000000000000..accae0c0f7c73 --- /dev/null +++ b/tests/ui/extern/extern-empty-string-issue-140884.stderr @@ -0,0 +1,15 @@ +error[E0703]: invalid ABI: found `` + --> $DIR/extern-empty-string-issue-140884.rs:1:8 + | +LL | extern "" {} + | ^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions +help: there's a similarly named valid ABI `C` + | +LL | extern "C" {} + | + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0703`.