about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs64
-rw-r--r--compiler/rustc_passes/src/reachable.rs10
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs8
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs73
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs3
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs58
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--library/core/src/ptr/mod.rs3
-rw-r--r--library/std/src/keyword_docs.rs10
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs3
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else2.rs2
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else2.stderr21
-rw-r--r--tests/codegen/box-uninit-bytes.rs (renamed from tests/codegen/box-maybe-uninit.rs)14
-rw-r--r--tests/ui/cross-crate/auxiliary/static_init_aux.rs4
-rw-r--r--tests/ui/cross-crate/static-init.rs3
-rw-r--r--tests/ui/lint/reference_casting.rs11
-rw-r--r--tests/ui/lint/reference_casting.stderr47
-rw-r--r--triagebot.toml92
18 files changed, 383 insertions, 46 deletions
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 2577cabb3f0..883f6242b56 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -56,20 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
     }
 
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
-        // &mut <expr>
-        let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
-            expr
-        // <expr> = ...
-        } else if let ExprKind::Assign(expr, _, _) = expr.kind {
-            expr
-        // <expr> += ...
-        } else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
-            expr
-        } else {
-            return;
-        };
-
-        let ExprKind::Unary(UnOp::Deref, e) = &inner.kind else {
+        let Some((is_assignment, e)) = is_operation_we_care_about(cx, expr) else {
             return;
         };
 
@@ -86,15 +73,58 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
         cx.emit_spanned_lint(
             INVALID_REFERENCE_CASTING,
             expr.span,
-            if matches!(expr.kind, ExprKind::AddrOf(..)) {
-                InvalidReferenceCastingDiag::BorrowAsMut { orig_cast }
-            } else {
+            if is_assignment {
                 InvalidReferenceCastingDiag::AssignToRef { orig_cast }
+            } else {
+                InvalidReferenceCastingDiag::BorrowAsMut { orig_cast }
             },
         );
     }
 }
 
