about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-25 20:29:33 +0000
committerbors <bors@rust-lang.org>2024-08-25 20:29:33 +0000
commitc6db1ca3c93ad69692a4c4b5542f26fda4bf3aec (patch)
treefcf719f1bab239d66a9c8f94fba886de7b0c8afe
parent1a94d839be8b248b972b9e022cb940d56de72fa1 (diff)
parent86d5c5336295944de1754265fc3e32f062b1db9f (diff)
downloadrust-c6db1ca3c93ad69692a4c4b5542f26fda4bf3aec.tar.gz
rust-c6db1ca3c93ad69692a4c4b5542f26fda4bf3aec.zip
Auto merge of #129563 - matthiaskrgr:rollup-t6bai2d, r=matthiaskrgr
Rollup of 7 pull requests

Successful merges:

 - #129091 (add Box::as_ptr and Box::as_mut_ptr methods)
 - #129134 (bootstrap: improve error recovery flags to curl)
 - #129416 (library: Move unstable API of new_uninit to new features)
 - #129459 (handle stage0 `cargo` and `rustc` separately)
 - #129487 (repr_transparent_external_private_fields: special-case some std types)
 - #129511 (Update minifier to 0.3.1)
 - #129523 (Make `rustc_type_ir` build on stable)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock7
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs3
-rw-r--r--compiler/rustc_index/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs6
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs13
-rw-r--r--compiler/rustc_passes/src/errors.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_type_ir/Cargo.toml3
-rw-r--r--compiler/rustc_type_ir/src/elaborate.rs2
-rw-r--r--compiler/rustc_type_ir/src/outlives.rs3
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs2
-rw-r--r--library/alloc/src/boxed.rs98
-rw-r--r--library/alloc/src/rc.rs6
-rw-r--r--library/alloc/src/sync.rs10
-rw-r--r--library/alloc/src/vec/mod.rs3
-rw-r--r--library/core/src/cell.rs3
-rw-r--r--library/core/src/mem/manually_drop.rs1
-rw-r--r--library/core/src/mem/maybe_uninit.rs1
-rw-r--r--library/core/src/pin.rs1
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--src/bootstrap/bootstrap.py37
-rw-r--r--src/bootstrap/src/core/download.rs24
-rwxr-xr-xsrc/ci/docker/scripts/rfl-build.sh4
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--tests/ui/attributes/rustc_pub_transparent.rs25
-rw-r--r--tests/ui/attributes/rustc_pub_transparent.stderr23
-rw-r--r--tests/ui/repr/repr-transparent-non-exhaustive-transparent-in-prose.rs25
30 files changed, 291 insertions, 33 deletions
diff --git a/Cargo.lock b/Cargo.lock
index ddcc5b0864b..cc960fd9a43 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2226,9 +2226,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/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index d4c54b67f24..2747a14d60a 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_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 14c5f8d9f16..728c3790098 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/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index b5e4f02a8d1..b9d2a43206b 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/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 5bd7736a3f3..6886562d9b7 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 665ab2797f2..3e101c0c635 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()
     }
 }
 
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index dfc726efeb9..b377c9f52d6 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 c93fb5c23b1..9ca4bb09b3e 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 1190e60f41f..f6a57b7d098 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -623,6 +623,15 @@ pub struct RustcStdInternalSymbol {
 }
 
 #[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 {
     #[primary_span]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index db09c948a8e..2957105288b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1674,6 +1674,7 @@ symbols! {
         rustc_private,
         rustc_proc_macro_decls,
         rustc_promotable,
+        rustc_pub_transparent,
         rustc_reallocator,
         rustc_regions,
         rustc_reservation_impl,
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index 2750838bbe9..785fa5e386a 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)'] }
diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs
index f30419c801f..433c444e701 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<I: Interner>(
     cx: I,
     trait_def_id: I::DefId,
 ) -> impl Iterator<Item = I::DefId> {
-    let mut set = HashSet::default();
+    let mut set: HashSet<I::DefId> = HashSet::default();
     let mut stack = vec![trait_def_id];
 
     set.insert(trait_def_id);
diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs
index bfcea6a81d3..e8afaf1a480 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<I: Interner> TypeVisitor<I> 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;
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index d47c9e725f3..418139c3aad 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<X: Cx> NestedGoals<X> {
         }
     }
 
