Rollup merge of #131838 - jieyouxu:boopjob, r=onur-ozkan

bootstrap: allow setting `--jobs` in config.toml

Allow setting `--jobs` in config.toml's `[build]` section.

```toml
[build]
jobs = 0
```

If this is unset or set to zero in config.toml, we look at `--jobs` flag. If that is also unset, then we fallback to `std::thread::available_parallelism`. If that is not available, then we default to `1`. The flags and `available_parallelism` fallback are already setup, this PR just adds a config.toml option to wire that up.

Closes #131836.

r? bootstrap
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index b84cbf9..98db36b 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -4011,6 +4011,7 @@
                 let instead = res.is_some();
                 let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
                     && path[0].ident.span.lo() == end.span.lo()
+                    && !matches!(start.kind, ExprKind::Lit(_))
                 {
                     let mut sugg = ".";
                     let mut span = start.span.between(end.span);
diff --git a/library/Cargo.lock b/library/Cargo.lock
index ed9e7dd..eede2f4 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -340,7 +340,6 @@
  "object",
  "panic_abort",
  "panic_unwind",
- "profiler_builtins",
  "r-efi",
  "r-efi-alloc",
  "rand",
@@ -368,6 +367,7 @@
 version = "0.0.0"
 dependencies = [
  "proc_macro",
+ "profiler_builtins",
  "std",
  "test",
 ]
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 5f8dcde..00bebf1 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -18,7 +18,6 @@
 panic_abort = { path = "../panic_abort" }
 core = { path = "../core", public = true }
 compiler_builtins = { version = "0.1.133" }
-profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
 hashbrown = { version = "0.15", default-features = false, features = [
     'rustc-dep-of-std',
@@ -98,7 +97,6 @@
 ]
 
 panic-unwind = ["panic_unwind"]
-profiler = ["profiler_builtins"]
 compiler-builtins-c = ["alloc/compiler-builtins-c"]
 compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
 compiler-builtins-no-asm = ["alloc/compiler-builtins-no-asm"]
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index 4ced706..abc8e69 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -10,7 +10,7 @@
 //! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles)
 
 use r_efi::efi::{self, Guid};
-use r_efi::protocols::{device_path, device_path_to_text};
+use r_efi::protocols::{device_path, device_path_to_text, shell};
 
 use crate::ffi::{OsStr, OsString};
 use crate::io::{self, const_io_error};
@@ -424,3 +424,24 @@
     let temp = s.encode_wide().chain(Some(0)).collect::<Box<[r_efi::efi::Char16]>>();
     if temp[..temp.len() - 1].contains(&0) { None } else { Some(temp) }
 }
+
+pub(crate) fn open_shell() -> Option<NonNull<shell::Protocol>> {
+    static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
+        AtomicPtr::new(crate::ptr::null_mut());
+
+    if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
+        if let Ok(protocol) = open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID) {
+            return Some(protocol);
+        }
+    }
+
+    let handles = locate_handles(shell::PROTOCOL_GUID).ok()?;
+    for handle in handles {
+        if let Ok(protocol) = open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID) {
+            LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
+            return Some(protocol);
+        }
+    }
+
+    None
+}
diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs
index 4eb7698..27395f7 100644
--- a/library/std/src/sys/pal/uefi/os.rs
+++ b/library/std/src/sys/pal/uefi/os.rs
@@ -125,7 +125,7 @@
 }
 
 pub fn getcwd() -> io::Result<PathBuf> {
-    match uefi_shell::open_shell() {
+    match helpers::open_shell() {
         Some(shell) => {
             // SAFETY: path_ptr is managed by UEFI shell and should not be deallocated
             let path_ptr = unsafe { ((*shell.as_ptr()).get_cur_dir)(crate::ptr::null_mut()) };
@@ -144,7 +144,7 @@
 }
 
 pub fn chdir(p: &path::Path) -> io::Result<()> {
-    let shell = uefi_shell::open_shell().ok_or(unsupported_err())?;
+    let shell = helpers::open_shell().ok_or(unsupported_err())?;
 
     let mut p = helpers::os_string_to_raw(p.as_os_str())
         .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?;
@@ -192,44 +192,58 @@
     helpers::device_path_to_text(protocol).map(PathBuf::from)
 }
 
-pub struct Env(!);
+pub struct EnvStrDebug<'a> {
+    iter: &'a [(OsString, OsString)],
+}
+
+impl fmt::Debug for EnvStrDebug<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut list = f.debug_list();
+        for (a, b) in self.iter {
+            list.entry(&(a.to_str().unwrap(), b.to_str().unwrap()));
+        }
+        list.finish()
+    }
+}
+
+pub struct Env(crate::vec::IntoIter<(OsString, OsString)>);
 
 impl Env {
     // FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
     pub fn str_debug(&self) -> impl fmt::Debug + '_ {
-        let Self(inner) = self;
-        match *inner {}
+        EnvStrDebug { iter: self.0.as_slice() }
     }
 }
 
 impl Iterator for Env {
     type Item = (OsString, OsString);
+
     fn next(&mut self) -> Option<(OsString, OsString)> {
-        self.0
+        self.0.next()
     }
 }
 
 impl fmt::Debug for Env {
-    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let Self(inner) = self;
-        match *inner {}
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
     }
 }
 
 pub fn env() -> Env {
-    panic!("not supported on this platform")
+    let env = uefi_env::get_all().expect("not supported on this platform");
+    Env(env.into_iter())
 }
 