+fn is_operation_we_care_about<'tcx>(
+    cx: &LateContext<'tcx>,
+    e: &'tcx Expr<'tcx>,
+) -> Option<(bool, &'tcx Expr<'tcx>)> {
+    fn deref_assign_or_addr_of<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<(bool, &'tcx Expr<'tcx>)> {
+        // &mut <expr>
+        let inner = if let ExprKind::AddrOf(_, Mutability::Mut, expr) = expr.kind {
+            expr
+        // <expr> = ...
+        } else if let ExprKind::Assign(expr, _, _) = expr.kind {
+            expr
+        // <expr> += ...
+        } else if let ExprKind::AssignOp(_, expr, _) = expr.kind {
+            expr
+        } else {
+            return None;
+        };
+
+        if let ExprKind::Unary(UnOp::Deref, e) = &inner.kind {
+            Some((!matches!(expr.kind, ExprKind::AddrOf(..)), e))
+        } else {
+            None
+        }
+    }
+
+    fn ptr_write<'tcx>(
+        cx: &LateContext<'tcx>,
+        e: &'tcx Expr<'tcx>,
+    ) -> Option<(bool, &'tcx Expr<'tcx>)> {
+        if let ExprKind::Call(path, [arg_ptr, _arg_val]) = e.kind
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::ptr_write | sym::ptr_write_volatile | sym::ptr_write_unaligned))
+        {
+            Some((true, arg_ptr))
+        } else {
+            None
+        }
+    }
+
+    deref_assign_or_addr_of(e).or_else(|| ptr_write(cx, e))
+}
+
 fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> bool {
     let e = e.peel_blocks();
 
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index f9d34ea71ba..e62833b358b 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -98,15 +98,11 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
                 self.worklist.push(def_id);
             } else {
                 match res {
-                    // If this path leads to a constant, then we need to
-                    // recurse into the constant to continue finding
-                    // items that are reachable.
-                    Res::Def(DefKind::Const | DefKind::AssocConst, _) => {
+                    // Reachable constants and reachable statics can have their contents inlined
+                    // into other crates. Mark them as reachable and recurse into their body.
+                    Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::Static(_), _) => {
                         self.worklist.push(def_id);
                     }
-
-                    // If this wasn't a static, then the destination is
-                    // surely reachable.
                     _ => {
                         self.reachable_symbols.insert(def_id);
                     }
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 078ff67446f..ebacb7cce83 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -80,6 +80,10 @@ impl<'tcx> Tables<'tcx> {
         self.def_ids[impl_def.0]
     }
 
+    pub fn generic_def_id(&self, generic_def: &stable_mir::ty::GenericDef) -> DefId {
+        self.def_ids[generic_def.0]
+    }
+
     pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem {
         stable_mir::CrateItem(self.create_def_id(did))
     }
@@ -120,6 +124,10 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::TraitDef(self.create_def_id(did))
     }
 
+    pub fn generic_def(&mut self, did: DefId) -> stable_mir::ty::GenericDef {
+        stable_mir::ty::GenericDef(self.create_def_id(did))
+    }
+
     pub fn const_def(&mut self, did: DefId) -> stable_mir::ty::ConstDef {
         stable_mir::ty::ConstDef(self.create_def_id(did))
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 7e8ac9a141a..aea59c31379 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -10,7 +10,8 @@
 use crate::rustc_internal::{self, opaque};
 use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx};
 use crate::stable_mir::ty::{
-    allocation_filter, new_allocation, Const, FloatTy, IntTy, Movability, RigidTy, TyKind, UintTy,
+    allocation_filter, new_allocation, Const, FloatTy, GenericDef, GenericParamDef, IntTy,
+    Movability, RigidTy, TyKind, UintTy,
 };
 use crate::stable_mir::{self, Context};
 use rustc_hir as hir;
@@ -101,6 +102,12 @@ impl<'tcx> Context for Tables<'tcx> {
         let ty = self.types[ty.0];
         ty.stable(self)
     }
+
+    fn generics_of(&mut self, generic_def: &GenericDef) -> stable_mir::ty::Generics {
+        let def_id = self.generic_def_id(generic_def);
+        let generic_def = self.tcx.generics_of(def_id);
+        generic_def.stable(self)
+    }
 }
 
 pub struct Tables<'tcx> {
@@ -1205,3 +1212,67 @@ impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
         TraitRef { def_id: rustc_internal::trait_def(self.def_id), args: self.args.stable(tables) }
     }
 }
+
+impl<'tcx> Stable<'tcx> for ty::Generics {
+    type T = stable_mir::ty::Generics;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::Generics;
+
+        let params: Vec<_> = self.params.iter().map(|param| param.stable(tables)).collect();
+        let param_def_id_to_index =
+            params.iter().map(|param| (param.def_id, param.index)).collect();
+
+        Generics {
+            parent: self.parent.map(|did| tables.generic_def(did)),
+            parent_count: self.parent_count,
+            params,
+            param_def_id_to_index,
+            has_self: self.has_self,
+            has_late_bound_regions: self
+                .has_late_bound_regions
+                .as_ref()
+                .map(|late_bound_regions| late_bound_regions.stable(tables)),
+            host_effect_index: self.host_effect_index,
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for rustc_span::Span {
+    type T = stable_mir::ty::Span;
+
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+        opaque(self)
+    }
+}
+
+impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
+    type T = stable_mir::ty::GenericParamDefKind;
+
+    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::GenericParamDefKind;
+        match self {
+            ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime,
+            ty::GenericParamDefKind::Type { has_default, synthetic } => {
+                GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic }
+            }
+            ty::GenericParamDefKind::Const { has_default } => {
+                GenericParamDefKind::Const { has_default: *has_default }
+            }
+        }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef {
+    type T = stable_mir::ty::GenericParamDef;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        GenericParamDef {
+            name: self.name.to_string(),
+            def_id: tables.generic_def(self.def_id),
+            index: self.index,
+            pure_wrt_drop: self.pure_wrt_drop,
+            kind: self.kind.stable(tables),
+        }
+    }
+}
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
index 2ae334c6a95..8e38e394b98 100644
--- a/compiler/rustc_smir/src/stable_mir/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -15,7 +15,7 @@ use std::cell::Cell;
 
 use crate::rustc_smir::Tables;
 
