about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs1
-rw-r--r--compiler/rustc_metadata/src/locator.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs31
-rw-r--r--compiler/rustc_passes/src/check_attr.rs42
-rw-r--r--compiler/rustc_passes/src/lib.rs3
-rw-r--r--compiler/rustc_passes/src/liveness.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs137
-rw-r--r--compiler/rustc_typeck/src/lib.rs22
-rw-r--r--library/core/src/fmt/num.rs3
-rw-r--r--library/core/src/num/int_macros.rs10
-rw-r--r--library/core/tests/fmt/num.rs1
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs16
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr3
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/closures.stderr3
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr6
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr9
-rw-r--r--src/test/ui/const-generics/issues/issue-67375.full.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-67945-2.full.stderr3
-rw-r--r--src/test/ui/duplicate_doc_alias.rs9
-rw-r--r--src/test/ui/duplicate_doc_alias.stderr24
-rw-r--r--src/test/ui/mir-dataflow/liveness-enum.rs22
-rw-r--r--src/test/ui/mir-dataflow/liveness-enum.stderr10
-rw-r--r--src/test/ui/proc-macro/generate-mod.stderr72
-rw-r--r--src/test/ui/suggestions/ignore-nested-field-binding.fixed20
-rw-r--r--src/test/ui/suggestions/ignore-nested-field-binding.rs20
-rw-r--r--src/test/ui/suggestions/ignore-nested-field-binding.stderr20
-rw-r--r--src/test/ui/typeck/issue-88609.rs19
27 files changed, 455 insertions, 80 deletions
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 5830ce26fea..9d56bc193fb 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1960,6 +1960,7 @@ declare_lint! {
     "detects proc macro derives using inaccessible names from parent modules",
     @future_incompatible = FutureIncompatibleInfo {
         reference: "issue #83583 <https://github.com/rust-lang/rust/issues/83583>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
     };
 }
 
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index abdac78ae24..9b1ea3b4c4c 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -740,7 +740,9 @@ fn get_metadata_section(
             // Header is okay -> inflate the actual metadata
             let compressed_bytes = &buf[header_len..];
             debug!("inflating {} bytes of compressed metadata", compressed_bytes.len());
-            let mut inflated = Vec::new();
+            // Assume the decompressed data will be at least the size of the compressed data, so we
+            // don't have to grow the buffer as much.
+            let mut inflated = Vec::with_capacity(compressed_bytes.len());
             match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) {
                 Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()),
                 Err(_) => {
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 0039d3188d5..3e2548845e2 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -11,6 +11,37 @@ use crate::{AnalysisDomain, Backward, GenKill, GenKillAnalysis};
 /// exist. See [this `mir-dataflow` test][flow-test] for an example. You almost never want to use
 /// this analysis without also looking at the results of [`MaybeBorrowedLocals`].
 ///
+/// ## Field-(in)sensitivity
+///
+/// As the name suggests, this analysis is field insensitive. If a projection of a variable `x` is
+/// assigned to (e.g. `x.0 = 42`), it does not "define" `x` as far as liveness is concerned. In fact,
+/// such an assignment is currently marked as a "use" of `x` in an attempt to be maximally
+/// conservative.
+///
+/// ## Enums and `SetDiscriminant`
+///
+/// Assigning a literal value to an `enum` (e.g. `Option<i32>`), does not result in a simple
+/// assignment of the form `_1 = /*...*/` in the MIR. For example, the following assignment to `x`:
+///
+/// ```
+/// x = Some(4);
+/// ```
+///
+/// compiles to this MIR
+///
+/// ```
+/// ((_1 as Some).0: i32) = const 4_i32;
+/// discriminant(_1) = 1;
+/// ```
+///
+/// However, `MaybeLiveLocals` **does** mark `x` (`_1`) as "killed" after a statement like this.
+/// That's because it treats the `SetDiscriminant` operation as a definition of `x`, even though
+/// the writes that actually initialized the locals happened earlier.
+///
+/// This makes `MaybeLiveLocals` unsuitable for certain classes of optimization normally associated
+/// with a live variables analysis, notably dead-store elimination. It's a dirty hack, but it works
+/// okay for the generator state transform (currently the main consumuer of this analysis).
+///
 /// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals
 /// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs
 /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 3e59fc4f551..e7b2a018680 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -9,7 +9,7 @@ use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
 
 use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, NestedMetaItem};
