about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-12-03 00:51:25 +0000
committerbors <bors@rust-lang.org>2024-12-03 00:51:25 +0000
commit41cbe3e4d1ef8de310fbbd77043082960def9446 (patch)
treec44e61acec0543e267febfc795db865490b9d241 /compiler
parent42b4b9c669ba8ddbf4291211711a79d66e933f41 (diff)
parent73f225acf6823ae8487478b3654f1db5236bff83 (diff)
downloadrust-41cbe3e4d1ef8de310fbbd77043082960def9446.tar.gz
rust-41cbe3e4d1ef8de310fbbd77043082960def9446.zip
Auto merge of #133770 - GuillaumeGomez:rollup-l62iyyx, r=GuillaumeGomez
Rollup of 10 pull requests

Successful merges:

 - #131713 (Stabilize `const_maybe_uninit_write`)
 - #133535 (show forbidden_lint_groups in future-compat reports)
 - #133610 (Move `Const::{from_anon_const,try_from_lit}` to hir_ty_lowering)
 - #133701 (Use c"lit" for CStrings without unwrap)
 - #133704 (fix ICE when promoted has layout size overflow)
 - #133705 (add "profiler" and "optimized-compiler-builtins" option coverage for ci-rustc)
 - #133710 (Reducing `target_feature` check-cfg merge conflicts)
 - #133732 (Fix `-Zdump-mir-dataflow`)
 - #133746 (Change `AttrArgs::Eq` to a struct variant)
 - #133763 (Fix `f16::midpoint` const feature gate)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast/src/ast.rs51
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs12
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs7
-rw-r--r--compiler/rustc_ast/src/visit.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs8
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs17
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs11
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0060.md13
-rw-r--r--compiler/rustc_expand/src/expand.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs21
-rw-r--r--compiler/rustc_hir_analysis/src/collect/dump.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs96
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs88
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs26
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs84
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/cursor.rs5
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/results.rs15
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs2
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs2
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs8
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs5
29 files changed, 263 insertions, 248 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 14205f66491..ed2a3a507c8 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1731,12 +1731,12 @@ pub enum AttrArgs {
     /// Delimited arguments: `#[attr()/[]/{}]`.
     Delimited(DelimArgs),
     /// Arguments of a key-value attribute: `#[attr = "value"]`.
-    Eq(
+    Eq {
         /// Span of the `=` token.
-        Span,
-        /// The "value".
-        AttrArgsEq,
-    ),
+        eq_span: Span,
+
+        value: AttrArgsEq,
+    },
 }
 
 // The RHS of an `AttrArgs::Eq` starts out as an expression. Once macro
@@ -1748,15 +1748,39 @@ pub enum AttrArgsEq {
     Hir(MetaItemLit),
 }
 
+impl AttrArgsEq {
+    pub fn span(&self) -> Span {
+        match self {
+            AttrArgsEq::Ast(p) => p.span,
+            AttrArgsEq::Hir(lit) => lit.span,
+        }
+    }
+
+    pub fn unwrap_ast(&self) -> &Expr {
+        match self {
+            AttrArgsEq::Ast(p) => p,
+            AttrArgsEq::Hir(lit) => {
+                unreachable!("in literal form when getting inner tokens: {lit:?}")
+            }
+        }
+    }
+
+    pub fn unwrap_ast_mut(&mut self) -> &mut P<Expr> {
+        match self {
+            AttrArgsEq::Ast(p) => p,
+            AttrArgsEq::Hir(lit) => {
+                unreachable!("in literal form when getting inner tokens: {lit:?}")
+            }
+        }
+    }
+}
+
 impl AttrArgs {
     pub fn span(&self) -> Option<Span> {
         match self {
             AttrArgs::Empty => None,
             AttrArgs::Delimited(args) => Some(args.dspan.entire()),
-            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => Some(eq_span.to(expr.span)),
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
-                unreachable!("in literal form when getting span: {:?}", lit);
-            }
+            AttrArgs::Eq { eq_span, value } => Some(eq_span.to(value.span())),
         }
     }
 
@@ -1766,10 +1790,7 @@ impl AttrArgs {
         match self {
             AttrArgs::Empty => TokenStream::default(),
             AttrArgs::Delimited(args) => args.tokens.clone(),
-            AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => TokenStream::from_ast(expr),
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
-                unreachable!("in literal form when getting inner tokens: {:?}", lit)
-            }
+            AttrArgs::Eq { value, .. } => TokenStream::from_ast(value.unwrap_ast()),
         }
     }
 }
@@ -1783,10 +1804,10 @@ where
         match self {
             AttrArgs::Empty => {}
             AttrArgs::Delimited(args) => args.hash_stable(ctx, hasher),
-            AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => {
+            AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
                 unreachable!("hash_stable {:?}", expr);
             }
-            AttrArgs::Eq(eq_span, AttrArgsEq::Hir(lit)) => {
+            AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) } => {
                 eq_span.hash_stable(ctx, hasher);
                 lit.hash_stable(ctx, hasher);
             }
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 888b13efa31..0d79cadef34 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -250,7 +250,7 @@ impl AttrItem {
             AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
                 MetaItemKind::list_from_tokens(args.tokens.clone())
             }