-pub fn getenv(_: &OsStr) -> Option<OsString> {
-    None
+pub fn getenv(key: &OsStr) -> Option<OsString> {
+    uefi_env::get(key)
 }
 
-pub unsafe fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot set env vars on this platform"))
+pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {
+    uefi_env::set(key, val)
 }
 
-pub unsafe fn unsetenv(_: &OsStr) -> io::Result<()> {
-    Err(io::const_io_error!(io::ErrorKind::Unsupported, "cannot unset env vars on this platform"))
+pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {
+    uefi_env::unset(key)
 }
 
 pub fn temp_dir() -> PathBuf {
@@ -261,36 +275,84 @@
     panic!("no pids on this platform")
 }
 
-mod uefi_shell {
-    use r_efi::protocols::shell;
-
-    use super::super::helpers;
+mod uefi_env {
+    use crate::ffi::{OsStr, OsString};
+    use crate::io;
+    use crate::os::uefi::ffi::OsStringExt;
     use crate::ptr::NonNull;
-    use crate::sync::atomic::{AtomicPtr, Ordering};
+    use crate::sys::{helpers, unsupported_err};
 
-    pub fn open_shell() -> Option<NonNull<shell::Protocol>> {
-        static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
-            AtomicPtr::new(crate::ptr::null_mut());
+    pub(crate) fn get(key: &OsStr) -> Option<OsString> {
+        let shell = helpers::open_shell()?;
+        let mut key_ptr = helpers::os_string_to_raw(key)?;
+        unsafe { get_raw(shell, key_ptr.as_mut_ptr()) }
+    }
 
-        if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
-            if let Ok(protocol) = helpers::open_protocol::<shell::Protocol>(
-                handle,
-                r_efi::protocols::shell::PROTOCOL_GUID,
-            ) {
-                return Some(protocol);
+    pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> {
+        let mut key_ptr = helpers::os_string_to_raw(key)
+            .ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;
+        let mut val_ptr = helpers::os_string_to_raw(val)
+            .ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;
+        unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) }
+    }
+
+    pub(crate) fn unset(key: &OsStr) -> io::Result<()> {
+        let mut key_ptr = helpers::os_string_to_raw(key)
+            .ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Key"))?;
+        unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) }
+    }
+
+    pub(crate) fn get_all() -> io::Result<Vec<(OsString, OsString)>> {
+        let shell = helpers::open_shell().ok_or(unsupported_err())?;
+
+        let mut vars = Vec::new();
+        let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) };
+
+        if val.is_null() {
+            return Ok(vars);
+        }
+
+        let mut start = 0;
+
+        // UEFI Shell returns all keys seperated by NULL.
+        // End of string is denoted by two NULLs
+        for i in 0.. {
+            if unsafe { *val.add(i) } == 0 {
+                // Two NULL signal end of string
+                if i == start {
+                    break;
+                }
+
+                let key = OsString::from_wide(unsafe {
+                    crate::slice::from_raw_parts(val.add(start), i - start)
+                });
+                // SAFETY: val.add(start) is always NULL terminated
+                let val = unsafe { get_raw(shell, val.add(start)) }
+                    .ok_or(io::const_io_error!(io::ErrorKind::InvalidInput, "Invalid Value"))?;
+
+                vars.push((key, val));
+                start = i + 1;
             }
         }
 
-        let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?;
-        for handle in handles {
-            if let Ok(protocol) =
-                helpers::open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID)
-            {
-                LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
-                return Some(protocol);
-            }
-        }
+        Ok(vars)
+    }
 
