From 6eaf531432147c0359fc1d3d959ee525851e7ced Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 14 Aug 2024 14:30:23 +0200 Subject: [PATCH 01/17] add Box::as_ptr and Box::as_mut_ptr methods --- library/alloc/src/boxed.rs | 89 ++++++++++++++++++++++++++++++++++++ library/alloc/src/vec/mod.rs | 3 +- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7de412595993a..0fe915bb838ca 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -1254,6 +1254,95 @@ impl Box { unsafe { (Unique::from(&mut *ptr), alloc) } } + /// Returns a raw mutable pointer to the `Box`'s contents. + /// + /// The caller must ensure that the `Box` outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying memory, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize references to the memory + /// may still invalidate this pointer. + /// See the example below for how this guarantee can be used. + /// + /// # Examples + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_as_ptr)] + /// + /// unsafe { + /// let mut b = Box::new(0); + /// let ptr1 = Box::as_mut_ptr(&mut b); + /// ptr1.write(1); + /// let ptr2 = Box::as_mut_ptr(&mut b); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Self::as_mut_ptr + /// [`as_ptr`]: Self::as_ptr + #[unstable(feature = "box_as_ptr", issue = "129090")] + #[rustc_never_returns_null_ptr] + #[inline] + pub fn as_mut_ptr(b: &mut Self) -> *mut T { + // This is a primitive deref, not going through `DerefMut`, and therefore not materializing + // any references. + ptr::addr_of_mut!(**b) + } + + /// Returns a raw pointer to the `Box`'s contents. + /// + /// The caller must ensure that the `Box` outlives the pointer this + /// function returns, or else it will end up dangling. + /// + /// The caller must also ensure that the memory the pointer (non-transitively) points to + /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer + /// derived from it. If you need to mutate the contents of the `Box`, use [`as_mut_ptr`]. + /// + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying memory, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. + /// Note that calling other methods that materialize mutable references to the memory, + /// as well as writing to this memory, may still invalidate this pointer. + /// See the example below for how this guarantee can be used. + /// + /// # Examples + /// + /// Due to the aliasing guarantee, the following code is legal: + /// + /// ```rust + /// #![feature(box_as_ptr)] + /// + /// unsafe { + /// let mut v = Box::new(0); + /// let ptr1 = Box::as_ptr(&v); + /// let ptr2 = Box::as_mut_ptr(&mut v); + /// let _val = ptr2.read(); + /// // No write to this memory has happened yet, so `ptr1` is still valid. + /// let _val = ptr1.read(); + /// // However, once we do a write... + /// ptr2.write(1); + /// // ... `ptr1` is no longer valid. + /// // This would be UB: let _val = ptr1.read(); + /// } + /// ``` + /// + /// [`as_mut_ptr`]: Self::as_mut_ptr + /// [`as_ptr`]: Self::as_ptr + #[unstable(feature = "box_as_ptr", issue = "129090")] + #[rustc_never_returns_null_ptr] + #[inline] + pub fn as_ptr(b: &Self) -> *const T { + // This is a primitive deref, not going through `DerefMut`, and therefore not materializing + // any references. + ptr::addr_of!(**b) + } + /// Returns a reference to the underlying allocator. /// /// Note: this is an associated function, which means that you have diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index b4e0bc5fcbe41..cfd2e4a15121a 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1334,7 +1334,7 @@ impl Vec { self.buf.ptr() } - /// Returns an unsafe mutable pointer to the vector's buffer, or a dangling + /// Returns a raw mutable pointer to the vector's buffer, or a dangling /// raw pointer valid for zero sized reads if the vector didn't allocate. /// /// The caller must ensure that the vector outlives the pointer this @@ -1350,7 +1350,6 @@ impl Vec { /// may still invalidate this pointer. /// See the second example below for how this guarantee can be used. /// - /// /// # Examples /// /// ``` From 58dcd1c2e6f020369e9e9c0d8ad76435cb34a6f3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 14 Aug 2024 14:32:17 +0200 Subject: [PATCH 02/17] use the new Box methods in the interpreter --- compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/mir/interpret/allocation.rs | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 5bd7736a3f3cc..6886562d9b76d 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -34,6 +34,7 @@ #![feature(allocator_api)] #![feature(array_windows)] #![feature(assert_matches)] +#![feature(box_as_ptr)] #![feature(box_patterns)] #![feature(closure_track_caller)] #![feature(const_option)] diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 665ab2797f21f..3e101c0c6354d 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -62,13 +62,11 @@ impl AllocBytes for Box<[u8]> { } fn as_mut_ptr(&mut self) -> *mut u8 { - // Carefully avoiding any intermediate references. - ptr::addr_of_mut!(**self).cast() + Box::as_mut_ptr(self).cast() } fn as_ptr(&self) -> *const u8 { - // Carefully avoiding any intermediate references. - ptr::addr_of!(**self).cast() + Box::as_ptr(self).cast() } } From 12e638978814d84e4e09b172f784d5f16759d8e1 Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 15 Aug 2024 16:22:01 -0400 Subject: [PATCH 03/17] bootstrap: improve error recovery flags to curl alternative to #128459 fixes #110178 --- src/bootstrap/bootstrap.py | 8 +++++++- src/bootstrap/src/core/download.rs | 31 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4e8e0fd2532f1..5ea4b4882a975 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -79,6 +79,8 @@ def get(base, url, path, checksums, verbose=False): eprint("removing", temp_path) os.unlink(temp_path) +def curl_version(): + return float(re.match(bytes("^curl ([0-9]+\\.[0-9]+)", "utf8"), require(["curl", "-V"]))[1]) def download(path, url, probably_big, verbose): for _ in range(4): @@ -107,11 +109,15 @@ def _download(path, url, probably_big, verbose, exception): # If curl is not present on Win32, we should not sys.exit # but raise `CalledProcessError` or `OSError` instead require(["curl", "--version"], exception=platform_is_win32()) - run(["curl", option, + extra_flags = [] + if curl_version() > 7.70: + extra_flags = [ "--retry-all-errors" ] + run(["curl", option] + extra_flags + [ "-L", # Follow redirect. "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds "--connect-timeout", "30", # timeout if cannot connect within 30 seconds "-o", path, + "--continue-at", "-", "--retry", "3", "-SRf", url], verbose=verbose, exception=True, # Will raise RuntimeError on failure diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 4d1aea3cd956a..ed7637e8ee097 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -21,6 +21,31 @@ fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> { config.try_run(cmd) } +fn extract_curl_version(out: &[u8]) -> f32 { + let out = &out[5..]; + let Some(i) = out.iter().position(|&x| x == b' ') else { return 0.0 }; + let out = &out[..i]; + let Some(k) = out.iter().rev().position(|&x| x == b'.') else { return 0.0 }; + let out = &out[..out.len()-k-1]; + std::str::from_utf8(out).unwrap().parse().unwrap_or(0.0) +} + +#[test] +fn test_extract_curl_version() { + assert_eq!(extract_curl_version(b"\ + curl 8.4.0 (x86_64-pc-linux-gnu) libcurl/8.4.0 \ + OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.4 \ + libssh2/1.11.0 nghttp2/1.57.0"), 8.4); +} + +fn curl_version() -> f32 { + let mut curl = Command::new("curl"); + curl.arg("-V"); + let Ok(out) = curl.output() else { return 0.0 }; + let out = out.stdout; + extract_curl_version(&out) +} + /// Generic helpers that are useful anywhere in bootstrap. impl Config { pub fn is_verbose(&self) -> bool { @@ -219,6 +244,8 @@ impl Config { "30", // timeout if cannot connect within 30 seconds "-o", tempfile.to_str().unwrap(), + "--continue-at", + "-", "--retry", "3", "-SRf", @@ -229,6 +256,10 @@ impl Config { } else { curl.arg("--progress-bar"); } + // --retry-all-errors was added in 7.71.0, don't use it if curl is old. + if dbg!(curl_version()) > 7.70 { + curl.arg("--retry-all-errors"); + } curl.arg(url); if !self.check_run(&mut curl) { if self.build.contains("windows-msvc") { From b3ec296f3d918efdbe4db02dbd7fbc7fea1641a1 Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 16 Aug 2024 23:25:18 -0400 Subject: [PATCH 04/17] autoformat and remove unit test --- src/bootstrap/src/core/download.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index ed7637e8ee097..2bde05501fcfc 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -26,18 +26,10 @@ fn extract_curl_version(out: &[u8]) -> f32 { let Some(i) = out.iter().position(|&x| x == b' ') else { return 0.0 }; let out = &out[..i]; let Some(k) = out.iter().rev().position(|&x| x == b'.') else { return 0.0 }; - let out = &out[..out.len()-k-1]; + let out = &out[..out.len() - k - 1]; std::str::from_utf8(out).unwrap().parse().unwrap_or(0.0) } -#[test] -fn test_extract_curl_version() { - assert_eq!(extract_curl_version(b"\ - curl 8.4.0 (x86_64-pc-linux-gnu) libcurl/8.4.0 \ - OpenSSL/3.0.13 zlib/1.3 brotli/1.1.0 zstd/1.5.5 libidn2/2.3.4 \ - libssh2/1.11.0 nghttp2/1.57.0"), 8.4); -} - fn curl_version() -> f32 { let mut curl = Command::new("curl"); curl.arg("-V"); From d1b41f3747ecb01b717bd50918513227de36f3cb Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 22 Aug 2024 19:04:34 -0400 Subject: [PATCH 05/17] remove dbg!() --- src/bootstrap/src/core/download.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 2bde05501fcfc..201addaec2fc5 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -249,7 +249,7 @@ impl Config { curl.arg("--progress-bar"); } // --retry-all-errors was added in 7.71.0, don't use it if curl is old. - if dbg!(curl_version()) > 7.70 { + if curl_version() > 7.70 { curl.arg("--retry-all-errors"); } curl.arg(url); From 5f2cedc5dc4ed5653069a83f1ed98b46f0c33c7c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 23 Aug 2024 12:08:41 +0300 Subject: [PATCH 06/17] handle stage0 cargo and rustc separately This change allows setting either `build.cargo` or `build.rustc` without requiring both to be set simultaneously, which was not possible previously. To try it, set `build.rustc` without setting `build.cargo`, and try to bootstrap on clean build. Signed-off-by: onur-ozkan --- src/bootstrap/bootstrap.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 4e8e0fd2532f1..0490d31fa584d 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -533,9 +533,13 @@ def download_toolchain(self): bin_root = self.bin_root() key = self.stage0_compiler.date - if self.rustc().startswith(bin_root) and \ - (not os.path.exists(self.rustc()) or - self.program_out_of_date(self.rustc_stamp(), key)): + is_outdated = self.program_out_of_date(self.rustc_stamp(), key) + need_rustc = self.rustc().startswith(bin_root) and (not os.path.exists(self.rustc()) \ + or is_outdated) + need_cargo = self.cargo().startswith(bin_root) and (not os.path.exists(self.cargo()) \ + or is_outdated) + + if need_rustc or need_cargo: if os.path.exists(bin_root): # HACK: On Windows, we can't delete rust-analyzer-proc-macro-server while it's # running. Kill it. @@ -556,7 +560,6 @@ def download_toolchain(self): run_powershell([script]) shutil.rmtree(bin_root) - key = self.stage0_compiler.date cache_dst = (self.get_toml('bootstrap-cache-path', 'build') or os.path.join(self.build_dir, "cache")) @@ -568,11 +571,16 @@ def download_toolchain(self): toolchain_suffix = "{}-{}{}".format(rustc_channel, self.build, tarball_suffix) - tarballs_to_download = [ - ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)), - ("rustc-{}".format(toolchain_suffix), "rustc"), - ("cargo-{}".format(toolchain_suffix), "cargo"), - ] + tarballs_to_download = [] + + if need_rustc: + tarballs_to_download.append( + ("rust-std-{}".format(toolchain_suffix), "rust-std-{}".format(self.build)) + ) + tarballs_to_download.append(("rustc-{}".format(toolchain_suffix), "rustc")) + + if need_cargo: + tarballs_to_download.append(("cargo-{}".format(toolchain_suffix), "cargo")) tarballs_download_info = [ DownloadInfo( From 69ca95bf7f5462eb7ade2de18d1f0d79b2c21cfd Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 23 Aug 2024 11:48:04 -0400 Subject: [PATCH 07/17] use tuples for semver, not floats --- src/bootstrap/bootstrap.py | 7 +++++-- src/bootstrap/src/core/download.rs | 18 +++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 5ea4b4882a975..c19134b4594fb 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -80,7 +80,10 @@ def get(base, url, path, checksums, verbose=False): os.unlink(temp_path) def curl_version(): - return float(re.match(bytes("^curl ([0-9]+\\.[0-9]+)", "utf8"), require(["curl", "-V"]))[1]) + m = re.match(bytes("^curl ([0-9]+)\\.([0-9]+)", "utf8"), require(["curl", "-V"])) + if m is None: + return (0, 0) + return (int(m[1]), int(m[2])) def download(path, url, probably_big, verbose): for _ in range(4): @@ -110,7 +113,7 @@ def _download(path, url, probably_big, verbose, exception): # but raise `CalledProcessError` or `OSError` instead require(["curl", "--version"], exception=platform_is_win32()) extra_flags = [] - if curl_version() > 7.70: + if curl_version() > (7, 70): extra_flags = [ "--retry-all-errors" ] run(["curl", option] + extra_flags + [ "-L", # Follow redirect. diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 201addaec2fc5..fd6f17130ee91 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -21,19 +21,23 @@ fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> { config.try_run(cmd) } -fn extract_curl_version(out: &[u8]) -> f32 { +fn extract_curl_version(out: &[u8]) -> (u16, u16) { let out = &out[5..]; - let Some(i) = out.iter().position(|&x| x == b' ') else { return 0.0 }; + let Some(i) = out.iter().position(|&x| x == b' ') else { return (0, 0) }; let out = &out[..i]; - let Some(k) = out.iter().rev().position(|&x| x == b'.') else { return 0.0 }; + let Some(k) = out.iter().rev().position(|&x| x == b'.') else { return (0, 0) }; let out = &out[..out.len() - k - 1]; - std::str::from_utf8(out).unwrap().parse().unwrap_or(0.0) + let Ok(s) = std::str::from_utf8(out) else { return (0, 0) }; + let parts = s.split('.').collect::>(); + let [s_major, s_minor] = &parts[..] else { return (0, 0) }; + let (Ok(major), Ok(minor)) = (s_major.parse(), s_minor.parse()) else { return (0, 0) }; + (major, minor) } -fn curl_version() -> f32 { +fn curl_version() -> (u16, u16) { let mut curl = Command::new("curl"); curl.arg("-V"); - let Ok(out) = curl.output() else { return 0.0 }; + let Ok(out) = curl.output() else { return (0, 0) }; let out = out.stdout; extract_curl_version(&out) } @@ -249,7 +253,7 @@ impl Config { curl.arg("--progress-bar"); } // --retry-all-errors was added in 7.71.0, don't use it if curl is old. - if curl_version() > 7.70 { + if curl_version() > (7, 70) { curl.arg("--retry-all-errors"); } curl.arg(url); From 9ccd7abefeba2bde9e3366b5bb3985375fb0b8e6 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 21 Aug 2024 22:32:03 -0700 Subject: [PATCH 08/17] library: Move unstable API of new_uninit to new features - `new_zeroed` variants move to `new_zeroed_alloc` - the `write` fn moves to `box_uninit_write` The remainder will be stabilized in upcoming patches, as it was decided to only stabilize `uninit*` and `assume_init`. --- compiler/rustc_index/src/lib.rs | 1 + library/alloc/src/boxed.rs | 9 ++++++--- library/alloc/src/rc.rs | 6 ++++-- library/alloc/src/sync.rs | 10 ++++++---- library/std/src/lib.rs | 1 + 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs index b5e4f02a8d15c..b9d2a43206b1e 100644 --- a/compiler/rustc_index/src/lib.rs +++ b/compiler/rustc_index/src/lib.rs @@ -2,6 +2,7 @@ #![cfg_attr(all(feature = "nightly", test), feature(stmt_expr_attributes))] #![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", feature(extend_one, new_uninit, step_trait, test))] +#![cfg_attr(feature = "nightly", feature(new_zeroed_alloc))] // tidy-alphabetical-end pub mod bit_set; diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7de412595993a..c8e8d2a22ca48 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -293,6 +293,7 @@ impl Box { /// /// ``` /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// let zero = Box::::new_zeroed(); /// let zero = unsafe { zero.assume_init() }; @@ -303,7 +304,7 @@ impl Box { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Box> { Self::new_zeroed_in(Global) @@ -684,6 +685,7 @@ impl Box<[T]> { /// # Examples /// /// ``` + /// #![feature(new_zeroed_alloc)] /// #![feature(new_uninit)] /// /// let values = Box::<[u32]>::new_zeroed_slice(3); @@ -694,7 +696,7 @@ impl Box<[T]> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Box<[mem::MaybeUninit]> { unsafe { RawVec::with_capacity_zeroed(len).into_box(len) } @@ -955,6 +957,7 @@ impl Box, A> { /// # Examples /// /// ``` + /// #![feature(box_uninit_write)] /// #![feature(new_uninit)] /// /// let big_box = Box::<[usize; 1024]>::new_uninit(); @@ -972,7 +975,7 @@ impl Box, A> { /// assert_eq!(*x, i); /// } /// ``` - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "box_uninit_write", issue = "129397")] #[inline] pub fn write(mut boxed: Self, value: T) -> Box { unsafe { diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index bdee06154faec..f153aa6d3be9a 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -539,6 +539,7 @@ impl Rc { /// # Examples /// /// ``` + /// #![feature(new_zeroed_alloc)] /// #![feature(new_uninit)] /// /// use std::rc::Rc; @@ -551,7 +552,7 @@ impl Rc { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Rc> { unsafe { @@ -1000,6 +1001,7 @@ impl Rc<[T]> { /// /// ``` /// #![feature(new_uninit)] + /// #![feature(new_zeroed_alloc)] /// /// use std::rc::Rc; /// @@ -1011,7 +1013,7 @@ impl Rc<[T]> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit]> { unsafe { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 2c0d19b0ada09..4a3522f1a641b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -542,6 +542,7 @@ impl Arc { /// # Examples /// /// ``` + /// #![feature(new_zeroed_alloc)] /// #![feature(new_uninit)] /// /// use std::sync::Arc; @@ -555,7 +556,7 @@ impl Arc { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed() -> Arc> { unsafe { @@ -1134,6 +1135,7 @@ impl Arc<[T]> { /// # Examples /// /// ``` + /// #![feature(new_zeroed_alloc)] /// #![feature(new_uninit)] /// /// use std::sync::Arc; @@ -1147,7 +1149,7 @@ impl Arc<[T]> { /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] #[inline] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "new_zeroed_alloc", issue = "129396")] #[must_use] pub fn new_zeroed_slice(len: usize) -> Arc<[mem::MaybeUninit]> { unsafe { @@ -1191,7 +1193,7 @@ impl Arc<[T], A> { /// assert_eq!(*values, [1, 2, 3]) /// ``` #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_uninit_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { unsafe { Arc::from_ptr_in(Arc::allocate_for_slice_in(len, &alloc), alloc) } @@ -1220,7 +1222,7 @@ impl Arc<[T], A> { /// /// [zeroed]: mem::MaybeUninit::zeroed #[cfg(not(no_global_oom_handling))] - #[unstable(feature = "new_uninit", issue = "63291")] + #[unstable(feature = "allocator_api", issue = "32838")] #[inline] pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Arc<[mem::MaybeUninit], A> { unsafe { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2530a37638757..f65e9bc8d8b5a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -363,6 +363,7 @@ #![feature(get_mut_unchecked)] #![feature(map_try_insert)] #![feature(new_uninit)] +#![feature(new_zeroed_alloc)] #![feature(slice_concat_trait)] #![feature(thin_box)] #![feature(try_reserve_kind)] From 90b4e17a1f6604db7f55b45b8b70c2db0afcec14 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Fri, 23 Aug 2024 09:28:30 +0200 Subject: [PATCH 09/17] CI: rfl: move to temporary commit Link: https://github.com/rust-lang/rust/pull/129416 Signed-off-by: Miguel Ojeda --- src/ci/docker/scripts/rfl-build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh index d690aac27fae6..389abb2fdd38c 100755 --- a/src/ci/docker/scripts/rfl-build.sh +++ b/src/ci/docker/scripts/rfl-build.sh @@ -2,7 +2,7 @@ set -euo pipefail -LINUX_VERSION=v6.11-rc1 +LINUX_VERSION=4c7864e81d8bbd51036dacf92fb0a400e13aaeee # Build rustc, rustdoc and cargo ../x.py build --stage 1 library rustdoc @@ -28,7 +28,7 @@ rm -rf linux || true # Download Linux at a specific commit mkdir -p linux git -C linux init -git -C linux remote add origin https://github.com/torvalds/linux.git +git -C linux remote add origin https://github.com/Rust-for-Linux/linux.git git -C linux fetch --depth 1 origin ${LINUX_VERSION} git -C linux checkout FETCH_HEAD From c36b5634cfde381fda497f71602158ce2c27ae5e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Aug 2024 18:34:28 +0200 Subject: [PATCH 10/17] Update minifier to 0.3.1 --- Cargo.lock | 7 +++++-- src/librustdoc/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2e2baea8e47c..724d7a0ed5512 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2230,9 +2230,12 @@ dependencies = [ [[package]] name = "minifier" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95bbbf96b9ac3482c2a25450b67a15ed851319bc5fabf3b40742ea9066e84282" +checksum = "9aa3f302fe0f8de065d4a2d1ed64f60204623cac58b80cd3c2a83a25d5a7d437" +dependencies = [ + "clap", +] [[package]] name = "minimal-lexical" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index b3fccbf6456e0..34332de80b365 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -12,7 +12,7 @@ rinja = { version = "0.3", default-features = false, features = ["config"] } base64 = "0.21.7" itertools = "0.12" indexmap = "2" -minifier = "0.3.0" +minifier = "0.3.1" pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false } regex = "1" rustdoc-json-types = { path = "../rustdoc-json-types" } From b9033bdd92aa697dee77fa581c22d418b5bdf308 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 24 Aug 2024 19:44:12 +0300 Subject: [PATCH 11/17] New `#[rustc_pub_transparent]` attribute --- compiler/rustc_feature/src/builtin_attrs.rs | 5 ++++ compiler/rustc_passes/messages.ftl | 4 +++ compiler/rustc_passes/src/check_attr.rs | 13 ++++++++++ compiler/rustc_passes/src/errors.rs | 9 +++++++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/cell.rs | 3 +++ library/core/src/mem/manually_drop.rs | 1 + library/core/src/mem/maybe_uninit.rs | 1 + library/core/src/pin.rs | 1 + tests/ui/attributes/rustc_pub_transparent.rs | 25 +++++++++++++++++++ .../attributes/rustc_pub_transparent.stderr | 23 +++++++++++++++++ 11 files changed, 86 insertions(+) create mode 100644 tests/ui/attributes/rustc_pub_transparent.rs create mode 100644 tests/ui/attributes/rustc_pub_transparent.stderr diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index d4c54b67f24d5..2747a14d60a5c 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -641,6 +641,11 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ErrorFollowing, EncodeCrossCrate::Yes, "rustc_deprecated_safe_2024 is supposed to be used in libstd only", ), + rustc_attr!( + rustc_pub_transparent, Normal, template!(Word), + WarnFollowing, EncodeCrossCrate::Yes, + "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation", + ), // ========================================================================== diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index dfc726efeb998..b377c9f52d640 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -657,6 +657,10 @@ passes_rustc_lint_opt_ty = `#[rustc_lint_opt_ty]` should be applied to a struct .label = not a struct +passes_rustc_pub_transparent = + attribute should be applied to `#[repr(transparent)]` types + .label = not a `#[repr(transparent)]` type + passes_rustc_safe_intrinsic = attribute should be applied to intrinsic functions .label = not an intrinsic function diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index c93fb5c23b1c4..9ca4bb09b3e17 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -245,6 +245,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_coroutine(attr, target); } [sym::linkage, ..] => self.check_linkage(attr, span, target), + [sym::rustc_pub_transparent, ..] => self.check_rustc_pub_transparent( attr.span, span, attrs), [ // ok sym::allow @@ -2381,6 +2382,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } } + + fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) { + if !attrs + .iter() + .filter(|attr| attr.has_name(sym::repr)) + .filter_map(|attr| attr.meta_item_list()) + .flatten() + .any(|nmi| nmi.has_name(sym::transparent)) + { + self.dcx().emit_err(errors::RustcPubTransparent { span, attr_span }); + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 1190e60f41f18..f6a57b7d0982d 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -622,6 +622,15 @@ pub struct RustcStdInternalSymbol { pub span: Span, } +#[derive(Diagnostic)] +#[diag(passes_rustc_pub_transparent)] +pub struct RustcPubTransparent { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_link_ordinal)] pub struct LinkOrdinal { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a2e94492f8c23..491d31b387cf8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1672,6 +1672,7 @@ symbols! { rustc_private, rustc_proc_macro_decls, rustc_promotable, + rustc_pub_transparent, rustc_reallocator, rustc_regions, rustc_reservation_impl, diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index d860f3415d982..5dd9721d3fee8 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -306,6 +306,7 @@ pub use once::OnceCell; /// See the [module-level documentation](self) for more. #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct Cell { value: UnsafeCell, } @@ -2055,6 +2056,7 @@ impl fmt::Display for RefMut<'_, T> { #[lang = "unsafe_cell"] #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct UnsafeCell { value: T, } @@ -2297,6 +2299,7 @@ impl UnsafeCell<*mut T> { /// See [`UnsafeCell`] for details. #[unstable(feature = "sync_unsafe_cell", issue = "95439")] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct SyncUnsafeCell { value: UnsafeCell, } diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 00c837041b697..be5cee2e85267 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -47,6 +47,7 @@ use crate::ptr; #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub struct ManuallyDrop { value: T, } diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index f920ab1792daf..c308def2f574a 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -237,6 +237,7 @@ use crate::{fmt, intrinsics, ptr, slice}; #[lang = "maybe_uninit"] #[derive(Copy)] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] pub union MaybeUninit { uninit: (), value: ManuallyDrop, diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 0569b8b762433..580e214e98b68 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1084,6 +1084,7 @@ use crate::{cmp, fmt}; #[lang = "pin"] #[fundamental] #[repr(transparent)] +#[cfg_attr(not(bootstrap), rustc_pub_transparent)] #[derive(Copy, Clone)] pub struct Pin { // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to: diff --git a/tests/ui/attributes/rustc_pub_transparent.rs b/tests/ui/attributes/rustc_pub_transparent.rs new file mode 100644 index 0000000000000..4508fa39baf8b --- /dev/null +++ b/tests/ui/attributes/rustc_pub_transparent.rs @@ -0,0 +1,25 @@ +#![feature(rustc_attrs, transparent_unions)] + +#[rustc_pub_transparent] +#[repr(transparent)] +union E { + value: T, + uninit: (), +} + +#[repr(transparent)] +#[rustc_pub_transparent] +struct S(T); + +#[rustc_pub_transparent] //~ ERROR attribute should be applied to `#[repr(transparent)]` types +#[repr(C)] +struct S1 { + A: u8, +} + +#[rustc_pub_transparent] //~ ERROR attribute should be applied to `#[repr(transparent)]` types +struct S2 { + value: T, +} + +fn main() {} diff --git a/tests/ui/attributes/rustc_pub_transparent.stderr b/tests/ui/attributes/rustc_pub_transparent.stderr new file mode 100644 index 0000000000000..1d1f9437cb2c1 --- /dev/null +++ b/tests/ui/attributes/rustc_pub_transparent.stderr @@ -0,0 +1,23 @@ +error: attribute should be applied to `#[repr(transparent)]` types + --> $DIR/rustc_pub_transparent.rs:14:1 + | +LL | #[rustc_pub_transparent] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[repr(C)] +LL | / struct S1 { +LL | | A: u8, +LL | | } + | |_- not a `#[repr(transparent)]` type + +error: attribute should be applied to `#[repr(transparent)]` types + --> $DIR/rustc_pub_transparent.rs:20:1 + | +LL | #[rustc_pub_transparent] + | ^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / struct S2 { +LL | | value: T, +LL | | } + | |_- not a `#[repr(transparent)]` type + +error: aborting due to 2 previous errors + From 06f2d73b2bd6f290a72d8041c957a08b3f6d50c7 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Sat, 24 Aug 2024 20:39:26 +0300 Subject: [PATCH 12/17] repr_transparent_external_private_fields: treat `rustc_pub_transparent` types as local --- .../rustc_hir_analysis/src/check/check.rs | 3 ++- ...ent-non-exhaustive-transparent-in-prose.rs | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 14c5f8d9f16da..728c3790098e7 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1259,7 +1259,8 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)), ty::Array(ty, _) => check_non_exhaustive(tcx, *ty), ty::Adt(def, args) => { - if !def.did().is_local() { + if !def.did().is_local() && !tcx.has_attr(def.did(), sym::rustc_pub_transparent) + { let non_exhaustive = def.is_variant_list_non_exhaustive() || def .variants() diff --git a/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs new file mode 100644 index 0000000000000..6ab34719f0664 --- /dev/null +++ b/tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs @@ -0,0 +1,25 @@ +//@ check-pass + +#![feature(sync_unsafe_cell)] +#![allow(unused)] +#![deny(repr_transparent_external_private_fields)] + +// https://github.com/rust-lang/rust/issues/129470 + +struct ZST; + +#[repr(transparent)] +struct TransparentWithManuallyDropZST { + value: i32, + md: std::mem::ManuallyDrop, + mu: std::mem::MaybeUninit, + p: std::pin::Pin, + pd: std::marker::PhantomData, + pp: std::marker::PhantomPinned, + c: std::cell::Cell, + uc: std::cell::UnsafeCell, + suc: std::cell::SyncUnsafeCell, + zst: ZST, +} + +fn main() {} From 300da9a910adda194898ee11c4f044956ee04563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 24 Aug 2024 20:36:56 +0000 Subject: [PATCH 13/17] only use rustc attr on nightly --- compiler/rustc_type_ir/src/search_graph/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index d47c9e725f350..418139c3aadc0 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -287,7 +287,7 @@ impl NestedGoals { } } - #[rustc_lint_query_instability] + #[cfg_attr(feature = "nightly", rustc_lint_query_instability)] #[allow(rustc::potential_query_instability)] fn iter(&self) -> impl Iterator + '_ { self.nested_goals.iter().map(|(i, p)| (*i, *p)) From 3e2763a2155d9a11ed6aaed4e813f782dc53b095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 24 Aug 2024 20:38:11 +0000 Subject: [PATCH 14/17] add missing associated item --- compiler/rustc_type_ir/src/outlives.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index bfcea6a81d313..e8afaf1a4809a 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -68,6 +68,9 @@ struct OutlivesCollector<'a, I: Interner> { } impl TypeVisitor for OutlivesCollector<'_, I> { + #[cfg(not(feature = "nightly"))] + type Result = (); + fn visit_ty(&mut self, ty: I::Ty) -> Self::Result { if !self.visited.insert(ty) { return; From ad855fe6db641755c528fb5b1cc0308f3a4bf607 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 24 Aug 2024 20:39:04 +0000 Subject: [PATCH 15/17] this needs the type for some reason --- compiler/rustc_type_ir/src/elaborate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index f30419c801f18..433c444e701cc 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -237,7 +237,7 @@ pub fn supertrait_def_ids( cx: I, trait_def_id: I::DefId, ) -> impl Iterator { - let mut set = HashSet::default(); + let mut set: HashSet = HashSet::default(); let mut stack = vec![trait_def_id]; set.insert(trait_def_id); From 902264b1a6c3d782df3242440cc6c5b866f982d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Sat, 24 Aug 2024 20:40:02 +0000 Subject: [PATCH 16/17] allow cfg(bootstrap) to avoid check-cfg warning on stable --- compiler/rustc_type_ir/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 2750838bbe99f..785fa5e386ae0 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -31,3 +31,6 @@ nightly = [ "rustc_index/nightly", "rustc_ast_ir/nightly" ] + +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)'] } From 56adf87213b22ef848fb8afd3b8180c0455456d7 Mon Sep 17 00:00:00 2001 From: binarycat Date: Sat, 24 Aug 2024 12:41:40 -0400 Subject: [PATCH 17/17] rewrite extract_curl_version again --- src/bootstrap/src/core/download.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index fd6f17130ee91..b5c55854eff58 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -21,23 +21,20 @@ fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> { config.try_run(cmd) } -fn extract_curl_version(out: &[u8]) -> (u16, u16) { - let out = &out[5..]; - let Some(i) = out.iter().position(|&x| x == b' ') else { return (0, 0) }; - let out = &out[..i]; - let Some(k) = out.iter().rev().position(|&x| x == b'.') else { return (0, 0) }; - let out = &out[..out.len() - k - 1]; - let Ok(s) = std::str::from_utf8(out) else { return (0, 0) }; - let parts = s.split('.').collect::>(); - let [s_major, s_minor] = &parts[..] else { return (0, 0) }; - let (Ok(major), Ok(minor)) = (s_major.parse(), s_minor.parse()) else { return (0, 0) }; - (major, minor) +fn extract_curl_version(out: &[u8]) -> semver::Version { + let out = String::from_utf8_lossy(out); + // The output should look like this: "curl .. ..." + out.lines() + .next() + .and_then(|line| line.split(" ").nth(1)) + .and_then(|version| semver::Version::parse(version).ok()) + .unwrap_or(semver::Version::new(1, 0, 0)) } -fn curl_version() -> (u16, u16) { +fn curl_version() -> semver::Version { let mut curl = Command::new("curl"); curl.arg("-V"); - let Ok(out) = curl.output() else { return (0, 0) }; + let Ok(out) = curl.output() else { return semver::Version::new(1, 0, 0) }; let out = out.stdout; extract_curl_version(&out) } @@ -253,7 +250,7 @@ impl Config { curl.arg("--progress-bar"); } // --retry-all-errors was added in 7.71.0, don't use it if curl is old. - if curl_version() > (7, 70) { + if curl_version() >= semver::Version::new(7, 71, 0) { curl.arg("--retry-all-errors"); } curl.arg(url);