-use self::ty::{ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind};
+use self::ty::{GenericDef, Generics, ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind};
 
 pub mod mir;
 pub mod ty;
@@ -110,6 +110,7 @@ pub trait Context {
     fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
     fn all_trait_impls(&mut self) -> ImplTraitDecls;
     fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
+    fn generics_of(&mut self, generic_def: &GenericDef) -> Generics;
     /// Get information about the local crate.
     fn local_crate(&self) -> Crate;
     /// Retrieve a list of all external crates.
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 7a6601f09da..fe7fef5d0c1 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -22,7 +22,7 @@ pub struct Const {
 
 type Ident = Opaque;
 pub(crate) type Region = Opaque;
-type Span = Opaque;
+pub type Span = Opaque;
 
 #[derive(Clone, Debug)]
 pub enum TyKind {
@@ -87,34 +87,37 @@ pub enum Movability {
     Movable,
 }
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct ForeignDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct FnDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct ClosureDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct GeneratorDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct ParamDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct BrNamedDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct AdtDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct AliasDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct TraitDef(pub(crate) DefId);
 
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub struct GenericDef(pub(crate) DefId);
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
 pub struct ConstDef(pub(crate) DefId);
 
 impl TraitDef {
@@ -132,6 +135,12 @@ impl ImplDef {
     }
 }
 
+impl GenericDef {
+    pub fn generics_of(&self) -> Generics {
+        with(|tcx| tcx.generics_of(self))
+    }
+}
+
 #[derive(Clone, Debug)]
 pub struct GenericArgs(pub Vec<GenericArgKind>);
 
@@ -461,3 +470,30 @@ pub struct TraitRef {
     pub def_id: TraitDef,
     pub args: GenericArgs,
 }
+
+#[derive(Clone, Debug)]
+pub struct Generics {
+    pub parent: Option<GenericDef>,
+    pub parent_count: usize,
+    pub params: Vec<GenericParamDef>,
+    pub param_def_id_to_index: Vec<(GenericDef, u32)>,
+    pub has_self: bool,
+    pub has_late_bound_regions: Option<Span>,
+    pub host_effect_index: Option<usize>,
+}
+
+#[derive(Clone, Debug)]
+pub enum GenericParamDefKind {
+    Lifetime,
+    Type { has_default: bool, synthetic: bool },
+    Const { has_default: bool },
+}
+
+#[derive(Clone, Debug)]
+pub struct GenericParamDef {
+    pub name: super::Symbol,
+    pub def_id: GenericDef,
+    pub index: u32,
+    pub pure_wrt_drop: bool,
+    pub kind: GenericParamDefKind,
+}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 28a2dfebcfe..8aec12f128e 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1179,6 +1179,9 @@ symbols! {
         ptr_offset_from,
         ptr_offset_from_unsigned,
         ptr_unique,
+        ptr_write,
+        ptr_write_unaligned,
+        ptr_write_volatile,
         pub_macro_rules,
         pub_restricted,
         public,
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 5f094ac4e7e..01e36044899 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1357,6 +1357,7 @@ pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+#[rustc_diagnostic_item = "ptr_write"]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn write<T>(dst: *mut T, src: T) {
     // Semantically, it would be fine for this to be implemented as a
@@ -1459,6 +1460,7 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
 #[inline]
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
 #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
+#[rustc_diagnostic_item = "ptr_write_unaligned"]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
     // SAFETY: the caller must guarantee that `dst` is valid for writes.
@@ -1607,6 +1609,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 /// ```
 #[inline]
 #[stable(feature = "volatile", since = "1.9.0")]
+#[rustc_diagnostic_item = "ptr_write_volatile"]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
     // SAFETY: the caller must uphold the safety contract for `volatile_store`.
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index eb46f4e54bb..873bfb6218b 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -1820,7 +1820,7 @@ mod true_keyword {}
 
 #[doc(keyword = "type")]
 //
-/// Define an alias for an existing type.
+/// Define an [alias] for an existing type.
 ///
 /// The syntax is `type Name = ExistingType;`.
 ///
@@ -1838,6 +1838,13 @@ mod true_keyword {}
 /// assert_eq!(m, k);
 /// ```
 ///
+/// A type can be generic:
+///
+/// ```rust
+/// # use std::sync::{Arc, Mutex};
+/// type ArcMutex<T> = Arc<Mutex<T>>;
+/// ```
+///
 /// In traits, `type` is used to declare an [associated type]:
 ///
 /// ```rust
@@ -1860,6 +1867,7 @@ mod true_keyword {}
 ///
 /// [`trait`]: keyword.trait.html
 /// [associated type]: ../reference/items/associated-items.html#associated-types
+/// [alias]: ../reference/items/type-aliases.html
 mod type_keyword {}
 
 #[doc(keyword = "unsafe")]
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index fdc35cd4ddf..98441e83eb4 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -10,6 +10,7 @@ use rustc_hir::{
     GenericArgs, Guard, HirId, HirIdMap, InlineAsmOperand, Let, Lifetime, LifetimeName, Pat, PatField, PatKind, Path,
     PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind, TypeBinding,
 };
+use rustc_hir::MatchSource::TryDesugar;
 use rustc_lexer::{tokenize, TokenKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::TypeckResults;
@@ -311,7 +312,7 @@ impl HirEqInterExpr<'_, '_, '_> {
                 lls == rls && self.eq_block(lb, rb) && both(ll, rl, |l, r| l.ident.name == r.ident.name)
             },
             (&ExprKind::Match(le, la, ref ls), &ExprKind::Match(re, ra, ref rs)) => {
-                ls == rs
+                (ls == rs || (matches!((ls, rs), (TryDesugar(_), TryDesugar(_)))))
                     && self.eq_expr(le, re)
                     && over(la, ra, |l, r| {
                         self.eq_pat(l.pat, r.pat)
diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.rs b/src/tools/clippy/tests/ui/if_same_then_else2.rs
index c545434efe5..0b171f21d0c 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else2.rs
+++ b/src/tools/clippy/tests/ui/if_same_then_else2.rs
@@ -98,7 +98,7 @@ fn if_same_then_else2() -> Result<&'static str, ()> {
     };
 
     if true {
-        // FIXME: should emit "this `if` has identical blocks"
+        //~^ ERROR: this `if` has identical blocks
         Ok("foo")?;
     } else {
         Ok("foo")?;
diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.stderr b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
index 37fe787d1de..56e5f3e45b2 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else2.stderr
+++ b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
@@ -83,6 +83,25 @@ LL | |     };
    | |_____^
 
 error: this `if` has identical blocks
+  --> $DIR/if_same_then_else2.rs:100:13
+   |
+LL |       if true {
+   |  _____________^
+LL | |
+LL | |         Ok("foo")?;
+LL | |     } else {
+   | |_____^
+   |
+note: same as this
+  --> $DIR/if_same_then_else2.rs:103:12
+   |
+LL |       } else {
+   |  ____________^
+LL | |         Ok("foo")?;
+LL | |     }
+   | |_____^
+
+error: this `if` has identical blocks
   --> $DIR/if_same_then_else2.rs:124:20
    |
 LL |       } else if true {
@@ -103,5 +122,5 @@ LL | |         return Ok(&foo[0..]);
 LL | |     }
    | |_____^
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/tests/codegen/box-maybe-uninit.rs b/tests/codegen/box-uninit-bytes.rs
index 282af99b067..732da0a1794 100644
--- a/tests/codegen/box-maybe-uninit.rs
+++ b/tests/codegen/box-uninit-bytes.rs
@@ -25,6 +25,20 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
     Box::new(MaybeUninit::uninit())
 }
 
+#[repr(align(1024))]
+pub struct LotsaPadding(usize);
+
+// Boxing a value with padding should not copy junk from the stack
+#[no_mangle]
+pub fn box_lotsa_padding() -> Box<LotsaPadding> {
+    // CHECK-LABEL: @box_lotsa_padding
+    // CHECK-NOT: alloca
+    // CHECK-NOT: getelementptr
+    // CHECK-NOT: memcpy
+    // CHECK-NOT: memset
+    Box::new(LotsaPadding(42))
+}
+
 // Hide the `allocalign` attribute in the declaration of __rust_alloc
 // from the CHECK-NOT above, and also verify the attributes got set reasonably.
 // CHECK: declare {{(dso_local )?}}noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
diff --git a/tests/ui/cross-crate/auxiliary/static_init_aux.rs b/tests/ui/cross-crate/auxiliary/static_init_aux.rs
index 3b664f43654..5e172ef3198 100644
--- a/tests/ui/cross-crate/auxiliary/static_init_aux.rs
+++ b/tests/ui/cross-crate/auxiliary/static_init_aux.rs
@@ -1,10 +1,14 @@
 pub static V: &u32 = &X;
 pub static F: fn() = f;
+pub static G: fn() = G0;
 
 static X: u32 = 42;
+static G0: fn() = g;
 
 pub fn v() -> *const u32 {
     V
 }
 
 fn f() {}
+
+fn g() {}
diff --git a/tests/ui/cross-crate/static-init.rs b/tests/ui/cross-crate/static-init.rs
index 2e893c5d9bf..0b50c41fc5e 100644
--- a/tests/ui/cross-crate/static-init.rs
+++ b/tests/ui/cross-crate/static-init.rs
@@ -1,9 +1,11 @@
+// Regression test for #84455 and #115052.
 // run-pass
 // aux-build:static_init_aux.rs
 extern crate static_init_aux as aux;
 
 static V: &u32 = aux::V;
 static F: fn() = aux::F;
+static G: fn() = aux::G;
 
 fn v() -> *const u32 {
     V
@@ -12,4 +14,5 @@ fn v() -> *const u32 {
 fn main() {
     assert_eq!(aux::v(), crate::v());
     F();
+    G();
 }
diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs
index 6c38bca3daa..92d985948ec 100644
--- a/tests/ui/lint/reference_casting.rs
+++ b/tests/ui/lint/reference_casting.rs
@@ -71,6 +71,11 @@ unsafe fn assign_to_ref() {
     //~^ ERROR assigning to `&T` is undefined behavior
     *std::mem::transmute::<_, *mut i32>(num) += 1;
     //~^ ERROR assigning to `&T` is undefined behavior
+    std::ptr::write(
+    //~^ ERROR assigning to `&T` is undefined behavior
+        std::mem::transmute::<*const i32, *mut i32>(num),
+        -1i32,
+    );
 
     let value = num as *const i32 as *mut i32;
     *value = 1;
@@ -79,6 +84,12 @@ unsafe fn assign_to_ref() {
     //~^ ERROR assigning to `&T` is undefined behavior
     *(num as *const _ as usize as *mut i32) = 2;
     //~^ ERROR assigning to `&T` is undefined behavior
+    std::ptr::write(value, 2);
+    //~^ ERROR assigning to `&T` is undefined behavior
+    std::ptr::write_unaligned(value, 2);
+    //~^ ERROR assigning to `&T` is undefined behavior
+    std::ptr::write_volatile(value, 2);
+    //~^ ERROR assigning to `&T` is undefined behavior
 
     unsafe fn generic_assign_to_ref<T>(this: &T, a: T) {
         *(this as *const _ as *mut _) = a;
diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr
index 7ff9b76a85e..c1589f13835 100644
--- a/tests/ui/lint/reference_casting.stderr
+++ b/tests/ui/lint/reference_casting.stderr
@@ -131,7 +131,17 @@ LL |     *std::mem::transmute::<_, *mut i32>(num) += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:76:5
+  --> $DIR/reference_casting.rs:74:5
+   |
+LL | /     std::ptr::write(
+LL | |
+LL | |         std::mem::transmute::<*const i32, *mut i32>(num),
+LL | |         -1i32,
+LL | |     );
+   | |_____^
+
+error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:81:5
    |
 LL |     let value = num as *const i32 as *mut i32;
    |                 ----------------------------- casting happend here
@@ -139,22 +149,49 @@ LL |     *value = 1;
    |     ^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:78:5
+  --> $DIR/reference_casting.rs:83:5
    |
 LL |     *(num as *const i32).cast::<i32>().cast_mut() = 2;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:80:5
+  --> $DIR/reference_casting.rs:85:5
    |
 LL |     *(num as *const _ as usize as *mut i32) = 2;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:84:9
+  --> $DIR/reference_casting.rs:87:5
+   |
+LL |     let value = num as *const i32 as *mut i32;
+   |                 ----------------------------- casting happend here
+...
+LL |     std::ptr::write(value, 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:89:5
+   |
+LL |     let value = num as *const i32 as *mut i32;
+   |                 ----------------------------- casting happend here
+...
+LL |     std::ptr::write_unaligned(value, 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:91:5
+   |
+LL |     let value = num as *const i32 as *mut i32;
+   |                 ----------------------------- casting happend here
+...
+LL |     std::ptr::write_volatile(value, 2);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:95:9
    |
 LL |         *(this as *const _ as *mut _) = a;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 25 previous errors
+error: aborting due to 29 previous errors
 
diff --git a/triagebot.toml b/triagebot.toml
index 2f380ef1dda..aef5b5bb8dc 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -177,6 +177,98 @@ exclude_labels = [
     "T-*",
 ]
 
+[autolabel."O-android"]
+trigger_files = [
+    "library/std/src/os/android"
+]
+
+[autolabel."O-fuchsia"]
+trigger_files = [
+    "library/std/src/os/fuchsia"
+]
+
+[autolabel."O-hermit"]
+trigger_files = [
+    "library/std/src/sys/hermit",
+    "library/std/src/os/hermit"
+]
+
+[autolabel."O-ios"]
+trigger_files = [
+    "library/std/src/os/ios"
+]
+
+[autolabel."O-itron"]
+trigger_files = [
+    "library/std/src/sys/itron"
+]
+
+[autolabel."O-linux"]
+trigger_files = [
+    "library/std/src/os/linux"
+]
+
+[autolabel."O-macos"]
+trigger_files = [
+    "library/std/src/os/macos"
+]
+
+[autolabel."O-netbsd"]
+trigger_files = [
+    "library/std/src/os/netbsd"
+]
+
+[autolabel."O-redox"]
+trigger_files = [
+    "library/std/src/os/redox"
+]
+
+[autolabel."O-SGX"]
+trigger_files = [
+    "library/std/src/sys/sgx",
+    "library/std/src/os/fortanix_sgx"
+]
+
+[autolabel."O-solaris"]
+trigger_files = [
+    "library/std/src/os/solaris"
+]
+
+[autolabel."O-solid"]
+trigger_files = [
+    "library/std/src/sys/solid",
+    "library/std/src/os/solid"
+]
+
+[autolabel."O-unix"]
+trigger_files = [
+    "library/std/src/sys/unix",
+    "library/std/src/os/unix"
+]
+
+[autolabel."O-wasi"]
+trigger_files = [
+    "library/std/src/sys/wasi",
+    "library/std/src/os/wasi"
+]
+
+[autolabel."O-wasm"]
+trigger_files = [
+    "library/std/src/sys/wasm",
+    "library/std/src/os/wasm"
+]
+
+[autolabel."O-watchos"]
+trigger_files = [
+    "library/std/src/os/watchos"
+]
+
+[autolabel."O-windows"]
+trigger_files = [
+    "library/std/src/sys/windows",
+    "library/std/src/os/windows"
+]
+
 [autolabel."T-bootstrap"]
 trigger_files = [
     "x.py",