-use rustc_data_structures::stable_set::FxHashSet;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability};
 use rustc_feature::{AttributeType, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
@@ -66,6 +66,7 @@ impl CheckAttrVisitor<'tcx> {
         target: Target,
         item: Option<ItemLike<'_>>,
     ) {
+        let mut doc_aliases = FxHashMap::default();
         let mut is_valid = true;
         let mut specified_inline = None;
         let mut seen = FxHashSet::default();
@@ -79,7 +80,13 @@ impl CheckAttrVisitor<'tcx> {
                 sym::track_caller => {
                     self.check_track_caller(hir_id, &attr.span, attrs, span, target)
                 }
-                sym::doc => self.check_doc_attrs(attr, hir_id, target, &mut specified_inline),
+                sym::doc => self.check_doc_attrs(
+                    attr,
+                    hir_id,
+                    target,
+                    &mut specified_inline,
+                    &mut doc_aliases,
+                ),
                 sym::no_link => self.check_no_link(hir_id, &attr, span, target),
                 sym::export_name => self.check_export_name(hir_id, &attr, span, target),
                 sym::rustc_layout_scalar_valid_range_start
@@ -512,6 +519,7 @@ impl CheckAttrVisitor<'tcx> {
         hir_id: HirId,
         target: Target,
         is_list: bool,
+        aliases: &mut FxHashMap<String, Span>,
     ) -> bool {
         let tcx = self.tcx;
         let err_fn = move |span: Span, msg: &str| {
@@ -582,17 +590,38 @@ impl CheckAttrVisitor<'tcx> {
         if &*item_name.as_str() == doc_alias {
             return err_fn(meta.span(), "is the same as the item's name");
         }
+        let span = meta.span();
+        if let Err(entry) = aliases.try_insert(doc_alias.to_owned(), span) {
+            self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, span, |lint| {
+                lint.build("doc alias is duplicated")
+                    .span_label(*entry.entry.get(), "first defined here")
+                    .emit();
+            });
+        }
         true
     }
 
