about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-05-04 05:41:56 +0000
committerbors <bors@rust-lang.org>2024-05-04 05:41:56 +0000
commit9fa862ff29ccfea885f8b1f33f4a507d456ae551 (patch)
treed246825b99aa5bb2930d8f1986a175b9988f1c03 /compiler
parent2c4bf249bd47f232de3c1e78ffe69b40c29bfcca (diff)
parenta55d30f53ce88d744e38a4ad8f2c063a5b4b38d8 (diff)
Auto merge of #124694 - compiler-errors:rollup-pfou5uu, r=compiler-errors
Rollup of 8 pull requests

Successful merges:

 - #124418 (Use a proof tree visitor to refine the `Obligation` for error reporting in new solver)
 - #124480 (Change `SIGPIPE` ui from `#[unix_sigpipe = "..."]` to `-Zon-broken-pipe=...`)
 - #124648 (Trim crate graph)
 - #124656 (release notes 1.78: add link to interior-mut breaking change)
 - #124658 (Migrate `run-make/doctests-keep-binaries` to new rmake.rs format)
 - #124678 (Stabilize `split_at_checked`)
 - #124681 (zkvm: fix run_tests)
 - #124687 (Make `Bounds.clauses` private)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc/src/main.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs4
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml3
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs6
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs2
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml1
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs3
-rw-r--r--compiler/rustc_interface/src/passes.rs6
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_interface/src/util.rs10
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs2
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs1
-rw-r--r--compiler/rustc_passes/messages.ftl3
-rw-r--r--compiler/rustc_passes/src/check_attr.rs1
-rw-r--r--compiler/rustc_passes/src/entry.rs43
-rw-r--r--compiler/rustc_passes/src/errors.rs7
-rw-r--r--compiler/rustc_privacy/Cargo.toml1
-rw-r--r--compiler/rustc_query_system/Cargo.toml1
-rw-r--r--compiler/rustc_session/src/config.rs5
-rw-r--r--compiler/rustc_session/src/config/sigpipe.rs2
-rw-r--r--compiler/rustc_session/src/options.rs16
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/solve/assembly/mod.rs15
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs156
-rw-r--r--compiler/rustc_trait_selection/src/solve/inspect/analyse.rs53
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals.rs5
32 files changed, 257 insertions, 121 deletions
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index 434b978ae31..7ba58406ef1 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -1,5 +1,3 @@
-#![feature(unix_sigpipe)]
-
 // A note about jemalloc: rustc uses jemalloc when built for CI and
 // distribution. The obvious way to do this is with the `#[global_allocator]`
 // mechanism. However, for complicated reasons (see
@@ -34,7 +32,6 @@
 // https://github.com/rust-lang/rust/commit/b90cfc887c31c3e7a9e6d462e2464db1fe506175#diff-43914724af6e464c1da2171e4a9b6c7e607d5bc1203fa95c0ab85be4122605ef
 // for an example of how to do so.
 
-#[unix_sigpipe = "sig_dfl"]
 fn main() {
     // See the comment at the top of this file for an explanation of this.
     #[cfg(feature = "jemalloc-sys")]
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 2c717661a1c..2450ac8f4b3 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -307,7 +307,7 @@ fn make_format_args(
         return ExpandResult::Ready(Err(guar));
     }
 
-    let to_span = |inner_span: rustc_parse_format::InnerSpan| {
+    let to_span = |inner_span: parse::InnerSpan| {
         is_source_literal.then(|| {
             fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end })
         })
@@ -577,7 +577,7 @@ fn make_format_args(
 fn invalid_placeholder_type_error(
     ecx: &ExtCtxt<'_>,
     ty: &str,
-    ty_span: Option<rustc_parse_format::InnerSpan>,
+    ty_span: Option<parse::InnerSpan>,
     fmt_span: Span,
 ) {
     let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end)));
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index a8bba3afb7e..cb37644d570 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -42,9 +42,8 @@ rustc_privacy = { path = "../rustc_privacy" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_resolve = { path = "../rustc_resolve" }
 rustc_session = { path = "../rustc_session" }
-rustc_smir ={ path = "../rustc_smir" }
+rustc_smir = { path = "../rustc_smir" }
 rustc_span = { path = "../rustc_span" }
-rustc_symbol_mangling = { path = "../rustc_symbol_mangling" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index b3a1e29f8e2..4696917554f 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -13,7 +13,7 @@ use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
 use rustc_span::Span;
 use rustc_target::abi::TargetDataLayoutErrors;
 use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
-use rustc_type_ir as type_ir;
+use rustc_type_ir::{ClosureKind, FloatTy};
 use std::backtrace::Backtrace;
 use std::borrow::Cow;
 use std::fmt;
@@ -196,7 +196,7 @@ impl IntoDiagArg for ast::token::TokenKind {
     }
 }
 
-impl IntoDiagArg for type_ir::FloatTy {
+impl IntoDiagArg for FloatTy {
     fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Borrowed(self.name_str()))
     }
@@ -252,7 +252,7 @@ impl IntoDiagArg for Level {
     }
 }
 