-        None
+    unsafe fn get_raw(
+        shell: NonNull<r_efi::efi::protocols::shell::Protocol>,
+        key_ptr: *mut r_efi::efi::Char16,
+    ) -> Option<OsString> {
+        let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) };
+        helpers::os_string_from_raw(val)
+    }
+
+    unsafe fn set_raw(
+        key_ptr: *mut r_efi::efi::Char16,
+        val_ptr: *mut r_efi::efi::Char16,
+    ) -> io::Result<()> {
+        let shell = helpers::open_shell().ok_or(unsupported_err())?;
+        let r =
+            unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) };
+        if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
     }
 }
diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
index 7165c3e..aa6c3dc 100644
--- a/library/sysroot/Cargo.toml
+++ b/library/sysroot/Cargo.toml
@@ -6,6 +6,7 @@
 # this is a dummy crate to ensure that all required crates appear in the sysroot
 [dependencies]
 proc_macro = { path = "../proc_macro" }
+profiler_builtins = { path = "../profiler_builtins", optional = true }
 std = { path = "../std" }
 test = { path = "../test" }
 
@@ -23,7 +24,7 @@
 panic-unwind = ["std/panic_unwind"]
 panic_immediate_abort = ["std/panic_immediate_abort"]
 optimize_for_size = ["std/optimize_for_size"]
-profiler = ["std/profiler"]
+profiler = ["dep:profiler_builtins"]
 std_detect_file_io = ["std/std_detect_file_io"]
 std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
 std_detect_env_override = ["std/std_detect_env_override"]
diff --git a/src/tools/cargo b/src/tools/cargo
index 8c30ce5..cf53cc5 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 8c30ce53688e25f7e9d860b33cc914fb2957ca9a
+Subproject commit cf53cc54bb593b5ec3dc2be4b1702f50c36d24d5
diff --git a/tests/ui/range/misleading-field-access-hint.rs b/tests/ui/range/misleading-field-access-hint.rs
new file mode 100644
index 0000000..252f1a4
--- /dev/null
+++ b/tests/ui/range/misleading-field-access-hint.rs
@@ -0,0 +1,8 @@
+// Check if rustc still displays the misleading hint to write `.` instead of `..`
+fn main() {
+    let width = 10;
+    // ...
+    for _ in 0..w {
+        //~^ ERROR cannot find value `w`
+    }
+}
diff --git a/tests/ui/range/misleading-field-access-hint.stderr b/tests/ui/range/misleading-field-access-hint.stderr
new file mode 100644
index 0000000..9b112a5
--- /dev/null
+++ b/tests/ui/range/misleading-field-access-hint.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `w` in this scope
+  --> $DIR/misleading-field-access-hint.rs:5:17
+   |
+LL |     for _ in 0..w {
+   |                 ^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.