-    fn check_doc_alias(&self, meta: &NestedMetaItem, hir_id: HirId, target: Target) -> bool {
+    fn check_doc_alias(
+        &self,
+        meta: &NestedMetaItem,
+        hir_id: HirId,
+        target: Target,
+        aliases: &mut FxHashMap<String, Span>,
+    ) -> bool {
         if let Some(values) = meta.meta_item_list() {
             let mut errors = 0;
             for v in values {
                 match v.literal() {
                     Some(l) => match l.kind {
                         LitKind::Str(s, _) => {
-                            if !self.check_doc_alias_value(v, &s.as_str(), hir_id, target, true) {
+                            if !self.check_doc_alias_value(
+                                v,
+                                &s.as_str(),
+                                hir_id,
+                                target,
+                                true,
+                                aliases,
+                            ) {
                                 errors += 1;
                             }
                         }
@@ -621,7 +650,7 @@ impl CheckAttrVisitor<'tcx> {
             }
             errors == 0
         } else if let Some(doc_alias) = meta.value_str().map(|s| s.to_string()) {
-            self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false)
+            self.check_doc_alias_value(meta, &doc_alias, hir_id, target, false, aliases)
         } else {
             self.tcx
                 .sess
@@ -858,6 +887,7 @@ impl CheckAttrVisitor<'tcx> {
         hir_id: HirId,
         target: Target,
         specified_inline: &mut Option<(bool, Span)>,
+        aliases: &mut FxHashMap<String, Span>,
     ) -> bool {
         let mut is_valid = true;
 
@@ -867,7 +897,7 @@ impl CheckAttrVisitor<'tcx> {
                     match i_meta.name_or_empty() {
                         sym::alias
                             if !self.check_attr_not_crate_level(&meta, hir_id, "alias")
-                                || !self.check_doc_alias(&meta, hir_id, target) =>
+                                || !self.check_doc_alias(&meta, hir_id, target, aliases) =>
                         {
                             is_valid = false
                         }
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index f583a5d58d5..4adec3c4f60 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -9,8 +9,9 @@
 #![feature(in_band_lifetimes)]
 #![feature(format_args_capture)]
 #![feature(iter_zip)]
-#![feature(nll)]
+#![feature(map_try_insert)]
 #![feature(min_specialization)]
+#![feature(nll)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 0d7abeba1a7..3d7a215754a 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -265,12 +265,13 @@ impl IrMaps<'tcx> {
         self.capture_info_map.insert(hir_id, Rc::new(cs));
     }
 
-    fn add_from_pat(&mut self, pat: &hir::Pat<'tcx>) {
+    fn collect_shorthand_field_ids(&self, pat: &hir::Pat<'tcx>) -> HirIdSet {
         // For struct patterns, take note of which fields used shorthand
         // (`x` rather than `x: x`).
         let mut shorthand_field_ids = HirIdSet::default();
         let mut pats = VecDeque::new();
         pats.push_back(pat);
+
         while let Some(pat) = pats.pop_front() {
             use rustc_hir::PatKind::*;
             match &pat.kind {
@@ -278,8 +279,10 @@ impl IrMaps<'tcx> {
                     pats.extend(inner_pat.iter());
                 }
                 Struct(_, fields, _) => {
-                    let ids = fields.iter().filter(|f| f.is_shorthand).map(|f| f.pat.hir_id);
-                    shorthand_field_ids.extend(ids);
+                    let (short, not_short): (Vec<&_>, Vec<&_>) =
+                        fields.iter().partition(|f| f.is_shorthand);
+                    shorthand_field_ids.extend(short.iter().map(|f| f.pat.hir_id));
+                    pats.extend(not_short.iter().map(|f| f.pat));
                 }
                 Ref(inner_pat, _) | Box(inner_pat) => {
                     pats.push_back(inner_pat);
@@ -296,6 +299,12 @@ impl IrMaps<'tcx> {
             }
         }
 
+        return shorthand_field_ids;
+    }
+
+    fn add_from_pat(&mut self, pat: &hir::Pat<'tcx>) {
+        let shorthand_field_ids = self.collect_shorthand_field_ids(pat);
+
         pat.each_binding(|_, hir_id, _, ident| {
             self.add_live_node_for_node(hir_id, VarDefNode(ident.span, hir_id));
             self.add_variable(Local(LocalInfo {
@@ -373,15 +382,13 @@ impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> {
     }
 
     fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
+        let shorthand_field_ids = self.collect_shorthand_field_ids(param.pat);
         param.pat.each_binding(|_bm, hir_id, _x, ident| {
             let var = match param.pat.kind {
-                rustc_hir::PatKind::Struct(_, fields, _) => Local(LocalInfo {
+                rustc_hir::PatKind::Struct(..) => Local(LocalInfo {
                     id: hir_id,
                     name: ident.name,
-                    is_shorthand: fields
-                        .iter()
-                        .find(|f| f.ident == ident)
-                        .map_or(false, |f| f.is_shorthand),
+                    is_shorthand: shorthand_field_ids.contains(&hir_id),
                 }),
                 _ => Param(hir_id, ident.name),
             };
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 24fa5007f1e..25ec9682d84 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -236,16 +236,27 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
         self.body.exprs[self.body_id].span
     }
 
-    fn error(&mut self, span: Option<Span>, msg: &str) -> Result<!, ErrorReported> {
+    fn error(&mut self, span: Span, msg: &str) -> Result<!, ErrorReported> {
         self.tcx
             .sess
             .struct_span_err(self.root_span(), "overly complex generic constant")
-            .span_label(span.unwrap_or(self.root_span()), msg)
+            .span_label(span, msg)
             .help("consider moving this anonymous constant into a `const` function")
             .emit();
 
         Err(ErrorReported)
     }
+    fn maybe_supported_error(&mut self, span: Span, msg: &str) -> Result<!, ErrorReported> {
+        self.tcx
+            .sess
+            .struct_span_err(self.root_span(), "overly complex generic constant")
+            .span_label(span, msg)
+            .help("consider moving this anonymous constant into a `const` function")
+            .note("this operation may be supported in the future")
+            .emit();
+
+        Err(ErrorReported)
+    }
 
     fn new(
         tcx: TyCtxt<'tcx>,
@@ -337,14 +348,14 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
         Ok(match &node.kind {
             // I dont know if handling of these 3 is correct
             &ExprKind::Scope { value, .. } => self.recurse_build(value)?,
-            &ExprKind::PlaceTypeAscription { source, .. } |
-            &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
+            &ExprKind::PlaceTypeAscription { source, .. }
+            | &ExprKind::ValueTypeAscription { source, .. } => self.recurse_build(source)?,
 
             // subtle: associated consts are literals this arm handles
             // `<T as Trait>::ASSOC` as well as `12`
             &ExprKind::Literal { literal, .. } => self.nodes.push(Node::Leaf(literal)),
 
-            ExprKind::Call { fun, args,  .. } => {
+            ExprKind::Call { fun, args, .. } => {
                 let fun = self.recurse_build(*fun)?;
 
                 let mut new_args = Vec::<NodeId>::with_capacity(args.len());
@@ -353,7 +364,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
                 }
                 let new_args = self.tcx.arena.alloc_slice(&new_args);
                 self.nodes.push(Node::FunctionCall(fun, new_args))
-            },
+            }
             &ExprKind::Binary { op, lhs, rhs } if Self::check_binop(op) => {
                 let lhs = self.recurse_build(lhs)?;
                 let rhs = self.recurse_build(rhs)?;
@@ -362,7 +373,7 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
             &ExprKind::Unary { op, arg } if Self::check_unop(op) => {
                 let arg = self.recurse_build(arg)?;
                 self.nodes.push(Node::UnaryOp(op, arg))
-            },
+            }
             // This is necessary so that the following compiles:
             //
             // ```
@@ -370,60 +381,100 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
             //     bar::<{ N + 1 }>();
             // }
             // ```
-            ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. }} => self.recurse_build(*e)?,
+            ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. } } => {
+                self.recurse_build(*e)?
+            }
             // `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
             // "coercion cast" i.e. using a coercion or is a no-op.
             // This is important so that `N as usize as usize` doesnt unify with `N as usize`. (untested)
             &ExprKind::Use { source } => {
                 let arg = self.recurse_build(source)?;
                 self.nodes.push(Node::Cast(abstract_const::CastKind::Use, arg, node.ty))
-            },
+            }
             &ExprKind::Cast { source } => {
                 let arg = self.recurse_build(source)?;
                 self.nodes.push(Node::Cast(abstract_const::CastKind::As, arg, node.ty))
-            },
+            }
 
             // FIXME(generic_const_exprs): We may want to support these.
             ExprKind::AddressOf { .. }
             | ExprKind::Borrow { .. }
-            | ExprKind::Deref { .. }
-            | ExprKind::Repeat { .. }
-            | ExprKind::Array { .. }
-            | ExprKind::Block { .. }
-            | ExprKind::NeverToAny { .. }
-            | ExprKind::Tuple { .. }
-            | ExprKind::Index { .. }
-            | ExprKind::Field { .. }
-            | ExprKind::ConstBlock { .. }
-            | ExprKind::Adt(_) => self.error(
-                    Some(node.span),
-                    "unsupported operation in generic constant, this may be supported in the future",
+            | ExprKind::Deref { .. } => self.maybe_supported_error(
+                node.span,
+                "dereferencing is not supported in generic constants",
+            )?,
+            ExprKind::Repeat { .. } | ExprKind::Array { .. } =>  self.maybe_supported_error(
+                node.span,
+                "array construction is not supported in generic constants",
+            )?,
+            ExprKind::Block { .. } => self.maybe_supported_error(
+                node.span,
+                "blocks are not supported in generic constant",
+            )?,
+            ExprKind::NeverToAny { .. } => self.maybe_supported_error(
+                node.span,
+                "converting nevers to any is not supported in generic constant",
+            )?,
+            ExprKind::Tuple { .. } => self.maybe_supported_error(
+                node.span,
+                "tuple construction is not supported in generic constants",
+            )?,
+            ExprKind::Index { .. } => self.maybe_supported_error(
+                node.span,
+                "indexing is not supported in generic constant",
+            )?,
+            ExprKind::Field { .. } => self.maybe_supported_error(
+                node.span,
+                "field access is not supported in generic constant",
+            )?,
+            ExprKind::ConstBlock { .. } => self.maybe_supported_error(
+                node.span,
+                "const blocks are not supported in generic constant",
+            )?,
+            ExprKind::Adt(_) => self.maybe_supported_error(
+                node.span,
+                "struct/enum construction is not supported in generic constants",
+            )?,
+            // dont know if this is correct
+            ExprKind::Pointer { .. } =>
+                self.error(node.span, "pointer casts are not allowed in generic constants")?,
+            ExprKind::Yield { .. } =>
+                self.error(node.span, "generator control flow is not allowed in generic constants")?,
+            ExprKind::Continue { .. } | ExprKind::Break { .. } | ExprKind::Loop { .. } => self
+                .error(
+                    node.span,
+                    "loops and loop control flow are not supported in generic constants",
                 )?,
+            ExprKind::Box { .. } =>
+                self.error(node.span, "allocations are not allowed in generic constants")?,
+
+            ExprKind::Unary { .. } => unreachable!(),
+            // we handle valid unary/binary ops above
+            ExprKind::Binary { .. } =>
+                self.error(node.span, "unsupported binary operation in generic constants")?,
+            ExprKind::LogicalOp { .. } =>
+                self.error(node.span, "unsupported operation in generic constants, short-circuiting operations would imply control flow")?,
+            ExprKind::Assign { .. } | ExprKind::AssignOp { .. } => {
+                self.error(node.span, "assignment is not supported in generic constants")?
+            }
+            ExprKind::Closure { .. } | ExprKind::Return { .. } => self.error(
+                node.span,
+                "closures and function keywords are not supported in generic constants",
+            )?,
+            // let expressions imply control flow
+            ExprKind::Match { .. } | ExprKind::If { .. } | ExprKind::Let { .. } =>
+                self.error(node.span, "control flow is not supported in generic constants")?,
+            ExprKind::LlvmInlineAsm { .. } | ExprKind::InlineAsm { .. } => {
+                self.error(node.span, "assembly is not supported in generic constants")?
+            }
 
-            ExprKind::Match { .. }
             // we dont permit let stmts so `VarRef` and `UpvarRef` cant happen
-            | ExprKind::VarRef { .. }
+            ExprKind::VarRef { .. }
             | ExprKind::UpvarRef { .. }
-            | ExprKind::Closure { .. }
-            | ExprKind::Let { .. } // let expressions imply control flow
-            | ExprKind::Loop { .. }
-            | ExprKind::Assign { .. }
             | ExprKind::StaticRef { .. }
-            | ExprKind::LogicalOp { .. }
-            // we handle valid unary/binary ops above
-            | ExprKind::Unary { .. }
-            | ExprKind::Binary { .. }
-            | ExprKind::Break { .. }
-            | ExprKind::Continue { .. }
-            | ExprKind::If { .. }
-            | ExprKind::Pointer { .. } // dont know if this is correct
-            | ExprKind::ThreadLocalRef(_)
-            | ExprKind::LlvmInlineAsm { .. }
-            | ExprKind::Return { .. }
-            | ExprKind::Box { .. } // allocations not allowed in constants
-            | ExprKind::AssignOp { .. }
-            | ExprKind::InlineAsm { .. }
-            | ExprKind::Yield { .. } => self.error(Some(node.span), "unsupported operation in generic constant")?,
+            | ExprKind::ThreadLocalRef(_) => {
+                self.error(node.span, "unsupported operation in generic constant")?
+            }
         })
     }
 }
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 8ff074e2fe5..65eedd2daaf 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -107,6 +107,7 @@ use rustc_middle::util;
 use rustc_session::config::EntryFnType;
 use rustc_span::{symbol::sym, Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
     self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _,
@@ -328,7 +329,26 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
                 ObligationCauseCode::MainFunctionType,
             );
             let mut fulfillment_cx = traits::FulfillmentContext::new();
-            fulfillment_cx.register_bound(&infcx, ty::ParamEnv::empty(), return_ty, term_id, cause);
+            // normalize any potential projections in the return type, then add
+            // any possible obligations to the fulfillment context.
+            // HACK(ThePuzzlemaker) this feels symptomatic of a problem within
+            // checking trait fulfillment, not this here. I'm not sure why it
+            // works in the example in `fn test()` given in #88609? This also
+            // probably isn't the best way to do this.
+            let InferOk { value: norm_return_ty, obligations } = infcx
+                .partially_normalize_associated_types_in(
+                    cause.clone(),
+                    ty::ParamEnv::empty(),
+                    return_ty,
+                );
+            fulfillment_cx.register_predicate_obligations(&infcx, obligations);
+            fulfillment_cx.register_bound(
+                &infcx,
+                ty::ParamEnv::empty(),
+                norm_return_ty,
+                term_id,
+                cause,
+            );
             if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
                 infcx.report_fulfillment_errors(&err, None, false);
                 error = true;
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index db45640df48..05ca50a97a6 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -305,7 +305,6 @@ macro_rules! impl_Exp {
                     n /= 10;
                     exponent += 1;
                 }
-                let trailing_zeros = exponent;
 
                 let (added_precision, subtracted_precision) = match f.precision() {
                     Some(fmt_prec) => {
@@ -333,7 +332,7 @@ macro_rules! impl_Exp {
                         n += 1;
                     }
                 }
-                (n, exponent, trailing_zeros, added_precision)
+                (n, exponent, exponent, added_precision)
             };
 
             // 39 digits (worst case u128) + . = 40
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index f1dcdf2c1aa..9d46948ce02 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1533,9 +1533,8 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
-            // Using `&` helps LLVM see that it is the same check made in division.
-            if unlikely!((self == Self::MIN) & (rhs == -1)) {
-                (0, true)
+            if unlikely!(rhs == -1) {
+                (0, self == Self::MIN)
             } else {
                 (self % rhs, false)
             }
@@ -1565,9 +1564,8 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[inline]
         pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
-            // Using `&` helps LLVM see that it is the same check made in division.
-            if unlikely!((self == Self::MIN) & (rhs == -1)) {
-                (0, true)
+            if unlikely!(rhs == -1) {
+                (0, self == Self::MIN)
             } else {
                 (self.rem_euclid(rhs), false)
             }
diff --git a/library/core/tests/fmt/num.rs b/library/core/tests/fmt/num.rs
index 275a1d062ca..b958422d14f 100644
--- a/library/core/tests/fmt/num.rs
+++ b/library/core/tests/fmt/num.rs
@@ -146,6 +146,7 @@ fn test_format_int_exp_precision() {
     assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000)));
     //test zero precision
     assert_eq!(format!("{:.0e}", 1), format!("1e0",));
+    assert_eq!(format!("{:.0e}", 35), format!("4e1",));
 
     //test padding with precision (and sign)
     assert_eq!(format!("{:+10.3e}", 1), "  +1.000e0");
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 8c33051cfa4..99013efb495 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -333,9 +333,19 @@ impl Command {
             let mut set = MaybeUninit::<libc::sigset_t>::uninit();
             cvt(sigemptyset(set.as_mut_ptr()))?;
             cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?;
-            let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
-            if ret == libc::SIG_ERR {
-                return Err(io::Error::last_os_error());
+
+            #[cfg(target_os = "android")] // see issue #88585
+            {
+                let mut action: libc::sigaction = mem::zeroed();
+                action.sa_sigaction = libc::SIG_DFL;
+                cvt(libc::sigaction(libc::SIGPIPE, &action, ptr::null_mut()))?;
+            }
+            #[cfg(not(target_os = "android"))]
+            {
+                let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
+                if ret == libc::SIG_ERR {
+                    return Err(io::Error::last_os_error());
+                }
             }
         }
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
index 9b3c32a9397..041232e8690 100644
--- a/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.full.stderr
@@ -10,9 +10,10 @@ error: overly complex generic constant
   --> $DIR/array-size-in-generic-struct-param.rs:19:15
    |
 LL |     arr: [u8; CFG.arr_size],
-   |               ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |               ^^^^^^^^^^^^ field access is not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
index 95dae4ecc04..0dfd804be41 100644
--- a/src/test/ui/const-generics/generic_const_exprs/closures.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
@@ -4,9 +4,10 @@ error: overly complex generic constant
 LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
    |                                   ^^^^-------^^
    |                                       |
-   |                                       unsupported operation in generic constant, this may be supported in the future
+   |                                       dereferencing is not supported in generic constants
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
index c9f84799522..5ebb4c3999c 100644
--- a/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/let-bindings.stderr
@@ -2,17 +2,19 @@ error: overly complex generic constant
   --> $DIR/let-bindings.rs:6:68
    |
 LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-   |                                                                    ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                                                    ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: overly complex generic constant
   --> $DIR/let-bindings.rs:6:35
    |
 LL | fn test<const N: usize>() -> [u8; { let x = N; N + 1 }] where [u8; { let x = N; N + 1 }]: Default {
-   |                                   ^^^^^^^^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                   ^^^^^^^^^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
index 3da91b19a5e..df73acf53de 100644
--- a/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/unused_expr.stderr
@@ -2,25 +2,28 @@ error: overly complex generic constant
   --> $DIR/unused_expr.rs:4:34
    |
 LL | fn add<const N: usize>() -> [u8; { N + 1; 5 }] {
-   |                                  ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                  ^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: overly complex generic constant
   --> $DIR/unused_expr.rs:9:34
    |
 LL | fn div<const N: usize>() -> [u8; { N / 1; 5 }] {
-   |                                  ^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                  ^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: overly complex generic constant
   --> $DIR/unused_expr.rs:16:38
    |
 LL | fn fn_call<const N: usize>() -> [u8; { foo(N); 5 }] {
-   |                                      ^^^^^^^^^^^^^ unsupported operation in generic constant, this may be supported in the future
+   |                                      ^^^^^^^^^^^^^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/const-generics/issues/issue-67375.full.stderr b/src/test/ui/const-generics/issues/issue-67375.full.stderr
index 8c9672fd7fc..0f0e339655b 100644
--- a/src/test/ui/const-generics/issues/issue-67375.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-67375.full.stderr
@@ -4,7 +4,7 @@ error: overly complex generic constant
 LL |     inner: [(); { [|_: &T| {}; 0].len() }],
    |                 ^^---------------------^^
    |                   |
-   |                   unsupported operation in generic constant
+   |                   pointer casts are not allowed in generic constants
    |
    = help: consider moving this anonymous constant into a `const` function
 
diff --git a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
index fe0351a8292..cce85772aa4 100644
--- a/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
+++ b/src/test/ui/const-generics/issues/issue-67945-2.full.stderr
@@ -8,9 +8,10 @@ LL | |         let x: Option<Box<Self>> = None;
 LL | |
 LL | |         0
 LL | |     }],
-   | |_____^ unsupported operation in generic constant, this may be supported in the future
+   | |_____^ blocks are not supported in generic constant
    |
    = help: consider moving this anonymous constant into a `const` function
+   = note: this operation may be supported in the future
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/duplicate_doc_alias.rs b/src/test/ui/duplicate_doc_alias.rs
new file mode 100644
index 00000000000..a564ab64532
--- /dev/null
+++ b/src/test/ui/duplicate_doc_alias.rs
@@ -0,0 +1,9 @@
+#![deny(unused_attributes)]
+
+#[doc(alias = "A")]
+#[doc(alias = "A")] //~ ERROR
+#[doc(alias = "B")]
+#[doc(alias("B"))] //~ ERROR
+pub struct Foo;
+
+fn main() {}
diff --git a/src/test/ui/duplicate_doc_alias.stderr b/src/test/ui/duplicate_doc_alias.stderr
new file mode 100644
index 00000000000..4b2dd1f8eb6
--- /dev/null
+++ b/src/test/ui/duplicate_doc_alias.stderr
@@ -0,0 +1,24 @@
+error: doc alias is duplicated
+  --> $DIR/duplicate_doc_alias.rs:4:7
+   |
+LL | #[doc(alias = "A")]
+   |       ----------- first defined here
+LL | #[doc(alias = "A")]
+   |       ^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/duplicate_doc_alias.rs:1:9
+   |
+LL | #![deny(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: doc alias is duplicated
+  --> $DIR/duplicate_doc_alias.rs:6:13
+   |
+LL | #[doc(alias = "B")]
+   |       ----------- first defined here
+LL | #[doc(alias("B"))]
+   |             ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/mir-dataflow/liveness-enum.rs b/src/test/ui/mir-dataflow/liveness-enum.rs
new file mode 100644
index 00000000000..5eb04ae8c8d
--- /dev/null
+++ b/src/test/ui/mir-dataflow/liveness-enum.rs
@@ -0,0 +1,22 @@
+#![feature(core_intrinsics, rustc_attrs)]
+
+use std::intrinsics::rustc_peek;
+
+#[rustc_mir(rustc_peek_liveness, stop_after_dataflow)]
+fn foo() -> Option<i32> {
+    let mut x = None;
+
+    // `x` is live here since it is used in the next statement...
+    rustc_peek(x);
+
+    dbg!(x);
+
+    // But not here, since it is overwritten below
+    rustc_peek(x); //~ ERROR rustc_peek: bit not set
+
+    x = Some(4);
+
+    x
+}
+
+fn main() {}
diff --git a/src/test/ui/mir-dataflow/liveness-enum.stderr b/src/test/ui/mir-dataflow/liveness-enum.stderr
new file mode 100644
index 00000000000..483944d731a
--- /dev/null
+++ b/src/test/ui/mir-dataflow/liveness-enum.stderr
@@ -0,0 +1,10 @@
+error: rustc_peek: bit not set
+  --> $DIR/liveness-enum.rs:15:5
+   |
+LL |     rustc_peek(x);
+   |     ^^^^^^^^^^^^^
+
+error: stop_after_dataflow ended compilation
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr
index 285876aadb2..d6fd4baeb5e 100644
--- a/src/test/ui/proc-macro/generate-mod.stderr
+++ b/src/test/ui/proc-macro/generate-mod.stderr
@@ -82,3 +82,75 @@ LL |     #[derive(generate_mod::CheckDerive)]
 error: aborting due to 4 previous errors; 4 warnings emitted
 
 For more information about this error, try `rustc --explain E0412`.
+Future incompatibility report: Future breakage diagnostic:
+warning: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:16:10
+   |
+LL | #[derive(generate_mod::CheckDerive)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = note: `#[warn(proc_macro_derive_resolution_fallback)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: cannot find type `OuterDerive` in this scope
+  --> $DIR/generate-mod.rs:16:10
+   |
+LL | #[derive(generate_mod::CheckDerive)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:23:14
+   |
+LL |     #[derive(generate_mod::CheckDerive)]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: cannot find type `OuterDerive` in this scope
+  --> $DIR/generate-mod.rs:23:14
+   |
+LL |     #[derive(generate_mod::CheckDerive)]
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: cannot find type `FromOutside` in this scope
+  --> $DIR/generate-mod.rs:30:10
+   |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+note: the lint level is defined here
+  --> $DIR/generate-mod.rs:30:10
+   |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+Future breakage diagnostic:
+warning: cannot find type `OuterDeriveLint` in this scope
+  --> $DIR/generate-mod.rs:30:10
+   |
+LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+   = note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
+
diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.fixed b/src/test/ui/suggestions/ignore-nested-field-binding.fixed
new file mode 100644
index 00000000000..1dc44838e8b
--- /dev/null
+++ b/src/test/ui/suggestions/ignore-nested-field-binding.fixed
@@ -0,0 +1,20 @@
+// Regression test for #88403, where prefixing with an underscore was
+// erroneously suggested for a nested shorthand struct field binding.
+
+// run-rustfix
+#![allow(unused)]
+#![forbid(unused_variables)]
+
+struct Inner { i: i32 }
+struct Outer { o: Inner }
+
+fn foo(Outer { o: Inner { i: _ } }: Outer) {}
+//~^ ERROR: unused variable: `i`
+//~| HELP: try ignoring the field
+
+fn main() {
+    let s = Outer { o: Inner { i: 42 } };
+    let Outer { o: Inner { i: _ } } = s;
+    //~^ ERROR: unused variable: `i`
+    //~| HELP: try ignoring the field
+}
diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.rs b/src/test/ui/suggestions/ignore-nested-field-binding.rs
new file mode 100644
index 00000000000..6dc0263ec9f
--- /dev/null
+++ b/src/test/ui/suggestions/ignore-nested-field-binding.rs
@@ -0,0 +1,20 @@
+// Regression test for #88403, where prefixing with an underscore was
+// erroneously suggested for a nested shorthand struct field binding.
+
+// run-rustfix
+#![allow(unused)]
+#![forbid(unused_variables)]
+
+struct Inner { i: i32 }
+struct Outer { o: Inner }
+
+fn foo(Outer { o: Inner { i } }: Outer) {}
+//~^ ERROR: unused variable: `i`
+//~| HELP: try ignoring the field
+
+fn main() {
+    let s = Outer { o: Inner { i: 42 } };
+    let Outer { o: Inner { i } } = s;
+    //~^ ERROR: unused variable: `i`
+    //~| HELP: try ignoring the field
+}
diff --git a/src/test/ui/suggestions/ignore-nested-field-binding.stderr b/src/test/ui/suggestions/ignore-nested-field-binding.stderr
new file mode 100644
index 00000000000..b2936a22a22
--- /dev/null
+++ b/src/test/ui/suggestions/ignore-nested-field-binding.stderr
@@ -0,0 +1,20 @@
+error: unused variable: `i`
+  --> $DIR/ignore-nested-field-binding.rs:11:27
+   |
+LL | fn foo(Outer { o: Inner { i } }: Outer) {}
+   |                           ^ help: try ignoring the field: `i: _`
+   |
+note: the lint level is defined here
+  --> $DIR/ignore-nested-field-binding.rs:6:11
+   |
+LL | #![forbid(unused_variables)]
+   |           ^^^^^^^^^^^^^^^^
+
+error: unused variable: `i`
+  --> $DIR/ignore-nested-field-binding.rs:17:28
+   |
+LL |     let Outer { o: Inner { i } } = s;
+   |                            ^ help: try ignoring the field: `i: _`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/typeck/issue-88609.rs b/src/test/ui/typeck/issue-88609.rs
new file mode 100644
index 00000000000..dc459c885fa
--- /dev/null
+++ b/src/test/ui/typeck/issue-88609.rs
@@ -0,0 +1,19 @@
+// Regression test for #88609:
+// The return type for `main` is not normalized while checking if it implements
+// the trait `std::process::Termination`.
+
+// build-pass
+
+trait Same {
+    type Output;
+}
+
+impl<T> Same for T {
+    type Output = T;
+}
+
+type Unit = <() as Same>::Output;
+
+fn main() -> Result<Unit, std::io::Error> {
+    unimplemented!()
+}