-impl IntoDiagArg for type_ir::ClosureKind {
+impl IntoDiagArg for ClosureKind {
     fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(self.as_str().into())
     }
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 9d3aac66c41..9c33cc8ed0b 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -396,10 +396,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
 
     // Entry point:
-    gated!(
-        unix_sigpipe, Normal, template!(NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing,
-        EncodeCrossCrate::Yes, experimental!(unix_sigpipe)
-    ),
     ungated!(start, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
     ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),
     ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index e7d7a9f380b..fe50499db76 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -619,8 +619,6 @@ declare_features! (
     /// Allows creation of instances of a struct by moving fields that have
     /// not changed from prior instances of the same struct (RFC #2528)
     (unstable, type_changing_struct_update, "1.58.0", Some(86555)),
-    /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
-    (unstable, unix_sigpipe, "1.65.0", Some(97889)),
     /// Allows unnamed fields of struct and union type
     (incomplete, unnamed_fields, "1.74.0", Some(49804)),
     /// Allows unsized fn parameters.
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index aafb5c1c0b4..5562b81871f 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -23,7 +23,7 @@ use rustc_span::Span;
 /// include the self type (e.g., `trait_bounds`) but in others we do not
 #[derive(Default, PartialEq, Eq, Clone, Debug)]
 pub struct Bounds<'tcx> {
-    pub clauses: Vec<(ty::Clause<'tcx>, Span)>,
+    clauses: Vec<(ty::Clause<'tcx>, Span)>,
 }
 
 impl<'tcx> Bounds<'tcx> {
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index 9e7f0776b60..73a775690d6 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -12,7 +12,6 @@ rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
-rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 382dba5f95f..8c7ae7f8e98 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -10,7 +10,6 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, Pat, PatKind};
 use rustc_infer::infer;
 use rustc_infer::infer::type_variable::TypeVariableOrigin;
-use rustc_lint as lint;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
@@ -684,7 +683,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             {
                 // `mut x` resets the binding mode in edition <= 2021.
                 self.tcx.emit_node_span_lint(
-                    lint::builtin::DEREFERENCING_MUT_BINDING,
+                    rustc_lint::builtin::DEREFERENCING_MUT_BINDING,
                     pat.hir_id,
                     pat.span,
                     errors::DereferencingMutBinding { span: pat.span },
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index b593c41a8ea..76d5d7a3ac2 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -4,7 +4,6 @@ use crate::proc_macro_decls;
 use crate::util;
 
 use rustc_ast::{self as ast, visit};
-use rustc_borrowck as mir_borrowck;
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::parallel;
 use rustc_data_structures::steal::Steal;
@@ -20,7 +19,6 @@ use rustc_middle::arena::Arena;
 use rustc_middle::dep_graph::DepGraph;
 use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
 use rustc_middle::util::Providers;
-use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
 use rustc_passes::{abi_test, hir_stats, layout_test};
 use rustc_resolve::Resolver;
@@ -616,8 +614,8 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
     proc_macro_decls::provide(providers);
     rustc_const_eval::provide(providers);
     rustc_middle::hir::provide(providers);
-    mir_borrowck::provide(providers);
-    mir_build::provide(providers);
+    rustc_borrowck::provide(providers);
+    rustc_mir_build::provide(providers);
     rustc_mir_transform::provide(providers);
     rustc_monomorphize::provide(providers);
     rustc_privacy::provide(providers);
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index db150cc1f87..36f9dda7250 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -20,7 +20,7 @@ use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
 use rustc_span::symbol::sym;
 use rustc_span::{FileName, SourceFileHashAlgorithm};
 use rustc_target::spec::{
-    CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi,
+    CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi,
 };
 use rustc_target::spec::{RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TlsModel};
 use std::collections::{BTreeMap, BTreeSet};
@@ -809,6 +809,7 @@ fn test_unstable_options_tracking_hash() {
     tracked!(no_profiler_runtime, true);
     tracked!(no_trait_vptr, true);
     tracked!(no_unique_section_names, true);
+    tracked!(on_broken_pipe, OnBrokenPipe::Kill);
     tracked!(oom, OomStrategy::Panic);
     tracked!(osx_rpath_install_name, true);
     tracked!(packed_bundled_libs, true);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 02dcfe9c8df..ce4d3825015 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -7,18 +7,16 @@ use rustc_data_structures::sync;
 use rustc_metadata::{load_symbol_from_dylib, DylibError};
 use rustc_middle::ty::CurrentGcx;
 use rustc_parse::validate_attr;
-use rustc_session as session;
-use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes};
+use rustc_session::config::{host_triple, Cfg, OutFileName, OutputFilenames, OutputTypes};
 use rustc_session::filesearch::sysroot_candidates;
 use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer};
-use rustc_session::{filesearch, Session};
+use rustc_session::output::{categorize_crate_type, CRATE_TYPES};
+use rustc_session::{filesearch, EarlyDiagCtxt, Session};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMapInputs;
 use rustc_span::symbol::sym;
 use rustc_target::spec::Target;
-use session::output::{categorize_crate_type, CRATE_TYPES};
-use session::EarlyDiagCtxt;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::path::{Path, PathBuf};
 use std::sync::atomic::{AtomicBool, Ordering};
@@ -286,7 +284,7 @@ fn get_codegen_sysroot(
         "cannot load the default codegen backend twice"
     );
 
-    let target = session::config::host_triple();
+    let target = host_triple();
     let sysroot_candidates = sysroot_candidates();
 
     let sysroot = iter::once(sysroot)
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 4c34bf88c7f..3ad6b68d129 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -273,6 +273,8 @@ pub enum GoalSource {
     /// they are from an impl where-clause. This is necessary due to
     /// backwards compatability, cc trait-system-refactor-initiatitive#70.
     ImplWhereBound,
+    /// Instantiating a higher-ranked goal and re-proving it.
+    InstantiateHigherRanked,
 }
 
 /// Possible ways the given goal can be proven.
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 2d73be387fd..11aa0e10931 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -127,6 +127,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
                         let source = match source {
                             GoalSource::Misc => "misc",
                             GoalSource::ImplWhereBound => "impl where-bound",
+                            GoalSource::InstantiateHigherRanked => "higher-ranked goal",
                         };
                         writeln!(this.f, "ADDED GOAL ({source}): {goal:?}")?
                     }
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index a545c170297..8878310d6e9 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -695,9 +695,6 @@ passes_transparent_incompatible =
 passes_undefined_naked_function_abi =
     Rust ABI is unsupported in naked functions
 
-passes_unix_sigpipe_values =
-    valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
-
 passes_unknown_external_lang_item =
     unknown external lang item: `{$lang_item}`
 
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index c403e9196fa..e60aa27dba2 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -2523,7 +2523,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
         sym::automatically_derived,
         sym::start,
         sym::rustc_main,
-        sym::unix_sigpipe,
         sym::derive,
         sym::test,
         sym::test_case,
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 438c583db49..d52092f2aa9 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -12,8 +12,7 @@ use rustc_span::symbol::sym;
 use rustc_span::{Span, Symbol};
 
 use crate::errors::{
-    AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain,
-    MultipleStartFunctions, NoMainErr, UnixSigpipeValues,
+    AttrOnlyInFunctions, ExternMain, MultipleRustcMain, MultipleStartFunctions, NoMainErr,
 };
 
 struct EntryContext<'tcx> {
@@ -67,11 +66,7 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
         ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
     );
     match entry_point_type {
-        EntryPointType::None => {
-            if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
-                ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
-            }
-        }
+        EntryPointType::None => (),
         _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
             for attr in [sym::start, sym::rustc_main] {
                 if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
@@ -81,9 +76,6 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
         }
         EntryPointType::MainNamed => (),
         EntryPointType::OtherMain => {
-            if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
-                ctxt.tcx.dcx().emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe });
-            }
             ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
         }
         EntryPointType::RustcMainAttr => {
@@ -98,9 +90,6 @@ fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
             }
         }
         EntryPointType::Start => {
-            if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
-                ctxt.tcx.dcx().emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
-            }
             if ctxt.start_fn.is_none() {
                 ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
             } else {
@@ -120,7 +109,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
         Some((def_id.to_def_id(), EntryFnType::Start))
     } else if let Some((local_def_id, _)) = visitor.attr_main_fn {
         let def_id = local_def_id.to_def_id();
-        Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }))
+        Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }))
     } else {
         if let Some(main_def) = tcx.resolutions(()).main_def
             && let Some(def_id) = main_def.opt_fn_def_id()
@@ -133,31 +122,19 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
                 return None;
             }
 