-    #[rustc_lint_query_instability]
+    #[cfg_attr(feature = "nightly", rustc_lint_query_instability)]
     #[allow(rustc::potential_query_instability)]
     fn iter(&self) -> impl Iterator<Item = (X::Input, UsageKind)> + '_ {
         self.nested_goals.iter().map(|(i, p)| (*i, *p))
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 7de41259599..caaf37f0465 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -293,6 +293,7 @@ impl<T> Box<T> {
     ///
     /// ```
     /// #![feature(new_uninit)]
+    /// #![feature(new_zeroed_alloc)]
     ///
     /// let zero = Box::<u32>::new_zeroed();
     /// let zero = unsafe { zero.assume_init() };
@@ -303,7 +304,7 @@ impl<T> Box<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() -> Box<mem::MaybeUninit<T>> {
         Self::new_zeroed_in(Global)
@@ -684,6 +685,7 @@ impl<T> Box<[T]> {
     /// # Examples
     ///
     /// ```
+    /// #![feature(new_zeroed_alloc)]
     /// #![feature(new_uninit)]
     ///
     /// let values = Box::<[u32]>::new_zeroed_slice(3);
@@ -694,7 +696,7 @@ impl<T> 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<T>]> {
         unsafe { RawVec::with_capacity_zeroed(len).into_box(len) }
@@ -955,6 +957,7 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
     /// # Examples
     ///
     /// ```
+    /// #![feature(box_uninit_write)]
     /// #![feature(new_uninit)]
     ///
     /// let big_box = Box::<[usize; 1024]>::new_uninit();
@@ -972,7 +975,7 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, 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<T, A> {
         unsafe {
@@ -1254,6 +1257,95 @@ impl<T: ?Sized, A: Allocator> Box<T, A> {
         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/rc.rs b/library/alloc/src/rc.rs
index bdee06154fa..f153aa6d3be 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -539,6 +539,7 @@ impl<T> Rc<T> {
     /// # Examples
     ///
     /// ```
+    /// #![feature(new_zeroed_alloc)]
     /// #![feature(new_uninit)]
     ///
     /// use std::rc::Rc;
@@ -551,7 +552,7 @@ impl<T> 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() -> Rc<mem::MaybeUninit<T>> {
         unsafe {
@@ -1000,6 +1001,7 @@ impl<T> Rc<[T]> {
     ///
     /// ```
     /// #![feature(new_uninit)]
+    /// #![feature(new_zeroed_alloc)]
     ///
     /// use std::rc::Rc;
     ///
@@ -1011,7 +1013,7 @@ impl<T> 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<T>]> {
         unsafe {
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 2c0d19b0ada..4a3522f1a64 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -542,6 +542,7 @@ impl<T> Arc<T> {
     /// # Examples
     ///
     /// ```
+    /// #![feature(new_zeroed_alloc)]
     /// #![feature(new_uninit)]
     ///
     /// use std::sync::Arc;
@@ -555,7 +556,7 @@ impl<T> 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() -> Arc<mem::MaybeUninit<T>> {
         unsafe {
@@ -1134,6 +1135,7 @@ impl<T> Arc<[T]> {
     /// # Examples
     ///
     /// ```
+    /// #![feature(new_zeroed_alloc)]
     /// #![feature(new_uninit)]
     ///
     /// use std::sync::Arc;
@@ -1147,7 +1149,7 @@ impl<T> 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<T>]> {
         unsafe {
@@ -1191,7 +1193,7 @@ impl<T, A: Allocator> 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<T>], A> {
         unsafe { Arc::from_ptr_in(Arc::allocate_for_slice_in(len, &alloc), alloc) }
@@ -1220,7 +1222,7 @@ impl<T, A: Allocator> 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<T>], A> {
         unsafe {
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index b4e0bc5fcbe..cfd2e4a1512 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1334,7 +1334,7 @@ impl<T, A: Allocator> Vec<T, A> {
         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<T, A: Allocator> Vec<T, A> {
     /// may still invalidate this pointer.
     /// See the second example below for how this guarantee can be used.
     ///
-    ///
     /// # Examples
     ///
     /// ```
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index d860f3415d9..5dd9721d3fe 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<T: ?Sized> {
     value: UnsafeCell<T>,
 }
@@ -2055,6 +2056,7 @@ impl<T: ?Sized + fmt::Display> 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<T: ?Sized> {
     value: T,
 }
@@ -2297,6 +2299,7 @@ impl<T> 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<T: ?Sized> {
     value: UnsafeCell<T>,
 }
diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs
index 00c837041b6..be5cee2e852 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<T: ?Sized> {
     value: T,
 }
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index f920ab1792d..c308def2f57 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<T> {
     uninit: (),
     value: ManuallyDrop<T>,
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index 0f9e6061c32..780e476f531 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<Ptr> {
     // FIXME(#93176): this field is made `#[unstable] #[doc(hidden)] pub` to:
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 2530a376387..f65e9bc8d8b 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)]
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 4e8e0fd2532..71f69e03a9f 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -79,6 +79,11 @@ def get(base, url, path, checksums, verbose=False):
                 eprint("removing", temp_path)
             os.unlink(temp_path)
 
+def curl_version():
+    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):
@@ -107,11 +112,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
@@ -533,9 +542,13 @@ class RustBuild(object):
         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 +569,6 @@ class RustBuild(object):
                     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 +580,16 @@ class RustBuild(object):
 
             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(
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index c225cc30146..1e3f8da5258 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -22,6 +22,24 @@ fn try_run(config: &Config, cmd: &mut Command) -> Result<(), ()> {
     config.try_run(cmd)
 }
 
+fn extract_curl_version(out: &[u8]) -> semver::Version {
+    let out = String::from_utf8_lossy(out);
+    // The output should look like this: "curl <major>.<minor>.<patch> ..."
+    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() -> semver::Version {
+    let mut curl = Command::new("curl");
+    curl.arg("-V");
+    let Ok(out) = curl.output() else { return semver::Version::new(1, 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 {
@@ -220,6 +238,8 @@ impl Config {
             "30", // timeout if cannot connect within 30 seconds
             "-o",
             tempfile.to_str().unwrap(),
+            "--continue-at",
+            "-",
             "--retry",
             "3",
             "-SRf",
@@ -230,6 +250,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 curl_version() >= semver::Version::new(7, 71, 0) {
+            curl.arg("--retry-all-errors");
+        }
         curl.arg(url);
         if !self.check_run(&mut curl) {
             if self.build.contains("windows-msvc") {
diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index d690aac27fa..389abb2fdd3 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
 
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index b3fccbf6456..34332de80b3 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" }
diff --git a/tests/ui/attributes/rustc_pub_transparent.rs b/tests/ui/attributes/rustc_pub_transparent.rs
new file mode 100644
index 00000000000..4508fa39baf
--- /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<T: Copy> {
+    value: T,
+    uninit: (),
+}
+
+#[repr(transparent)]
+#[rustc_pub_transparent]
+struct S<T>(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<T> {
+    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 00000000000..1d1f9437cb2
--- /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<T> {
+LL | |     value: T,
+LL | | }
+   | |_- not a `#[repr(transparent)]` type
+
+error: aborting due to 2 previous errors
+
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 00000000000..6ab34719f06
--- /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<ZST>,
+    mu: std::mem::MaybeUninit<ZST>,
+    p: std::pin::Pin<ZST>,
+    pd: std::marker::PhantomData<ZST>,
+    pp: std::marker::PhantomPinned,
+    c: std::cell::Cell<ZST>,
+    uc: std::cell::UnsafeCell<ZST>,
+    suc: std::cell::SyncUnsafeCell<ZST>,
+    zst: ZST,
+}
+
+fn main() {}