-            AttrArgs::Delimited(_) | AttrArgs::Eq(..) | AttrArgs::Empty => None,
+            AttrArgs::Delimited(_) | AttrArgs::Eq { .. } | AttrArgs::Empty => None,
         }
     }
 
@@ -268,7 +268,7 @@ impl AttrItem {
     /// ```
     fn value_str(&self) -> Option<Symbol> {
         match &self.args {
-            AttrArgs::Eq(_, args) => args.value_str(),
+            AttrArgs::Eq { value, .. } => value.value_str(),
             AttrArgs::Delimited(_) | AttrArgs::Empty => None,
         }
     }
@@ -492,7 +492,7 @@ impl MetaItemKind {
                 MetaItemKind::list_from_tokens(tokens.clone()).map(MetaItemKind::List)
             }
             AttrArgs::Delimited(..) => None,
-            AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => match expr.kind {
+            AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => match expr.kind {
                 ExprKind::Lit(token_lit) => {
                     // Turn failures to `None`, we'll get parse errors elsewhere.
                     MetaItemLit::from_token_lit(token_lit, expr.span)
@@ -501,7 +501,9 @@ impl MetaItemKind {
                 }
                 _ => None,
             },
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => Some(MetaItemKind::NameValue(lit.clone())),
+            AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
+                Some(MetaItemKind::NameValue(lit.clone()))
+            }
         }
     }
 }
@@ -702,7 +704,7 @@ pub fn mk_attr_name_value_str(
         tokens: None,
     });
     let path = Path::from_ident(Ident::new(name, span));
-    let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
+    let args = AttrArgs::Eq { eq_span: span, value: AttrArgsEq::Ast(expr) };
     mk_attr(g, style, unsafety, path, args, span)
 }
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 0aceed45028..196fcc1af30 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -451,13 +451,10 @@ fn visit_attr_args<T: MutVisitor>(vis: &mut T, args: &mut AttrArgs) {
     match args {
         AttrArgs::Empty => {}
         AttrArgs::Delimited(args) => visit_delim_args(vis, args),
-        AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => {
-            vis.visit_expr(expr);
+        AttrArgs::Eq { eq_span, value } => {
+            vis.visit_expr(value.unwrap_ast_mut());
             vis.visit_span(eq_span);
         }
-        AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => {
-            unreachable!("in literal form when visiting mac args eq: {:?}", lit)
-        }
     }
 }
 
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 718397e8ca0..2f6998783fa 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -1273,10 +1273,7 @@ pub fn walk_attr_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a AttrArgs) -
     match args {
         AttrArgs::Empty => {}
         AttrArgs::Delimited(_args) => {}
-        AttrArgs::Eq(_eq_span, AttrArgsEq::Ast(expr)) => try_visit!(visitor.visit_expr(expr)),
-        AttrArgs::Eq(_eq_span, AttrArgsEq::Hir(lit)) => {
-            unreachable!("in literal form when walking mac args eq: {:?}", lit)
-        }
+        AttrArgs::Eq { value, .. } => try_visit!(visitor.visit_expr(value.unwrap_ast())),
     }
     V::Result::output()
 }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 7ffe4db6e45..8ec1272e360 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -889,7 +889,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // This is an inert key-value attribute - it will never be visible to macros
             // after it gets lowered to HIR. Therefore, we can extract literals to handle
             // nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
-            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => {
+            &AttrArgs::Eq { eq_span, ref value } => {
+                let expr = value.unwrap_ast();
                 // In valid code the value always ends up as a single literal. Otherwise, a dummy
                 // literal suffices because the error is handled elsewhere.
                 let lit = if let ExprKind::Lit(token_lit) = expr.kind
@@ -905,10 +906,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         span: DUMMY_SP,
                     }
                 };
-                AttrArgs::Eq(*eq_span, AttrArgsEq::Hir(lit))
-            }
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
-                unreachable!("in literal form when lowering mac args eq: {:?}", lit)
+                AttrArgs::Eq { eq_span, value: AttrArgsEq::Hir(lit) }
             }
         }
     }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index d7c531f3760..479677b0a5a 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -648,14 +648,14 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
             AttrArgs::Empty => {
                 self.print_path(&item.path, false, 0);
             }