-            return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx, def_id) }));
+            return Some((def_id, EntryFnType::Main { sigpipe: sigpipe(tcx) }));
         }
         no_main_err(tcx, visitor);
         None
     }
 }
 
-fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
-    if let Some(attr) = tcx.get_attr(def_id, sym::unix_sigpipe) {
-        match (attr.value_str(), attr.meta_item_list()) {
-            (Some(sym::inherit), None) => sigpipe::INHERIT,
-            (Some(sym::sig_ign), None) => sigpipe::SIG_IGN,
-            (Some(sym::sig_dfl), None) => sigpipe::SIG_DFL,
-            (Some(_), None) => {
-                tcx.dcx().emit_err(UnixSigpipeValues { span: attr.span });
-                sigpipe::DEFAULT
-            }
-            _ => {
-                // Keep going so that `fn emit_malformed_attribute()` can print
-                // an excellent error message
-                sigpipe::DEFAULT
-            }
-        }
-    } else {
-        sigpipe::DEFAULT
+fn sigpipe(tcx: TyCtxt<'_>) -> u8 {
+    match tcx.sess.opts.unstable_opts.on_broken_pipe {
+        rustc_target::spec::OnBrokenPipe::Default => sigpipe::DEFAULT,
+        rustc_target::spec::OnBrokenPipe::Kill => sigpipe::SIG_DFL,
+        rustc_target::spec::OnBrokenPipe::Error => sigpipe::SIG_IGN,
+        rustc_target::spec::OnBrokenPipe::Inherit => sigpipe::INHERIT,
     }
 }
 
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 03a607348e8..743faf54560 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1259,13 +1259,6 @@ pub struct ExternMain {
     pub span: Span,
 }
 
-#[derive(Diagnostic)]
-#[diag(passes_unix_sigpipe_values)]
-pub struct UnixSigpipeValues {
-    #[primary_span]
-    pub span: Span,
-}
-
 pub struct NoMainErr {
     pub sp: Span,
     pub crate_name: Symbol,
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index e7a32771f35..f998e0ff154 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -11,7 +11,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
-rustc_hir_analysis = { path = "../rustc_hir_analysis" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 6ea87a4a633..4d845ab0d07 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -19,7 +19,6 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
-rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index ad66e5e1c2b..f2bdabbf394 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -2909,7 +2909,9 @@ pub(crate) mod dep_tracking {
     use rustc_feature::UnstableFeatures;
     use rustc_span::edition::Edition;
     use rustc_span::RealFileName;
-    use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel, WasmCAbi};
+    use rustc_target::spec::{
+        CodeModel, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel, WasmCAbi,
+    };
     use rustc_target::spec::{
         RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
     };
@@ -2973,6 +2975,7 @@ pub(crate) mod dep_tracking {
         InstrumentXRay,
         CrateType,
         MergeFunctions,
+        OnBrokenPipe,
         PanicStrategy,
         RelroLevel,
         OptLevel,
diff --git a/compiler/rustc_session/src/config/sigpipe.rs b/compiler/rustc_session/src/config/sigpipe.rs
index 1fadc75cfd0..1830ee03485 100644
--- a/compiler/rustc_session/src/config/sigpipe.rs
+++ b/compiler/rustc_session/src/config/sigpipe.rs
@@ -1,6 +1,6 @@
 //! NOTE: Keep these constants in sync with `library/std/src/sys/pal/unix/mod.rs`!
 
-/// The default value if `#[unix_sigpipe]` is not specified. This resolves
+/// The default value if `-Zon-broken-pipe=...` is not specified. This resolves
 /// to `SIG_IGN` in `library/std/src/sys/pal/unix/mod.rs`.
 ///
 /// Note that `SIG_IGN` has been the Rust default since 2014. See
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 7355e5b6953..65660286dd7 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -12,7 +12,7 @@ use rustc_span::edition::Edition;
 use rustc_span::RealFileName;
 use rustc_span::SourceFileHashAlgorithm;
 use rustc_target::spec::{
-    CodeModel, LinkerFlavorCli, MergeFunctions, PanicStrategy, SanitizerSet, WasmCAbi,
+    CodeModel, LinkerFlavorCli, MergeFunctions, OnBrokenPipe, PanicStrategy, SanitizerSet, WasmCAbi,
 };
 use rustc_target::spec::{
     RelocModel, RelroLevel, SplitDebuginfo, StackProtector, TargetTriple, TlsModel,
@@ -378,6 +378,7 @@ mod desc {
     pub const parse_time_passes_format: &str = "`text` (default) or `json`";
     pub const parse_passes: &str = "a space-separated list of passes, or `all`";
     pub const parse_panic_strategy: &str = "either `unwind` or `abort`";
+    pub const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
     pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_oom_strategy: &str = "either `panic` or `abort`";
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
@@ -708,6 +709,17 @@ mod parse {
         true
     }
 
+    pub(crate) fn parse_on_broken_pipe(slot: &mut OnBrokenPipe, v: Option<&str>) -> bool {
+        match v {
+            // OnBrokenPipe::Default can't be explicitly specified
+            Some("kill") => *slot = OnBrokenPipe::Kill,
+            Some("error") => *slot = OnBrokenPipe::Error,
+            Some("inherit") => *slot = OnBrokenPipe::Inherit,
+            _ => return false,
+        }
+        true
+    }
+
     pub(crate) fn parse_oom_strategy(slot: &mut OomStrategy, v: Option<&str>) -> bool {
         match v {
             Some("panic") => *slot = OomStrategy::Panic,
@@ -1833,6 +1845,8 @@ options! {
         "do not use unique names for text and data sections when -Z function-sections is used"),
     normalize_docs: bool = (false, parse_bool, [TRACKED],
         "normalize associated items in rustdoc when generating documentation"),
+    on_broken_pipe: OnBrokenPipe = (OnBrokenPipe::Default, parse_on_broken_pipe, [TRACKED],
+        "behavior of std::io::ErrorKind::BrokenPipe (SIGPIPE)"),
     oom: OomStrategy = (OomStrategy::Abort, parse_oom_strategy, [TRACKED],
         "panic strategy for out-of-memory handling"),
     osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7fe94c2e82b..9c556f1152a 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1936,7 +1936,6 @@ symbols! {
         unit,
         universal_impl_trait,
         unix,
-        unix_sigpipe,
         unlikely,
         unmarked_api,
         unnamed_fields,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index bd347c1b4b3..cbb248a0fc2 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -778,6 +778,14 @@ pub enum PanicStrategy {
     Abort,
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Hash, Encodable, Decodable, HashStable_Generic)]
+pub enum OnBrokenPipe {
+    Default,
+    Kill,
+    Error,
+    Inherit,
+}
+
 impl PanicStrategy {
     pub fn desc(&self) -> &str {
         match *self {
diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
index 280975f63bd..f2ca42a0be9 100644
--- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs
@@ -58,15 +58,15 @@ pub(super) trait GoalKind<'tcx>:
     /// goal by equating it with the assumption.
     fn probe_and_consider_implied_clause(
         ecx: &mut EvalCtxt<'_, 'tcx>,
-        source: CandidateSource,
+        parent_source: CandidateSource,
         goal: Goal<'tcx, Self>,
         assumption: ty::Clause<'tcx>,
-        requirements: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
+        requirements: impl IntoIterator<Item = (GoalSource, Goal<'tcx, ty::Predicate<'tcx>>)>,
     ) -> Result<Candidate<'tcx>, NoSolution> {
-        Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| {
-            // FIXME(-Znext-solver=coinductive): check whether this should be
-            // `GoalSource::ImplWhereBound` for any caller.
-            ecx.add_goals(GoalSource::Misc, requirements);
+        Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| {
+            for (nested_source, goal) in requirements {
+                ecx.add_goal(nested_source, goal);
+            }
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
     }
@@ -85,9 +85,8 @@ pub(super) trait GoalKind<'tcx>:
             let ty::Dynamic(bounds, _, _) = *goal.predicate.self_ty().kind() else {
                 bug!("expected object type in `probe_and_consider_object_bound_candidate`");
             };
-            // FIXME(-Znext-solver=coinductive): Should this be `GoalSource::ImplWhereBound`?
             ecx.add_goals(
-                GoalSource::Misc,
+                GoalSource::ImplWhereBound,
                 structural_traits::predicates_for_object_candidate(
                     ecx,
                     goal.param_env,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 6722abd709c..d6bf2b596ef 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -90,6 +90,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         &mut self,
         certainty: Certainty,
     ) -> QueryResult<'tcx> {
+        self.inspect.make_canonical_response(certainty);
+
         let goals_certainty = self.try_evaluate_added_goals()?;
         assert_eq!(
             self.tainted,
@@ -98,8 +100,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
             previous call to `try_evaluate_added_goals!`"
         );
 
-        self.inspect.make_canonical_response(certainty);
-
         // When normalizing, we've replaced the expected term with an unconstrained
         // inference variable. This means that we dropped information which could
         // have been important. We handle this by instead returning the nested goals
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 1710746ae50..bae1c6b6011 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -454,7 +454,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         } else {
             self.infcx.enter_forall(kind, |kind| {
                 let goal = goal.with(self.tcx(), ty::Binder::dummy(kind));
-                self.add_goal(GoalSource::Misc, goal);
+                self.add_goal(GoalSource::InstantiateHigherRanked, goal);
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             })
         }
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 3fa409eefff..796222129f1 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -1,15 +1,19 @@
 use std::mem;
+use std::ops::ControlFlow;
 
 use rustc_infer::infer::InferCtxt;
-use rustc_infer::traits::solve::MaybeCause;
+use rustc_infer::traits::query::NoSolution;
+use rustc_infer::traits::solve::inspect::ProbeKind;
+use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
 use rustc_infer::traits::{
-    query::NoSolution, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
-    PredicateObligation, SelectionError, TraitEngine,
+    self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
+    ObligationCause, PredicateObligation, SelectionError, TraitEngine,
 };
-use rustc_middle::ty;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
+use rustc_middle::ty::{self, TyCtxt};
 
 use super::eval_ctxt::GenerateProofTree;
+use super::inspect::{ProofTreeInferCtxtExt, ProofTreeVisitor};
 use super::{Certainty, InferCtxtEvalExt};
 
 /// A trait engine using the new trait solver.
@@ -133,9 +137,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
             .collect();
 
         errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
-            root_obligation: obligation.clone(),
+            obligation: find_best_leaf_obligation(infcx, &obligation),
             code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
-            obligation,
+            root_obligation: obligation,
         }));
 
         errors
@@ -192,8 +196,10 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
 
 fn fulfillment_error_for_no_solution<'tcx>(
     infcx: &InferCtxt<'tcx>,
-    obligation: PredicateObligation<'tcx>,
+    root_obligation: PredicateObligation<'tcx>,
 ) -> FulfillmentError<'tcx> {
+    let obligation = find_best_leaf_obligation(infcx, &root_obligation);
+
     let code = match obligation.predicate.kind().skip_binder() {
         ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => {
             FulfillmentErrorCode::ProjectionError(
@@ -234,7 +240,8 @@ fn fulfillment_error_for_no_solution<'tcx>(
             bug!("unexpected goal: {obligation:?}")
         }
     };
-    FulfillmentError { root_obligation: obligation.clone(), code, obligation }
+
+    FulfillmentError { obligation, code, root_obligation }
 }
 
 fn fulfillment_error_for_stalled<'tcx>(
@@ -258,5 +265,136 @@ fn fulfillment_error_for_stalled<'tcx>(
         }
     });
 
-    FulfillmentError { obligation: obligation.clone(), code, root_obligation: obligation }
+    FulfillmentError {
+        obligation: find_best_leaf_obligation(infcx, &obligation),
+        code,
+        root_obligation: obligation,
+    }
+}
+
+fn find_best_leaf_obligation<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    obligation: &PredicateObligation<'tcx>,
+) -> PredicateObligation<'tcx> {
+    let obligation = infcx.resolve_vars_if_possible(obligation.clone());
+    infcx
+        .visit_proof_tree(
+            obligation.clone().into(),
+            &mut BestObligation { obligation: obligation.clone() },
+        )
+        .break_value()
+        .unwrap_or(obligation)
+}
+
+struct BestObligation<'tcx> {
+    obligation: PredicateObligation<'tcx>,
+}
+
+impl<'tcx> BestObligation<'tcx> {
+    fn with_derived_obligation(
+        &mut self,
+        derived_obligation: PredicateObligation<'tcx>,
+        and_then: impl FnOnce(&mut Self) -> <Self as ProofTreeVisitor<'tcx>>::Result,
+    ) -> <Self as ProofTreeVisitor<'tcx>>::Result {
+        let old_obligation = std::mem::replace(&mut self.obligation, derived_obligation);
+        let res = and_then(self);
+        self.obligation = old_obligation;
+        res
+    }
+}
+
+impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
+    type Result = ControlFlow<PredicateObligation<'tcx>>;
+
+    fn span(&self) -> rustc_span::Span {
+        self.obligation.cause.span
+    }
+
+    fn visit_goal(&mut self, goal: &super::inspect::InspectGoal<'_, 'tcx>) -> Self::Result {
+        // FIXME: Throw out candidates that have no failing WC and >0 failing misc goal.
+        // This most likely means that the goal just didn't unify at all, e.g. a param
+        // candidate with an alias in it.
+        let candidates = goal.candidates();
+
+        let [candidate] = candidates.as_slice() else {
+            return ControlFlow::Break(self.obligation.clone());
+        };
+
+        // FIXME: Could we extract a trait ref from a projection here too?
+        // FIXME: Also, what about considering >1 layer up the stack? May be necessary
+        // for normalizes-to.
+        let Some(parent_trait_pred) = goal.goal().predicate.to_opt_poly_trait_pred() else {
+            return ControlFlow::Break(self.obligation.clone());
+        };
+
+        let tcx = goal.infcx().tcx;
+        let mut impl_where_bound_count = 0;
+        for nested_goal in candidate.instantiate_nested_goals(self.span()) {
+            let obligation;
+            match nested_goal.source() {
+                GoalSource::Misc => {
+                    continue;
+                }
+                GoalSource::ImplWhereBound => {
+                    obligation = Obligation {
+                        cause: derive_cause(
+                            tcx,
+                            candidate.kind(),
+                            self.obligation.cause.clone(),
+                            impl_where_bound_count,
+                            parent_trait_pred,
+                        ),
+                        param_env: nested_goal.goal().param_env,
+                        predicate: nested_goal.goal().predicate,
+                        recursion_depth: self.obligation.recursion_depth + 1,
+                    };
+                    impl_where_bound_count += 1;
+                }
+                GoalSource::InstantiateHigherRanked => {
+                    obligation = self.obligation.clone();
+                }
+            }
+
+            // Skip nested goals that hold.
+            //FIXME: We should change the max allowed certainty based on if we're
+            // visiting an ambiguity or error obligation.
+            if matches!(nested_goal.result(), Ok(Certainty::Yes)) {
+                continue;
+            }
+
+            self.with_derived_obligation(obligation, |this| nested_goal.visit_with(this))?;
+        }
+
+        ControlFlow::Break(self.obligation.clone())
+    }
+}
+
+fn derive_cause<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    candidate_kind: ProbeKind<'tcx>,
+    mut cause: ObligationCause<'tcx>,
+    idx: usize,
+    parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
+) -> ObligationCause<'tcx> {
+    match candidate_kind {
+        ProbeKind::TraitCandidate { source: CandidateSource::Impl(impl_def_id), result: _ } => {
+            if let Some((_, span)) =
+                tcx.predicates_of(impl_def_id).instantiate_identity(tcx).iter().nth(idx)
+            {
+                cause = cause.derived_cause(parent_trait_pred, |derived| {
+                    traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause {
+                        derived,
+                        impl_or_alias_def_id: impl_def_id,
+                        impl_def_predicate_index: Some(idx),
+                        span,
+                    }))
+                })
+            }
+        }
+        ProbeKind::TraitCandidate { source: CandidateSource::BuiltinImpl(..), result: _ } => {
+            cause = cause.derived_cause(parent_trait_pred, traits::BuiltinDerivedObligation);
+        }
+        _ => {}
+    };
+    cause
 }
diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
index 97de25295b8..4f79f1b2aaf 100644
--- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
+++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs
@@ -41,6 +41,7 @@ pub struct InspectGoal<'a, 'tcx> {
     result: Result<Certainty, NoSolution>,
     evaluation_kind: inspect::CanonicalGoalEvaluationKind<'tcx>,
     normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
+    source: GoalSource,
 }
 
 /// The expected term of a `NormalizesTo` goal gets replaced
@@ -90,7 +91,7 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
 pub struct InspectCandidate<'a, 'tcx> {
     goal: &'a InspectGoal<'a, 'tcx>,
     kind: inspect::ProbeKind<'tcx>,
-    nested_goals: Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
+    nested_goals: Vec<(GoalSource, inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>)>,
     final_state: inspect::CanonicalState<'tcx, ()>,
     result: QueryResult<'tcx>,
     shallow_certainty: Certainty,
@@ -125,10 +126,8 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
     /// back their inference constraints. This function modifies
     /// the state of the `infcx`.
     pub fn visit_nested_no_probe<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
-        if self.goal.depth < visitor.config().max_depth {
-            for goal in self.instantiate_nested_goals(visitor.span()) {
-                try_visit!(visitor.visit_goal(&goal));
-            }
+        for goal in self.instantiate_nested_goals(visitor.span()) {
+            try_visit!(goal.visit_with(visitor));
         }
 
         V::Result::output()
@@ -143,13 +142,16 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
         let instantiated_goals: Vec<_> = self
             .nested_goals
             .iter()
-            .map(|goal| {
-                canonical::instantiate_canonical_state(
-                    infcx,
-                    span,
-                    param_env,
-                    &mut orig_values,
-                    *goal,
+            .map(|(source, goal)| {
+                (
+                    *source,
+                    canonical::instantiate_canonical_state(
+                        infcx,
+                        span,
+                        param_env,
+                        &mut orig_values,
+                        *goal,
+                    ),
                 )
             })
             .collect();
@@ -171,7 +173,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
 
         instantiated_goals
             .into_iter()
-            .map(|goal| match goal.predicate.kind().no_bound_vars() {
+            .map(|(source, goal)| match goal.predicate.kind().no_bound_vars() {
                 Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => {
                     let unconstrained_term = match term.unpack() {
                         ty::TermKind::Ty(_) => infcx
@@ -195,6 +197,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                         self.goal.depth + 1,
                         proof_tree.unwrap(),
                         Some(NormalizesToTermHack { term, unconstrained_term }),
+                        source,
                     )
                 }
                 _ => InspectGoal::new(
@@ -202,6 +205,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
                     self.goal.depth + 1,
                     infcx.evaluate_root_goal(goal, GenerateProofTree::Yes).1.unwrap(),
                     None,
+                    source,
                 ),
             })
             .collect()
@@ -227,16 +231,23 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         self.result
     }
 
+    pub fn source(&self) -> GoalSource {
+        self.source
+    }
+
     fn candidates_recur(
         &'a self,
         candidates: &mut Vec<InspectCandidate<'a, 'tcx>>,
-        nested_goals: &mut Vec<inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>>,
+        nested_goals: &mut Vec<(
+            GoalSource,
+            inspect::CanonicalState<'tcx, Goal<'tcx, ty::Predicate<'tcx>>>,
+        )>,
         probe: &inspect::Probe<'tcx>,
     ) {
         let mut shallow_certainty = None;
         for step in &probe.steps {
             match step {
-                &inspect::ProbeStep::AddGoal(_source, goal) => nested_goals.push(goal),
+                &inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)),
                 inspect::ProbeStep::NestedProbe(ref probe) => {
                     // Nested probes have to prove goals added in their parent
                     // but do not leak them, so we truncate the added goals
@@ -319,6 +330,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
         depth: usize,
         root: inspect::GoalEvaluation<'tcx>,
         normalizes_to_term_hack: Option<NormalizesToTermHack<'tcx>>,
+        source: GoalSource,
     ) -> Self {
         let inspect::GoalEvaluation { uncanonicalized_goal, kind, evaluation } = root;
         let inspect::GoalEvaluationKind::Root { orig_values } = kind else { unreachable!() };
@@ -341,8 +353,17 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
             result,
             evaluation_kind: evaluation.kind,
             normalizes_to_term_hack,
+            source,
         }
     }
+
+    pub(crate) fn visit_with<V: ProofTreeVisitor<'tcx>>(&self, visitor: &mut V) -> V::Result {
+        if self.depth < visitor.config().max_depth {
+            try_visit!(visitor.visit_goal(self));
+        }
+
+        V::Result::output()
+    }
 }
 
 /// The public API to interact with proof trees.
@@ -367,6 +388,6 @@ impl<'tcx> InferCtxt<'tcx> {
     ) -> V::Result {
         let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
         let proof_tree = proof_tree.unwrap();
-        visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None))
+        visitor.visit_goal(&InspectGoal::new(self, 0, proof_tree, None, GoalSource::Misc))
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index dab87fffe46..f886c588650 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -389,7 +389,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
             pred,
-            [goal.with(tcx, output_is_sized_pred)],
+            [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))],
         )
     }
 
@@ -473,7 +473,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             pred,
             [goal.with(tcx, output_is_sized_pred)]
                 .into_iter()
-                .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))),
+                .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred)))
+                .map(|goal| (GoalSource::ImplWhereBound, goal)),
         )
     }
 
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
index c8cb14abb55..d2b893d6383 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs
@@ -321,7 +321,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
             goal,
             pred,
-            [goal.with(tcx, output_is_sized_pred)],
+            [(GoalSource::ImplWhereBound, goal.with(tcx, output_is_sized_pred))],
         )
     }
 
@@ -367,7 +367,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
             pred,
             [goal.with(tcx, output_is_sized_pred)]
                 .into_iter()
-                .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred))),
+                .chain(nested_preds.into_iter().map(|pred| goal.with(tcx, pred)))
+                .map(|goal| (GoalSource::ImplWhereBound, goal)),
         )
     }