-            AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => {
+            AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
                 self.print_path(&item.path, false, 0);
                 self.space();
                 self.word_space("=");
                 let token_str = self.expr_to_string(expr);
                 self.word(token_str);
             }
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => {
+            AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
                 self.print_path(&item.path, false, 0);
                 self.space();
                 self.word_space("=");
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 48beb9be2b2..f6d2ec24da6 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -148,7 +148,7 @@ fn prepare_lto(
     // __llvm_profile_counter_bias is pulled in at link time by an undefined reference to
     // __llvm_profile_runtime, therefore we won't know until link time if this symbol
     // should have default visibility.
-    symbols_below_threshold.push(CString::new("__llvm_profile_counter_bias").unwrap());
+    symbols_below_threshold.push(c"__llvm_profile_counter_bias".to_owned());
     Ok((symbols_below_threshold, upstream_modules))
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 2744795d998..bde6668929c 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -509,7 +509,7 @@ fn get_pgo_sample_use_path(config: &ModuleConfig) -> Option<CString> {
 }
 
 fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> {
-    config.instrument_coverage.then(|| CString::new("default_%m_%p.profraw").unwrap())
+    config.instrument_coverage.then(|| c"default_%m_%p.profraw".to_owned())
 }
 
 pub(crate) unsafe fn llvm_optimize(
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 1271d9d2d0d..3cb77d1dcb5 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -139,12 +139,14 @@ where
     match error {
         // Don't emit a new diagnostic for these errors, they are already reported elsewhere or
         // should remain silent.
+        err_inval!(AlreadyReported(info)) => ErrorHandled::Reported(info, span),
         err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
             ErrorHandled::TooGeneric(span)
         }
-        err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span),
         err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
-            ErrorHandled::Reported(ReportedErrorInfo::tainted_by_errors(guar), span)
+            // This can occur in infallible promoteds e.g. when a non-existent type or field is
+            // encountered.
+            ErrorHandled::Reported(ReportedErrorInfo::allowed_in_infallible(guar), span)
         }
         // Report remaining errors.
         _ => {
@@ -152,7 +154,12 @@ where
             let span = span.substitute_dummy(our_span);
             let err = mk(span, frames);
             let mut err = tcx.dcx().create_err(err);
-            let can_be_spurious = matches!(error, InterpErrorKind::ResourceExhaustion(_));
+            // We allow invalid programs in infallible promoteds since invalid layouts can occur
+            // anyway (e.g. due to size overflow). And we allow OOM as that can happen any time.
+            let allowed_in_infallible = matches!(
+                error,
+                InterpErrorKind::ResourceExhaustion(_) | InterpErrorKind::InvalidProgram(_)
+            );
 
             let msg = error.diagnostic_message();
             error.add_args(&mut err);
@@ -160,8 +167,8 @@ where
             // Use *our* span to label the interp error
             err.span_label(our_span, msg);
             let g = err.emit();
-            let reported = if can_be_spurious {
-                ReportedErrorInfo::spurious(g)
+            let reported = if allowed_in_infallible {
+                ReportedErrorInfo::allowed_in_infallible(g)
             } else {
                 ReportedErrorInfo::from(g)
             };
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index fe93a48c2f2..241be5e175c 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -268,7 +268,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         };
         // do not continue if typeck errors occurred (can only occur in local crate)
         if let Some(err) = body.tainted_by_errors {
-            throw_inval!(AlreadyReported(ReportedErrorInfo::tainted_by_errors(err)));
+            throw_inval!(AlreadyReported(ReportedErrorInfo::from(err)));
         }
         interp_ok(body)
     }
@@ -585,13 +585,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     match err {
                         ErrorHandled::TooGeneric(..) => {},
                         ErrorHandled::Reported(reported, span) => {
-                            if reported.is_tainted_by_errors() {
-                                // const-eval will return "tainted" errors if e.g. the layout cannot
-                                // be computed as the type references non-existing names.
-                                // See <https://github.com/rust-lang/rust/issues/124348>.
-                            } else if reported.can_be_spurious() {
+                            if reported.is_allowed_in_infallible() {
                                 // These errors can just sometimes happen, even when the expression
-                                // is nominally "infallible", e.g. when running out of memory.
+                                // is nominally "infallible", e.g. when running out of memory
+                                // or when some layout could not be computed.
                             } else {
                                 // Looks like the const is not captured by `required_consts`, that's bad.
                                 span_bug!(span, "interpret const eval failure of {val:?} which is not in required_consts");
diff --git a/compiler/rustc_error_codes/src/error_codes/E0060.md b/compiler/rustc_error_codes/src/error_codes/E0060.md
index 54b10c886cc..a6831c881e3 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0060.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0060.md
@@ -15,7 +15,7 @@ unsafe { printf(); } // error!
 Using this declaration, it must be called with at least one argument, so
 simply calling `printf()` is invalid. But the following uses are allowed:
 
-```
+```rust,edition2021
 # use std::os::raw::{c_char, c_int};
 # #[cfg_attr(all(windows, target_env = "msvc"),
 #            link(name = "legacy_stdio_definitions",
@@ -23,16 +23,11 @@ simply calling `printf()` is invalid. But the following uses are allowed:
 # extern "C" { fn printf(_: *const c_char, ...) -> c_int; }
 # fn main() {
 unsafe {
-    use std::ffi::CString;
-
-    let fmt = CString::new("test\n").unwrap();
-    printf(fmt.as_ptr());
+    printf(c"test\n".as_ptr());
 
-    let fmt = CString::new("number = %d\n").unwrap();
-    printf(fmt.as_ptr(), 3);
+    printf(c"number = %d\n".as_ptr(), 3);
 
-    let fmt = CString::new("%d, %d\n").unwrap();
-    printf(fmt.as_ptr(), 10, 5);
+    printf(c"%d, %d\n".as_ptr(), 10, 5);
 }
 # }
 ```
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 19c2d466f7c..e5500c8bba1 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -732,7 +732,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         _ => item.to_tokens(),
                     };
                     let attr_item = attr.unwrap_normal_item();
-                    if let AttrArgs::Eq(..) = attr_item.args {
+                    if let AttrArgs::Eq { .. } = attr_item.args {
                         self.cx.dcx().emit_err(UnsupportedKeyValue { span });
                     }
                     let inner_tokens = attr_item.args.inner_tokens();
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 8fa797db246..ed3ae1e12b9 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -13,6 +13,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
 use rustc_macros::LintDiagnostic;
+use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
@@ -1170,19 +1171,13 @@ fn check_type_defn<'tcx>(
 
             // Explicit `enum` discriminant values must const-evaluate successfully.
             if let ty::VariantDiscr::Explicit(discr_def_id) = variant.discr {
-                let cause = traits::ObligationCause::new(
-                    tcx.def_span(discr_def_id),
-                    wfcx.body_def_id,
-                    ObligationCauseCode::Misc,
-                );
-                wfcx.register_obligation(Obligation::new(
-                    tcx,
-                    cause,
-                    wfcx.param_env,
-                    ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
-                        ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
-                    ))),
-                ));
+                match tcx.const_eval_poly(discr_def_id) {
+                    Ok(_) => {}
+                    Err(ErrorHandled::Reported(..)) => {}
+                    Err(ErrorHandled::TooGeneric(sp)) => {
+                        span_bug!(sp, "enum variant discr was too generic to eval")
+                    }
+                }
             }
         }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs
index 8648a7d1e32..f1022d95753 100644
--- a/compiler/rustc_hir_analysis/src/collect/dump.rs
+++ b/compiler/rustc_hir_analysis/src/collect/dump.rs
@@ -1,6 +1,6 @@
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
 use rustc_hir::intravisit;
-use rustc_middle::hir::nested_filter::OnlyBodies;
+use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::sym;
 
@@ -42,7 +42,8 @@ pub(crate) fn predicates_and_item_bounds(tcx: TyCtxt<'_>) {
 }
 
 pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
-    for did in tcx.hir().body_owners() {
+    for iid in tcx.hir().items() {
+        let did = iid.owner_id.def_id;
         if tcx.has_attr(did, sym::rustc_dump_def_parents) {
             struct AnonConstFinder<'tcx> {
                 tcx: TyCtxt<'tcx>,
@@ -50,7 +51,7 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
             }
 
             impl<'tcx> intravisit::Visitor<'tcx> for AnonConstFinder<'tcx> {
-                type NestedFilter = OnlyBodies;
+                type NestedFilter = nested_filter::All;
 
                 fn nested_visit_map(&mut self) -> Self::Map {
                     self.tcx.hir()
@@ -62,11 +63,11 @@ pub(crate) fn def_parents(tcx: TyCtxt<'_>) {
                 }
             }
 
-            // Look for any anon consts inside of this body owner as there is no way to apply
+            // Look for any anon consts inside of this item as there is no way to apply
             // the `rustc_dump_def_parents` attribute to the anon const so it would not be possible
             // to see what its def parent is.
             let mut anon_ct_finder = AnonConstFinder { tcx, anon_consts: vec![] };
-            intravisit::walk_expr(&mut anon_ct_finder, tcx.hir().body_owned_by(did).value);
+            intravisit::walk_item(&mut anon_ct_finder, tcx.hir().item(iid));
 
             for did in [did].into_iter().chain(anon_ct_finder.anon_consts) {
                 let span = tcx.def_span(did);
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index bfee5d33598..ca2597e79fd 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1,12 +1,13 @@
 use std::assert_matches::assert_matches;
 
-use hir::{HirId, Node};
+use hir::Node;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast};
+use rustc_middle::ty::{
+    self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
+};
 use rustc_middle::{bug, span_bug};
 use rustc_span::symbol::Ident;
 use rustc_span::{DUMMY_SP, Span};
@@ -305,7 +306,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     }
 
     if tcx.features().generic_const_exprs() {
-        predicates.extend(const_evaluatable_predicates_of(tcx, def_id));
+        predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
     }
 
     let mut predicates: Vec<_> = predicates.into_iter().collect();
@@ -369,32 +370,48 @@ fn compute_bidirectional_outlives_predicates<'tcx>(
     }
 }
 
-fn const_evaluatable_predicates_of(
-    tcx: TyCtxt<'_>,
+#[instrument(level = "debug", skip(tcx, predicates), ret)]
+fn const_evaluatable_predicates_of<'tcx>(
+    tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
-) -> FxIndexSet<(ty::Clause<'_>, Span)> {
+    predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
+) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
     struct ConstCollector<'tcx> {
         tcx: TyCtxt<'tcx>,
         preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
     }
 
-    impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
-        fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
-            let ct = ty::Const::from_anon_const(self.tcx, c.def_id);
-            if let ty::ConstKind::Unevaluated(_) = ct.kind() {
-                let span = self.tcx.def_span(c.def_id);
-                self.preds.insert((ty::ClauseKind::ConstEvaluatable(ct).upcast(self.tcx), span));
-            }
-        }
+    fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
+        let hir_id = tcx.local_def_id_to_hir_id(def);
+        let (_, parent_node) = tcx
+            .hir()
+            .parent_iter(hir_id)
+            .skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
+            .next()
+            .unwrap();
+        matches!(
+            parent_node,
+            Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
+        )
+    }
 
-        fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) {
-            // Do not look into const param defaults,
-            // these get checked when they are actually instantiated.
-            //
-            // We do not want the following to error:
-            //
-            //     struct Foo<const N: usize, const M: usize = { N + 1 }>;
-            //     struct Bar<const N: usize>(Foo<N, 3>);
+    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
+        fn visit_const(&mut self, c: ty::Const<'tcx>) {
+            if let ty::ConstKind::Unevaluated(uv) = c.kind() {
+                if is_const_param_default(self.tcx, uv.def.expect_local()) {
+                    // Do not look into const param defaults,
+                    // these get checked when they are actually instantiated.
+                    //
+                    // We do not want the following to error:
+                    //
+                    //     struct Foo<const N: usize, const M: usize = { N + 1 }>;
+                    //     struct Bar<const N: usize>(Foo<N, 3>);
+                    return;
+                }
+
+                let span = self.tcx.def_span(uv.def);
+                self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
+            }
         }
     }
 
@@ -402,28 +419,31 @@ fn const_evaluatable_predicates_of(
     let node = tcx.hir_node(hir_id);
 
     let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
+
+    for (clause, _sp) in predicates {
+        clause.visit_with(&mut collector);
+    }
+
     if let hir::Node::Item(item) = node
-        && let hir::ItemKind::Impl(impl_) = item.kind
+        && let hir::ItemKind::Impl(_) = item.kind
     {
-        if let Some(of_trait) = &impl_.of_trait {
-            debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
-            collector.visit_trait_ref(of_trait);
+        if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
+            debug!("visit impl trait_ref");
+            of_trait.instantiate_identity().visit_with(&mut collector);
         }
 
-        debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
-        collector.visit_ty(impl_.self_ty);
-    }
-
-    if let Some(generics) = node.generics() {
-        debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id);
-        collector.visit_generics(generics);
+        debug!("visit self_ty");
+        let self_ty = tcx.type_of(def_id);
+        self_ty.instantiate_identity().visit_with(&mut collector);
     }
 
-    if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) {
-        debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id);
-        collector.visit_fn_decl(fn_sig.decl);
+    if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) {
+        debug!("visit fn sig");
+        let fn_sig = tcx.fn_sig(def_id);
+        let fn_sig = fn_sig.instantiate_identity();
+        debug!(?fn_sig);
+        fn_sig.visit_with(&mut collector);
     }
-    debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds);
 
     collector.preds
 }
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index 9d60759ae48..0404e38a293 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -703,7 +703,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
 ///
 /// It might actually be possible that we can already support early-bound generic params
 /// in such types if we just lifted some more checks in other places, too, for example
-/// inside [`ty::Const::from_anon_const`]. However, even if that were the case, we should
+/// inside `HirTyLowerer::lower_anon_const`. However, even if that were the case, we should
 /// probably gate this behind another feature flag.
 ///
 /// [^1]: <https://github.com/rust-lang/project-const-generics/issues/28>.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 7b8e95f3434..cb4209116ac 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2089,7 +2089,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 qpath.span(),
                 format!("Const::lower_const_arg: invalid qpath {qpath:?}"),
             ),
-            hir::ConstArgKind::Anon(anon) => Const::from_anon_const(tcx, anon.def_id),
+            hir::ConstArgKind::Anon(anon) => self.lower_anon_const(anon.def_id),
             hir::ConstArgKind::Infer(span) => self.ct_infer(None, span),
         }
     }
@@ -2177,6 +2177,92 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
     }
 
+    /// Literals and const generic parameters are eagerly converted to a constant, everything else
+    /// becomes `Unevaluated`.
+    #[instrument(skip(self), level = "debug")]
+    fn lower_anon_const(&self, def: LocalDefId) -> Const<'tcx> {
+        let tcx = self.tcx();
+
+        let body_id = match tcx.hir_node_by_def_id(def) {
+            hir::Node::AnonConst(ac) => ac.body,
+            node => span_bug!(
+                tcx.def_span(def.to_def_id()),
+                "from_anon_const can only process anonymous constants, not {node:?}"
+            ),
+        };
+
+        let expr = &tcx.hir().body(body_id).value;
+        debug!(?expr);
+
+        let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
+
+        match self.try_lower_anon_const_lit(ty, expr) {
+            Some(v) => v,
+            None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
+                def: def.to_def_id(),
+                args: ty::GenericArgs::identity_for_item(tcx, def.to_def_id()),
+            }),
+        }
+    }
+
+    #[instrument(skip(self), level = "debug")]
+    fn try_lower_anon_const_lit(
+        &self,
+        ty: Ty<'tcx>,
+        expr: &'tcx hir::Expr<'tcx>,
+    ) -> Option<Const<'tcx>> {
+        let tcx = self.tcx();
+
+        // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
+        // currently have to be wrapped in curly brackets, so it's necessary to special-case.
+        let expr = match &expr.kind {
+            hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
+                block.expr.as_ref().unwrap()
+            }
+            _ => expr,
+        };
+
+        if let hir::ExprKind::Path(hir::QPath::Resolved(
+            _,
+            &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
+        )) = expr.kind
+        {
+            span_bug!(
+                expr.span,
+                "try_lower_anon_const_lit: received const param which shouldn't be possible"
+            );
+        };
+
+        let lit_input = match expr.kind {
+            hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
+            hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
+                hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
+                _ => None,
+            },
+            _ => None,
+        };
+
+        if let Some(lit_input) = lit_input {
+            // If an error occurred, ignore that it's a literal and leave reporting the error up to
+            // mir.
+            match tcx.at(expr.span).lit_to_const(lit_input) {
+                Ok(c) => return Some(c),
+                Err(_) if lit_input.ty.has_aliases() => {
+                    // allow the `ty` to be an alias type, though we cannot handle it here
+                    return None;
+                }
+                Err(e) => {
+                    tcx.dcx().span_delayed_bug(
+                        expr.span,
+                        format!("try_lower_anon_const_lit: couldn't lit_to_const {e:?}"),
+                    );
+                }
+            }
+        }
+
+        None
+    }
+
     fn lower_delegation_ty(&self, idx: hir::InferDelegationKind) -> Ty<'tcx> {
         let delegation_sig = self.tcx().inherit_sig_for_delegation_item(self.item_def_id());
         match idx {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 3b406c7e161..d2b7ae620e2 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -179,7 +179,7 @@ declare_lint! {
     Warn,
     "applying forbid to lint-groups",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
         reference: "issue #81670 <https://github.com/rust-lang/rust/issues/81670>",
     };
 }
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 08afa33c6b4..ad5d678178d 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -46,7 +46,7 @@ impl ErrorHandled {
     pub fn emit_note(&self, tcx: TyCtxt<'_>) {
         match self {
             &ErrorHandled::Reported(err, span) => {
-                if !err.is_tainted_by_errors && !span.is_dummy() {
+                if !err.allowed_in_infallible && !span.is_dummy() {
                     tcx.dcx().emit_note(error::ErroneousConstant { span });
                 }
             }
@@ -58,34 +58,26 @@ impl ErrorHandled {
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
 pub struct ReportedErrorInfo {
     error: ErrorGuaranteed,
-    is_tainted_by_errors: bool,
-    /// Whether this is the kind of error that can sometimes occur, and sometimes not.
-    /// Used for resource exhaustion errors.
-    can_be_spurious: bool,
+    /// Whether this error is allowed to show up even in otherwise "infallible" promoteds.
+    /// This is for things like overflows during size computation or resource exhaustion.
+    allowed_in_infallible: bool,
 }
 
 impl ReportedErrorInfo {
     #[inline]
-    pub fn tainted_by_errors(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { is_tainted_by_errors: true, can_be_spurious: false, error }
-    }
-    #[inline]
-    pub fn spurious(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { can_be_spurious: true, is_tainted_by_errors: false, error }
+    pub fn allowed_in_infallible(error: ErrorGuaranteed) -> ReportedErrorInfo {
+        ReportedErrorInfo { allowed_in_infallible: true, error }
     }
 
-    pub fn is_tainted_by_errors(&self) -> bool {
-        self.is_tainted_by_errors
-    }
-    pub fn can_be_spurious(&self) -> bool {
-        self.can_be_spurious
+    pub fn is_allowed_in_infallible(&self) -> bool {
+        self.allowed_in_infallible
     }
 }
 
 impl From<ErrorGuaranteed> for ReportedErrorInfo {
     #[inline]
     fn from(error: ErrorGuaranteed) -> ReportedErrorInfo {
-        ReportedErrorInfo { is_tainted_by_errors: false, can_be_spurious: false, error }
+        ReportedErrorInfo { allowed_in_infallible: false, error }
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index d27205e26ab..31055276422 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -2,15 +2,11 @@ use std::borrow::Cow;
 
 use rustc_data_structures::intern::Interned;
 use rustc_error_messages::MultiSpan;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::{self as hir};
 use rustc_macros::HashStable;
 use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo};
-use tracing::{debug, instrument};
 
-use crate::mir::interpret::{LitToConstInput, Scalar};
-use crate::ty::{self, GenericArgs, Ty, TyCtxt, TypeVisitableExt};
+use crate::mir::interpret::Scalar;
+use crate::ty::{self, Ty, TyCtxt};
 
 mod int;
 mod kind;
@@ -181,82 +177,6 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
 }
 
 impl<'tcx> Const<'tcx> {
-    // FIXME: move this and try_from_lit to hir_ty_lowering like lower_const_arg/from_const_arg
-    /// Literals and const generic parameters are eagerly converted to a constant, everything else
-    /// becomes `Unevaluated`.
-    #[instrument(skip(tcx), level = "debug")]
-    pub fn from_anon_const(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Self {
-        let body_id = match tcx.hir_node_by_def_id(def) {
-            hir::Node::AnonConst(ac) => ac.body,
-            node => span_bug!(
-                tcx.def_span(def.to_def_id()),
-                "from_anon_const can only process anonymous constants, not {node:?}"
-            ),
-        };
-
-        let expr = &tcx.hir().body(body_id).value;
-        debug!(?expr);
-
-        let ty = tcx.type_of(def).no_bound_vars().expect("const parameter types cannot be generic");
-
-        match Self::try_from_lit(tcx, ty, expr) {
-            Some(v) => v,
-            None => ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst {
-                def: def.to_def_id(),
-                args: GenericArgs::identity_for_item(tcx, def.to_def_id()),
-            }),
-        }
-    }
-
-    #[instrument(skip(tcx), level = "debug")]
-    fn try_from_lit(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, expr: &'tcx hir::Expr<'tcx>) -> Option<Self> {
-        // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments
-        // currently have to be wrapped in curly brackets, so it's necessary to special-case.
-        let expr = match &expr.kind {
-            hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => {
-                block.expr.as_ref().unwrap()
-            }
-            _ => expr,
-        };
-
-        if let hir::ExprKind::Path(hir::QPath::Resolved(
-            _,
-            &hir::Path { res: Res::Def(DefKind::ConstParam, _), .. },
-        )) = expr.kind
-        {
-            span_bug!(expr.span, "try_from_lit: received const param which shouldn't be possible");
-        };
-
-        let lit_input = match expr.kind {
-            hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
-            hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind {
-                hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }),
-                _ => None,
-            },
-            _ => None,
-        };
-
-        if let Some(lit_input) = lit_input {
-            // If an error occurred, ignore that it's a literal and leave reporting the error up to
-            // mir.
-            match tcx.at(expr.span).lit_to_const(lit_input) {
-                Ok(c) => return Some(c),
-                Err(_) if lit_input.ty.has_aliases() => {
-                    // allow the `ty` to be an alias type, though we cannot handle it here
-                    return None;
-                }
-                Err(e) => {
-                    tcx.dcx().span_delayed_bug(
-                        expr.span,
-                        format!("Const::try_from_lit: couldn't lit_to_const {e:?}"),
-                    );
-                }
-            }
-        }
-
-        None
-    }
-
     /// Creates a constant with the given integer value and interns it.
     #[inline]
     pub fn from_bits(
diff --git a/compiler/rustc_mir_dataflow/src/framework/cursor.rs b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
index 11cf8c3e898..4a9bcdaddb3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/cursor.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/cursor.rs
@@ -15,7 +15,6 @@ pub enum ResultsHandle<'a, 'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    Borrowed(&'a Results<'tcx, A>),
     BorrowedMut(&'a mut Results<'tcx, A>),
     Owned(Results<'tcx, A>),
 }
@@ -28,7 +27,6 @@ where
 
     fn deref(&self) -> &Results<'tcx, A> {
         match self {
-            ResultsHandle::Borrowed(borrowed) => borrowed,
             ResultsHandle::BorrowedMut(borrowed) => borrowed,
             ResultsHandle::Owned(owned) => owned,
         }
@@ -41,9 +39,6 @@ where
 {
     fn deref_mut(&mut self) -> &mut Results<'tcx, A> {
         match self {
-            ResultsHandle::Borrowed(_borrowed) => {
-                panic!("tried to deref_mut a `ResultsHandle::Borrowed")
-            }
             ResultsHandle::BorrowedMut(borrowed) => borrowed,
             ResultsHandle::Owned(owned) => owned,
         }
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index 6e4994af8b4..561229cf725 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -47,7 +47,7 @@ where
 {
     pub(crate) fn new(
         body: &'mir Body<'tcx>,
-        results: &'mir Results<'tcx, A>,
+        results: &'mir mut Results<'tcx, A>,
         style: OutputStyle,
     ) -> Self {
         let reachable = mir::traversal::reachable_as_bitset(body);
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index f1ea94e1689..b9407882ec5 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -281,10 +281,10 @@ pub trait Analysis<'tcx> {
             );
         }
 
-        let results = Results { analysis: self, entry_sets };
+        let mut results = Results { analysis: self, entry_sets };
 
         if tcx.sess.opts.unstable_opts.dump_mir_dataflow {
-            let res = write_graphviz_results(tcx, body, &results, pass_name);
+            let res = write_graphviz_results(tcx, body, &mut results, pass_name);
             if let Err(e) = res {
                 error!("Failed to write graphviz dataflow results: {}", e);
             }
diff --git a/compiler/rustc_mir_dataflow/src/framework/results.rs b/compiler/rustc_mir_dataflow/src/framework/results.rs
index 8493a7aa44b..c4321c454e6 100644
--- a/compiler/rustc_mir_dataflow/src/framework/results.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/results.rs
@@ -37,18 +37,9 @@ impl<'tcx, A> Results<'tcx, A>
 where
     A: Analysis<'tcx>,
 {
-    /// Creates a `ResultsCursor` that can inspect these `Results`. Immutably borrows the `Results`,
-    /// which is appropriate when the `Results` is used outside the cursor.
+    /// Creates a `ResultsCursor` that mutably borrows the `Results`, which is appropriate when the
+    /// `Results` is also used outside the cursor.
     pub fn as_results_cursor<'mir>(
-        &'mir self,
-        body: &'mir mir::Body<'tcx>,
-    ) -> ResultsCursor<'mir, 'tcx, A> {
-        ResultsCursor::new(body, ResultsHandle::Borrowed(self))
-    }
-
-    /// Creates a `ResultsCursor` that can mutate these `Results`. Mutably borrows the `Results`,
-    /// which is appropriate when the `Results` is used outside the cursor.
-    pub fn as_results_cursor_mut<'mir>(
         &'mir mut self,
         body: &'mir mir::Body<'tcx>,
     ) -> ResultsCursor<'mir, 'tcx, A> {
@@ -95,7 +86,7 @@ where
 pub(super) fn write_graphviz_results<'tcx, A>(
     tcx: TyCtxt<'tcx>,
     body: &mir::Body<'tcx>,
-    results: &Results<'tcx, A>,
+    results: &mut Results<'tcx, A>,
     pass_name: Option<&'static str>,
 ) -> std::io::Result<()>
 where
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 9b9aeccf890..858752a3f01 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -680,7 +680,7 @@ fn locals_live_across_suspend_points<'tcx>(
     let mut requires_storage_results =
         MaybeRequiresStorage::new(borrowed_locals_results.into_results_cursor(body))
             .iterate_to_fixpoint(tcx, body, None);
-    let mut requires_storage_cursor = requires_storage_results.as_results_cursor_mut(body);
+    let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body);
 
     // Calculate the liveness of MIR locals ignoring borrows.
     let mut liveness =
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 0ed8d152d2d..37556c064d8 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1376,7 +1376,7 @@ impl<'a> Parser<'a> {
             AttrArgs::Delimited(args)
         } else if self.eat(&token::Eq) {
             let eq_span = self.prev_token.span;
-            AttrArgs::Eq(eq_span, AttrArgsEq::Ast(self.parse_expr_force_collect()?))
+            AttrArgs::Eq { eq_span, value: AttrArgsEq::Ast(self.parse_expr_force_collect()?) }
         } else {
             AttrArgs::Empty
         })
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index f3174e7dea2..aab3f10bc66 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -43,7 +43,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
             }
         }
         _ => {
-            if let AttrArgs::Eq(..) = attr_item.args {
+            if let AttrArgs::Eq { .. } = attr_item.args {
                 // All key-value attributes are restricted to meta-item syntax.
                 match parse_meta(psess, attr) {
                     Ok(_) => {}
@@ -70,7 +70,7 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
                     parse_in(psess, tokens.clone(), "meta list", |p| p.parse_meta_seq_top())?;
                 MetaItemKind::List(nmis)
             }
-            AttrArgs::Eq(_, AttrArgsEq::Ast(expr)) => {
+            AttrArgs::Eq { value: AttrArgsEq::Ast(expr), .. } => {
                 if let ast::ExprKind::Lit(token_lit) = expr.kind {
                     let res = ast::MetaItemLit::from_token_lit(token_lit, expr.span);
                     let res = match res {
@@ -116,7 +116,9 @@ pub fn parse_meta<'a>(psess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Met
                     return Err(err);
                 }
             }
-            AttrArgs::Eq(_, AttrArgsEq::Hir(lit)) => MetaItemKind::NameValue(lit.clone()),
+            AttrArgs::Eq { value: AttrArgsEq::Hir(lit), .. } => {
+                MetaItemKind::NameValue(lit.clone())
+            }
         },
     })
 }
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 02e255d7726..65128ceb866 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -220,9 +220,9 @@ pub fn attrs_to_doc_fragments<'a>(
 
 fn span_for_value(attr: &ast::Attribute) -> Span {
     if let ast::AttrKind::Normal(normal) = &attr.kind
-        && let ast::AttrArgs::Eq(_, ast::AttrArgsEq::Hir(meta)) = &normal.item.args
+        && let ast::AttrArgs::Eq { value, .. } = &normal.item.args
     {
-        meta.span.with_ctxt(attr.span.ctxt())
+        value.span().with_ctxt(attr.span.ctxt())
     } else {
         attr.span
     }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
index 7f42c932fcf..f10314c1c9e 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -1,7 +1,7 @@
 use std::iter;
 use std::path::PathBuf;
 
-use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind, Attribute, MetaItemInner};
+use rustc_ast::{AttrArgs, AttrKind, Attribute, MetaItemInner};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::codes::*;
 use rustc_errors::{ErrorGuaranteed, struct_span_code_err};
@@ -639,8 +639,7 @@ impl<'tcx> OnUnimplementedDirective {
                 let report_span = match &item.args {
                     AttrArgs::Empty => item.path.span,
                     AttrArgs::Delimited(args) => args.dspan.entire(),
-                    AttrArgs::Eq(eq_span, AttrArgsEq::Ast(expr)) => eq_span.to(expr.span),
-                    AttrArgs::Eq(span, AttrArgsEq::Hir(expr)) => span.to(expr.span),
+                    AttrArgs::Eq { eq_span, value } => eq_span.to(value.span()),
                 };
 
                 if let Some(item_def_id) = item_def_id.as_local() {