about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock41
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs20
-rw-r--r--compiler/rustc_error_messages/locales/en-US/save_analysis.ftl1
-rw-r--r--compiler/rustc_error_messages/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_save_analysis/Cargo.toml21
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs1465
-rw-r--r--compiler/rustc_save_analysis/src/dumper.rs91
-rw-r--r--compiler/rustc_save_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs1067
-rw-r--r--compiler/rustc_save_analysis/src/sig.rs931
-rw-r--r--compiler/rustc_save_analysis/src/span_utils.rs96
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--src/bootstrap/builder.rs11
-rw-r--r--src/bootstrap/dist.rs11
-rw-r--r--src/bootstrap/install.rs12
-rw-r--r--src/doc/rustc/src/json.md1
-rw-r--r--src/tools/tidy/src/deps.rs2
-rw-r--r--tests/run-make-fulldeps/issues-41478-43796/Makefile8
-rw-r--r--tests/run-make-fulldeps/issues-41478-43796/a.rs9
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/Makefile6
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/SameDir.rs5
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/SameDir3.rs3
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs27
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/foo.rs463
-rw-r--r--tests/run-make-fulldeps/save-analysis-fail/krate2.rs8
-rw-r--r--tests/run-make-fulldeps/save-analysis-rfc2126/Makefile8
-rw-r--r--tests/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs6
-rw-r--r--tests/run-make-fulldeps/save-analysis-rfc2126/krate2.rs5
-rw-r--r--tests/run-make-fulldeps/save-analysis-rfc2126/validate_json.py7
-rw-r--r--tests/run-make-fulldeps/save-analysis/Makefile6
-rw-r--r--tests/run-make-fulldeps/save-analysis/SameDir.rs5
-rw-r--r--tests/run-make-fulldeps/save-analysis/SameDir3.rs3
-rw-r--r--tests/run-make-fulldeps/save-analysis/SubDir/mod.rs27
-rw-r--r--tests/run-make-fulldeps/save-analysis/extra-docs.md1
-rw-r--r--tests/run-make-fulldeps/save-analysis/foo.rs465
-rw-r--r--tests/run-make-fulldeps/save-analysis/krate2.rs8
-rw-r--r--tests/rustdoc-ui/z-help.stdout1
-rw-r--r--tests/ui/asm/issue-72570.rs2
-rw-r--r--tests/ui/asm/issue-72570.stderr2
-rw-r--r--tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr2
-rw-r--r--tests/ui/const-generics/const-argument-non-static-lifetime.rs1
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs3
-rw-r--r--tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr2
-rw-r--r--tests/ui/const-generics/issues/issue-73260.rs1
-rw-r--r--tests/ui/const-generics/issues/issue-73260.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-associated_type_bounds.rs3
-rw-r--r--tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr34
-rw-r--r--tests/ui/impl-trait/bound-normalization-pass.rs2
-rw-r--r--tests/ui/issues/issue-3763.rs3
-rw-r--r--tests/ui/issues/issue-3763.stderr10
-rw-r--r--tests/ui/methods/assign-to-method.rs3
-rw-r--r--tests/ui/methods/assign-to-method.stderr4
-rw-r--r--tests/ui/save-analysis/emit-notifications.polonius.stderr2
-rw-r--r--tests/ui/save-analysis/emit-notifications.rs7
-rw-r--r--tests/ui/save-analysis/emit-notifications.stderr2
-rw-r--r--tests/ui/save-analysis/issue-26459.rs8
-rw-r--r--tests/ui/save-analysis/issue-26459.stderr9
-rw-r--r--tests/ui/save-analysis/issue-37323.rs20
-rw-r--r--tests/ui/save-analysis/issue-59134-0.rs12
-rw-r--r--tests/ui/save-analysis/issue-59134-0.stderr9
-rw-r--r--tests/ui/save-analysis/issue-59134-1.rs12
-rw-r--r--tests/ui/save-analysis/issue-59134-1.stderr9
-rw-r--r--tests/ui/save-analysis/issue-63663.rs28
-rw-r--r--tests/ui/save-analysis/issue-64659.rs10
-rw-r--r--tests/ui/save-analysis/issue-65411.rs15
-rw-r--r--tests/ui/save-analysis/issue-65590.rs21
-rw-r--r--tests/ui/save-analysis/issue-68621.rs17
-rw-r--r--tests/ui/save-analysis/issue-68621.stderr10
-rw-r--r--tests/ui/save-analysis/issue-72267.rs7
-rw-r--r--tests/ui/save-analysis/issue-72267.stderr15
-rw-r--r--tests/ui/save-analysis/issue-73020.rs5
-rw-r--r--tests/ui/save-analysis/issue-73020.stderr9
-rw-r--r--tests/ui/save-analysis/issue-73022.rs13
-rw-r--r--tests/ui/save-analysis/issue-89066.rs28
-rw-r--r--tests/ui/save-analysis/issue-89066.stderr39
-rw-r--r--tests/ui/traits/alias/self-in-generics.rs4
-rw-r--r--tests/ui/traits/alias/self-in-generics.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63279.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63279.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs1
82 files changed, 50 insertions, 5215 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 15f051d0cff..6a1525f7530 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3496,25 +3496,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rls-data"
-version = "0.19.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a58135eb039f3a3279a33779192f0ee78b56f57ae636e25cec83530e41debb99"
-dependencies = [
- "rls-span",
- "serde",
-]
-
-[[package]]
-name = "rls-span"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eea58478fc06e15f71b03236612173a1b81e9770314edecfa664375e3e4c86"
-dependencies = [
- "serde",
-]
-
-[[package]]
 name = "rust-demangler"
 version = "0.0.1"
 dependencies = [
@@ -3965,7 +3946,6 @@ dependencies = [
  "rustc_middle",
  "rustc_parse",
  "rustc_plugin_impl",
- "rustc_save_analysis",
  "rustc_session",
  "rustc_span",
  "rustc_target",
@@ -4626,27 +4606,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_save_analysis"
-version = "0.0.0"
-dependencies = [
- "rls-data",
- "rls-span",
- "rustc_ast",
- "rustc_ast_pretty",
- "rustc_data_structures",
- "rustc_errors",
- "rustc_hir",
- "rustc_hir_pretty",
- "rustc_lexer",
- "rustc_macros",
- "rustc_middle",
- "rustc_session",
- "rustc_span",
- "serde_json",
- "tracing",
-]
-
-[[package]]
 name = "rustc_serialize"
 version = "0.0.0"
 dependencies = [
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index af85b12c52b..cdec4f91277 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -22,7 +22,6 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_metadata = { path = "../rustc_metadata" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_plugin_impl = { path = "../rustc_plugin_impl" }
-rustc_save_analysis = { path = "../rustc_save_analysis" }
 rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
 rustc_session = { path = "../rustc_session" }
 rustc_error_codes = { path = "../rustc_error_codes" }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 1067fcebcf3..1a4fe07b476 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -25,13 +25,10 @@ use rustc_data_structures::sync::SeqCst;
 use rustc_errors::registry::{InvalidErrorCode, Registry};
 use rustc_errors::{ErrorGuaranteed, PResult, TerminalUrl};
 use rustc_feature::find_gated_cfg;
-use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
 use rustc_lint::LintStore;
 use rustc_metadata::locator;
-use rustc_save_analysis as save;
-use rustc_save_analysis::DumpHandler;
 use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
 use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, TrimmedDefPaths};
 use rustc_session::cstore::MetadataLoader;
@@ -343,22 +340,7 @@ fn run_compiler(
                 return early_exit();
             }
 
-            queries.global_ctxt()?.enter(|tcx| {
-                let result = tcx.analysis(());
-                if sess.opts.unstable_opts.save_analysis {
-                    let crate_name = tcx.crate_name(LOCAL_CRATE);
-                    sess.time("save_analysis", || {
-                        save::process_crate(
-                            tcx,
-                            crate_name,
-                            &sess.io.input,
-                            None,
-                            DumpHandler::new(sess.io.output_dir.as_deref(), crate_name),
-                        )
-                    });
-                }
-                result
-            })?;
+            queries.global_ctxt()?.enter(|tcx| tcx.analysis(()))?;
 
             if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
                 return early_exit();
diff --git a/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl b/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl
deleted file mode 100644
index 36c2ff46823..00000000000
--- a/compiler/rustc_error_messages/locales/en-US/save_analysis.ftl
+++ /dev/null
@@ -1 +0,0 @@
-save_analysis_could_not_open = Could not open `{$file_name}`: `{$err}`
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 1882d4b698e..579466ed366 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -67,7 +67,6 @@ fluent_messages! {
     privacy => "../locales/en-US/privacy.ftl",
     query_system => "../locales/en-US/query_system.ftl",
     resolve => "../locales/en-US/resolve.ftl",
-    save_analysis => "../locales/en-US/save_analysis.ftl",
     session => "../locales/en-US/session.ftl",
     symbol_mangling => "../locales/en-US/symbol_mangling.ftl",
     trait_selection => "../locales/en-US/trait_selection.ftl",
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 0d3499ca9a0..ac32988d3ac 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -691,7 +691,6 @@ fn test_unstable_options_tracking_hash() {
     untracked!(proc_macro_execution_strategy, ProcMacroExecutionStrategy::CrossThread);
     untracked!(profile_closures, true);
     untracked!(query_dep_graph, true);
-    untracked!(save_analysis, true);
     untracked!(self_profile, SwitchWithOptPath::Enabled(None));
     untracked!(self_profile_events, Some(vec![String::new()]));
     untracked!(span_debug, true);
diff --git a/compiler/rustc_save_analysis/Cargo.toml b/compiler/rustc_save_analysis/Cargo.toml
deleted file mode 100644
index 181e27f334b..00000000000
--- a/compiler/rustc_save_analysis/Cargo.toml
+++ /dev/null
@@ -1,21 +0,0 @@
-[package]
-name = "rustc_save_analysis"
-version = "0.0.0"
-edition = "2021"
-
-[dependencies]
-tracing = "0.1"
-rustc_middle = { path = "../rustc_middle" }
-rustc_ast = { path = "../rustc_ast" }
-rustc_ast_pretty = { path = "../rustc_ast_pretty" }
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_errors = { path = "../rustc_errors" }
-rustc_hir = { path = "../rustc_hir" }
-rustc_hir_pretty = { path = "../rustc_hir_pretty" }
-rustc_lexer = { path = "../rustc_lexer" }
-rustc_macros = { path = "../rustc_macros" }
-serde_json = "1"
-rustc_session = { path = "../rustc_session" }
-rustc_span = { path = "../rustc_span" }
-rls-data = "0.19"
-rls-span = "0.5"
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
deleted file mode 100644
index 3982111e38e..00000000000
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ /dev/null
@@ -1,1465 +0,0 @@
-//! Write the output of rustc's analysis to an implementor of Dump.
-//!
-//! Dumping the analysis is implemented by walking the AST and getting a bunch of
-//! info out from all over the place. We use `DefId`s to identify objects. The
-//! tricky part is getting syntactic (span, source text) and semantic (reference
-//! `DefId`s) information for parts of expressions which the compiler has discarded.
-//! E.g., in a path `foo::bar::baz`, the compiler only keeps a span for the whole
-//! path and a reference to `baz`, but we want spans and references for all three
-//! idents.
-//!
-//! SpanUtils is used to manipulate spans. In particular, to extract sub-spans
-//! from spans (e.g., the span for `bar` from the above example path).
-//! DumpVisitor walks the AST and processes it, and Dumper is used for
-//! recording the output.
-
-use rustc_ast as ast;
-use rustc_ast::walk_list;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind as HirDefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir_pretty::{bounds_to_string, fn_to_string, generic_params_to_string, ty_to_string};
-use rustc_middle::hir::nested_filter;
-use rustc_middle::span_bug;
-use rustc_middle::ty::{self, DefIdTree, TyCtxt};
-use rustc_session::config::Input;
-use rustc_span::symbol::Ident;
-use rustc_span::*;
-
-use std::env;
-use std::path::Path;
-
-use crate::dumper::{Access, Dumper};
-use crate::sig;
-use crate::span_utils::SpanUtils;
-use crate::{
-    escape, generated_code, id_from_def_id, id_from_hir_id, lower_attributes, PathCollector,
-    SaveContext,
-};
-
-use rls_data::{
-    CompilationOptions, CratePreludeData, Def, DefKind, GlobalCrateId, Import, ImportKind, Ref,
-    RefKind, Relation, RelationKind, SpanData,
-};
-
-#[rustfmt::skip] // https://github.com/rust-lang/rustfmt/issues/5213
-macro_rules! down_cast_data {
-    ($id:ident, $kind:ident, $sp:expr) => {
-        let super::Data::$kind($id) = $id else {
-            span_bug!($sp, "unexpected data kind: {:?}", $id);
-        };
-    };
-}
-
-macro_rules! access_from {
-    ($save_ctxt:expr, $id:expr) => {
-        Access {
-            public: $save_ctxt.tcx.visibility($id).is_public(),
-            reachable: $save_ctxt.effective_visibilities.is_reachable($id),
-        }
-    };
-}
-
-pub struct DumpVisitor<'tcx> {
-    pub save_ctxt: SaveContext<'tcx>,
-    tcx: TyCtxt<'tcx>,
-    dumper: Dumper,
-
-    span: SpanUtils<'tcx>,
-    // Set of macro definition (callee) spans, and the set
-    // of macro use (callsite) spans. We store these to ensure
-    // we only write one macro def per unique macro definition, and
-    // one macro use per unique callsite span.
-    // mac_defs: FxHashSet<Span>,
-    // macro_calls: FxHashSet<Span>,
-}
-
-impl<'tcx> DumpVisitor<'tcx> {
-    pub fn new(save_ctxt: SaveContext<'tcx>) -> DumpVisitor<'tcx> {
-        let span_utils = SpanUtils::new(&save_ctxt.tcx.sess);
-        let dumper = Dumper::new(save_ctxt.config.clone());
-        DumpVisitor { tcx: save_ctxt.tcx, save_ctxt, dumper, span: span_utils }
-    }
-
-    pub fn analysis(&self) -> &rls_data::Analysis {
-        self.dumper.analysis()
-    }
-
-    fn nest_typeck_results<F>(&mut self, item_def_id: LocalDefId, f: F)
-    where
-        F: FnOnce(&mut Self),
-    {
-        let typeck_results = if self.tcx.has_typeck_results(item_def_id) {
-            Some(self.tcx.typeck(item_def_id))
-        } else {
-            None
-        };
-
-        let old_maybe_typeck_results = self.save_ctxt.maybe_typeck_results;
-        self.save_ctxt.maybe_typeck_results = typeck_results;
-        f(self);
-        self.save_ctxt.maybe_typeck_results = old_maybe_typeck_results;
-    }
-
-    fn span_from_span(&self, span: Span) -> SpanData {
-        self.save_ctxt.span_from_span(span)
-    }
-
-    fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
-        self.save_ctxt.lookup_def_id(ref_id)
-    }
-
-    pub fn dump_crate_info(&mut self, name: Symbol) {
-        let crate_root = self.tcx.sess.local_crate_source_file().map(|source_file| {
-            match source_file.file_name() {
-                Some(_) => source_file.parent().unwrap().display(),
-                None => source_file.display(),
-            }
-            .to_string()
-        });
-
-        let data = CratePreludeData {
-            crate_id: GlobalCrateId {
-                name: name.to_string(),
-                disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
-            },
-            crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
-            external_crates: self.save_ctxt.get_external_crates(),
-            span: self.span_from_span(self.tcx.def_span(CRATE_DEF_ID)),
-        };
-
-        self.dumper.crate_prelude(data);
-    }
-
-    pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) {
-        // Apply possible `remap-path-prefix` remapping to the input source file
-        // (and don't include remapping args anymore)
-        let (program, arguments) = {
-            let remap_arg_indices = {
-                let mut indices = FxHashSet::default();
-                // Args are guaranteed to be valid UTF-8 (checked early)
-                for (i, e) in env::args().enumerate() {
-                    if e.starts_with("--remap-path-prefix=") {
-                        indices.insert(i);
-                    } else if e == "--remap-path-prefix" {
-                        indices.insert(i);
-                        indices.insert(i + 1);
-                    }
-                }
-                indices
-            };
-
-            let mut args = env::args()
-                .enumerate()
-                .filter(|(i, _)| !remap_arg_indices.contains(i))
-                .map(|(_, arg)| match input {
-                    Input::File(ref path) if path == Path::new(&arg) => self
-                        .tcx
-                        .sess
-                        .local_crate_source_file()
-                        .as_ref()
-                        .unwrap()
-                        .to_string_lossy()
-                        .into(),
-                    _ => arg,
-                });
-
-            (args.next().unwrap(), args.collect())
-        };
-
-        let data = CompilationOptions {
-            directory: self.tcx.sess.opts.working_dir.remapped_path_if_available().into(),
-            program,
-            arguments,
-            output: self.save_ctxt.compilation_output(crate_name),
-        };
-
-        self.dumper.compilation_opts(data);
-    }
-
-    fn write_segments(&mut self, segments: impl IntoIterator<Item = &'tcx hir::PathSegment<'tcx>>) {
-        for seg in segments {
-            if let Some(data) = self.save_ctxt.get_path_segment_data(seg) {
-                self.dumper.dump_ref(data);
-            }
-        }
-    }
-
-    fn write_sub_paths<R>(&mut self, path: &'tcx hir::Path<'tcx, R>) {
-        self.write_segments(path.segments)
-    }
-
-    // As write_sub_paths, but does not process the last ident in the path (assuming it
-    // will be processed elsewhere). See note on write_sub_paths about global.
-    fn write_sub_paths_truncated<R>(&mut self, path: &'tcx hir::Path<'tcx, R>) {
-        if let [segments @ .., _] = path.segments {
-            self.write_segments(segments)
-        }
-    }
-
-    fn process_formals(&mut self, formals: &'tcx [hir::Param<'tcx>], qualname: &str) {
-        for arg in formals {
-            self.visit_pat(&arg.pat);
-            let mut collector = PathCollector::new(self.tcx);
-            collector.visit_pat(&arg.pat);
-
-            for (hir_id, ident, ..) in collector.collected_idents {
-                let typ = match self.save_ctxt.typeck_results().node_type_opt(hir_id) {
-                    Some(s) => s.to_string(),
-                    None => continue,
-                };
-                if !self.span.filter_generated(ident.span) {
-                    let id = id_from_hir_id(hir_id);
-                    let span = self.span_from_span(ident.span);
-
-                    self.dumper.dump_def(
-                        &Access { public: false, reachable: false },
-                        Def {
-                            kind: DefKind::Local,
-                            id,
-                            span,
-                            name: ident.to_string(),
-                            qualname: format!("{}::{}", qualname, ident),
-                            value: typ,
-                            parent: None,
-                            children: vec![],
-                            decl_id: None,
-                            docs: String::new(),
-                            sig: None,
-                            attributes: vec![],
-                        },
-                    );
-                }
-            }
-        }
-    }
-
-    fn process_method(
-        &mut self,
-        sig: &'tcx hir::FnSig<'tcx>,
-        body: Option<hir::BodyId>,
-        owner_id: hir::OwnerId,
-        ident: Ident,
-        generics: &'tcx hir::Generics<'tcx>,
-        span: Span,
-    ) {
-        debug!("process_method: {:?}:{}", owner_id, ident);
-
-        let map = self.tcx.hir();
-        let hir_id: hir::HirId = owner_id.into();
-        self.nest_typeck_results(owner_id.def_id, |v| {
-            if let Some(mut method_data) = v.save_ctxt.get_method_data(owner_id, ident, span) {
-                if let Some(body) = body {
-                    v.process_formals(map.body(body).params, &method_data.qualname);
-                }
-                v.process_generic_params(&generics, &method_data.qualname, hir_id);
-
-                method_data.value =
-                    fn_to_string(sig.decl, sig.header, Some(ident.name), generics, &[], None);
-                method_data.sig =
-                    sig::method_signature(owner_id, ident, generics, sig, &v.save_ctxt);
-
-                v.dumper.dump_def(&access_from!(v.save_ctxt, owner_id.def_id), method_data);
-            }
-
-            // walk arg and return types
-            for arg in sig.decl.inputs {
-                v.visit_ty(arg);
-            }
-
-            if let hir::FnRetTy::Return(ref ret_ty) = sig.decl.output {
-                v.visit_ty(ret_ty)
-            }
-
-            // walk the fn body
-            if let Some(body) = body {
-                v.visit_expr(&map.body(body).value);
-            }
-        });
-    }
-
-    fn process_struct_field_def(
-        &mut self,
-        field: &'tcx hir::FieldDef<'tcx>,
-        parent_id: LocalDefId,
-    ) {
-        let field_data = self.save_ctxt.get_field_data(field, parent_id);
-        if let Some(field_data) = field_data {
-            self.dumper.dump_def(&access_from!(self.save_ctxt, field.def_id), field_data);
-        }
-    }
-
-    // Dump generic params bindings, then visit_generics
-    fn process_generic_params(
-        &mut self,
-        generics: &'tcx hir::Generics<'tcx>,
-        prefix: &str,
-        id: hir::HirId,
-    ) {
-        for param in generics.params {
-            match param.kind {
-                hir::GenericParamKind::Lifetime { .. } => {}
-                hir::GenericParamKind::Type { .. } => {
-                    let param_ss = param.name.ident().span;
-                    let name = escape(self.span.snippet(param_ss));
-                    // Append $id to name to make sure each one is unique.
-                    let qualname = format!("{}::{}${}", prefix, name, id);
-                    if !self.span.filter_generated(param_ss) {
-                        let id = id_from_def_id(param.def_id.to_def_id());
-                        let span = self.span_from_span(param_ss);
-
-                        self.dumper.dump_def(
-                            &Access { public: false, reachable: false },
-                            Def {
-                                kind: DefKind::Type,
-                                id,
-                                span,
-                                name,
-                                qualname,
-                                value: String::new(),
-                                parent: None,
-                                children: vec![],
-                                decl_id: None,
-                                docs: String::new(),
-                                sig: None,
-                                attributes: vec![],
-                            },
-                        );
-                    }
-                }
-                hir::GenericParamKind::Const { .. } => {}
-            }
-        }
-
-        self.visit_generics(generics)
-    }
-
-    fn process_fn(
-        &mut self,
-        item: &'tcx hir::Item<'tcx>,
-        decl: &'tcx hir::FnDecl<'tcx>,
-        _header: &'tcx hir::FnHeader,
-        ty_params: &'tcx hir::Generics<'tcx>,
-        body: hir::BodyId,
-    ) {
-        let map = self.tcx.hir();
-        self.nest_typeck_results(item.owner_id.def_id, |v| {
-            let body = map.body(body);
-            if let Some(fn_data) = v.save_ctxt.get_item_data(item) {
-                down_cast_data!(fn_data, DefData, item.span);
-                v.process_formals(body.params, &fn_data.qualname);
-                v.process_generic_params(ty_params, &fn_data.qualname, item.hir_id());
-
-                v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), fn_data);
-            }
-
-            for arg in decl.inputs {
-                v.visit_ty(arg)
-            }
-
-            if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
-                v.visit_ty(ret_ty)
-            }
-
-            v.visit_expr(&body.value);
-        });
-    }
-
-    fn process_static_or_const_item(
-        &mut self,
-        item: &'tcx hir::Item<'tcx>,
-        typ: &'tcx hir::Ty<'tcx>,
-        expr: &'tcx hir::Expr<'tcx>,
-    ) {
-        self.nest_typeck_results(item.owner_id.def_id, |v| {
-            if let Some(var_data) = v.save_ctxt.get_item_data(item) {
-                down_cast_data!(var_data, DefData, item.span);
-                v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), var_data);
-            }
-            v.visit_ty(&typ);
-            v.visit_expr(expr);
-        });
-    }
-
-    fn process_assoc_const(
-        &mut self,
-        owner_id: hir::OwnerId,
-        ident: Ident,
-        typ: &'tcx hir::Ty<'tcx>,
-        expr: Option<&'tcx hir::Expr<'tcx>>,
-        parent_id: DefId,
-        attrs: &'tcx [ast::Attribute],
-    ) {
-        let qualname = format!("::{}", self.tcx.def_path_str(owner_id.to_def_id()));
-
-        if !self.span.filter_generated(ident.span) {
-            let sig = sig::assoc_const_signature(owner_id, ident.name, typ, expr, &self.save_ctxt);
-            let span = self.span_from_span(ident.span);
-
-            self.dumper.dump_def(
-                &access_from!(self.save_ctxt, owner_id.def_id),
-                Def {
-                    kind: DefKind::Const,
-                    id: id_from_def_id(owner_id.to_def_id()),
-                    span,
-                    name: ident.name.to_string(),
-                    qualname,
-                    value: ty_to_string(&typ),
-                    parent: Some(id_from_def_id(parent_id)),
-                    children: vec![],
-                    decl_id: None,
-                    docs: self.save_ctxt.docs_for_attrs(attrs),
-                    sig,
-                    attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
-                },
-            );
-        }
-
-        // walk type and init value
-        self.nest_typeck_results(owner_id.def_id, |v| {
-            v.visit_ty(typ);
-            if let Some(expr) = expr {
-                v.visit_expr(expr);
-            }
-        });
-    }
-
-    // FIXME tuple structs should generate tuple-specific data.
-    fn process_struct(
-        &mut self,
-        item: &'tcx hir::Item<'tcx>,
-        def: &'tcx hir::VariantData<'tcx>,
-        ty_params: &'tcx hir::Generics<'tcx>,
-    ) {
-        debug!("process_struct {:?} {:?}", item, item.span);
-        let name = item.ident.to_string();
-        let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id()));
-
-        let kind = match item.kind {
-            hir::ItemKind::Struct(_, _) => DefKind::Struct,
-            hir::ItemKind::Union(_, _) => DefKind::Union,
-            _ => unreachable!(),
-        };
-
-        let (value, fields) = match item.kind {
-            hir::ItemKind::Struct(hir::VariantData::Struct(ref fields, ..), ..)
-            | hir::ItemKind::Union(hir::VariantData::Struct(ref fields, ..), ..) => {
-                let include_priv_fields = !self.save_ctxt.config.pub_only;
-                let fields_str = fields
-                    .iter()
-                    .filter_map(|f| {
-                        if include_priv_fields {
-                            return Some(f.ident.to_string());
-                        }
-                        if self.save_ctxt.tcx.visibility(f.def_id).is_public() {
-                            Some(f.ident.to_string())
-                        } else {
-                            None
-                        }
-                    })
-                    .collect::<Vec<_>>()
-                    .join(", ");
-                let value = format!("{} {{ {} }}", name, fields_str);
-                (value, fields.iter().map(|f| id_from_def_id(f.def_id.to_def_id())).collect())
-            }
-            _ => (String::new(), vec![]),
-        };
-
-        if !self.span.filter_generated(item.ident.span) {
-            let span = self.span_from_span(item.ident.span);
-            let attrs = self.tcx.hir().attrs(item.hir_id());
-            self.dumper.dump_def(
-                &access_from!(self.save_ctxt, item.owner_id.def_id),
-                Def {
-                    kind,
-                    id: id_from_def_id(item.owner_id.to_def_id()),
-                    span,
-                    name,
-                    qualname: qualname.clone(),
-                    value,
-                    parent: None,
-                    children: fields,
-                    decl_id: None,
-                    docs: self.save_ctxt.docs_for_attrs(attrs),
-                    sig: sig::item_signature(item, &self.save_ctxt),
-                    attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
-                },
-            );
-        }
-
-        self.nest_typeck_results(item.owner_id.def_id, |v| {
-            for field in def.fields() {
-                v.process_struct_field_def(field, item.owner_id.def_id);
-                v.visit_ty(&field.ty);
-            }
-
-            v.process_generic_params(ty_params, &qualname, item.hir_id());
-        });
-    }
-
-    fn process_enum(
-        &mut self,
-        item: &'tcx hir::Item<'tcx>,
-        enum_definition: &'tcx hir::EnumDef<'tcx>,
-        ty_params: &'tcx hir::Generics<'tcx>,
-    ) {
-        let enum_data = self.save_ctxt.get_item_data(item);
-        let Some(enum_data) = enum_data else {
-            return;
-        };
-        down_cast_data!(enum_data, DefData, item.span);
-
-        let access = access_from!(self.save_ctxt, item.owner_id.def_id);
-
-        for variant in enum_definition.variants {
-            let name = variant.ident.name.to_string();
-            let qualname = format!("{}::{}", enum_data.qualname, name);
-            let name_span = variant.ident.span;
-
-            match variant.data {
-                hir::VariantData::Struct(ref fields, ..) => {
-                    let fields_str =
-                        fields.iter().map(|f| f.ident.to_string()).collect::<Vec<_>>().join(", ");
-                    let value = format!("{}::{} {{ {} }}", enum_data.name, name, fields_str);
-                    if !self.span.filter_generated(name_span) {
-                        let span = self.span_from_span(name_span);
-                        let id = id_from_def_id(variant.def_id.to_def_id());
-                        let parent = Some(id_from_def_id(item.owner_id.to_def_id()));
-                        let attrs = self.tcx.hir().attrs(variant.hir_id);
-
-                        self.dumper.dump_def(
-                            &access,
-                            Def {
-                                kind: DefKind::StructVariant,
-                                id,
-                                span,
-                                name,
-                                qualname,
-                                value,
-                                parent,
-                                children: vec![],
-                                decl_id: None,
-                                docs: self.save_ctxt.docs_for_attrs(attrs),
-                                sig: sig::variant_signature(variant, &self.save_ctxt),
-                                attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
-                            },
-                        );
-                    }
-                }
-                ref v => {
-                    let mut value = format!("{}::{}", enum_data.name, name);
-                    if let hir::VariantData::Tuple(fields, _, _) = v {
-                        value.push('(');
-                        value.push_str(
-                            &fields
-                                .iter()
-                                .map(|f| ty_to_string(&f.ty))
-                                .collect::<Vec<_>>()
-                                .join(", "),
-                        );
-                        value.push(')');
-                    }
-                    if !self.span.filter_generated(name_span) {
-                        let span = self.span_from_span(name_span);
-                        let id = id_from_def_id(variant.def_id.to_def_id());
-                        let parent = Some(id_from_def_id(item.owner_id.to_def_id()));
-                        let attrs = self.tcx.hir().attrs(variant.hir_id);
-
-                        self.dumper.dump_def(
-                            &access,
-                            Def {
-                                kind: DefKind::TupleVariant,
-                                id,
-                                span,
-                                name,
-                                qualname,
-                                value,
-                                parent,
-                                children: vec![],
-                                decl_id: None,
-                                docs: self.save_ctxt.docs_for_attrs(attrs),
-                                sig: sig::variant_signature(variant, &self.save_ctxt),
-                                attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
-                            },
-                        );
-                    }
-                }
-            }
-
-            for field in variant.data.fields() {
-                self.process_struct_field_def(field, variant.def_id);
-                self.visit_ty(field.ty);
-            }
-        }
-        self.process_generic_params(ty_params, &enum_data.qualname, item.hir_id());
-        self.dumper.dump_def(&access, enum_data);
-    }
-
-    fn process_impl(&mut self, item: &'tcx hir::Item<'tcx>, impl_: &'tcx hir::Impl<'tcx>) {
-        if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
-            if !self.span.filter_generated(item.span) {
-                if let super::Data::RelationData(rel, imp) = impl_data {
-                    self.dumper.dump_relation(rel);
-                    self.dumper.dump_impl(imp);
-                } else {
-                    span_bug!(item.span, "unexpected data kind: {:?}", impl_data);
-                }
-            }
-        }
-
-        let map = self.tcx.hir();
-        self.nest_typeck_results(item.owner_id.def_id, |v| {
-            v.visit_ty(&impl_.self_ty);
-            if let Some(trait_ref) = &impl_.of_trait {
-                v.process_path(trait_ref.hir_ref_id, &hir::QPath::Resolved(None, &trait_ref.path));
-            }
-            v.process_generic_params(&impl_.generics, "", item.hir_id());
-            for impl_item in impl_.items {
-                v.process_impl_item(map.impl_item(impl_item.id), item.owner_id.to_def_id());
-            }
-        });
-    }
-
-    fn process_trait(
-        &mut self,
-        item: &'tcx hir::Item<'tcx>,
-        generics: &'tcx hir::Generics<'tcx>,
-        trait_refs: hir::GenericBounds<'tcx>,
-        methods: &'tcx [hir::TraitItemRef],
-    ) {
-        let name = item.ident.to_string();
-        let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id()));
-        let mut val = name.clone();
-        if !generics.params.is_empty() {
-            val.push_str(&generic_params_to_string(generics.params));
-        }
-        if !trait_refs.is_empty() {
-            val.push_str(": ");
-            val.push_str(&bounds_to_string(trait_refs));
-        }
-        if !self.span.filter_generated(item.ident.span) {
-            let id = id_from_def_id(item.owner_id.to_def_id());
-            let span = self.span_from_span(item.ident.span);
-            let children =
-                methods.iter().map(|i| id_from_def_id(i.id.owner_id.to_def_id())).collect();
-            let attrs = self.tcx.hir().attrs(item.hir_id());
-            self.dumper.dump_def(
-                &access_from!(self.save_ctxt, item.owner_id.def_id),
-                Def {
-                    kind: DefKind::Trait,
-                    id,
-                    span,
-                    name,
-                    qualname: qualname.clone(),
-                    value: val,
-                    parent: None,
-                    children,
-                    decl_id: None,
-                    docs: self.save_ctxt.docs_for_attrs(attrs),
-                    sig: sig::item_signature(item, &self.save_ctxt),
-                    attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
-                },
-            );
-        }
-
-        // supertraits
-        for super_bound in trait_refs.iter() {
-            let (def_id, sub_span) = match *super_bound {
-                hir::GenericBound::Trait(ref trait_ref, _) => (
-                    self.lookup_def_id(trait_ref.trait_ref.hir_ref_id),
-                    trait_ref.trait_ref.path.segments.last().unwrap().ident.span,
-                ),
-                hir::GenericBound::LangItemTrait(lang_item, span, _, _) => {
-                    (Some(self.tcx.require_lang_item(lang_item, Some(span))), span)
-                }
-                hir::GenericBound::Outlives(..) => continue,
-            };
-
-            if let Some(id) = def_id {
-                if !self.span.filter_generated(sub_span) {
-                    let span = self.span_from_span(sub_span);
-                    self.dumper.dump_ref(Ref {
-                        kind: RefKind::Type,
-                        span: span.clone(),
-                        ref_id: id_from_def_id(id),
-                    });
-
-                    self.dumper.dump_relation(Relation {
-                        kind: RelationKind::SuperTrait,
-                        span,
-                        from: id_from_def_id(id),
-                        to: id_from_def_id(item.owner_id.to_def_id()),
-                    });
-                }
-            }
-        }
-
-        // walk generics and methods
-        self.process_generic_params(generics, &qualname, item.hir_id());
-        for method in methods {
-            let map = self.tcx.hir();
-            self.process_trait_item(map.trait_item(method.id), item.owner_id.to_def_id())
-        }
-    }
-
-    // `item` is the module in question, represented as an( item.
-    fn process_mod(&mut self, item: &'tcx hir::Item<'tcx>) {
-        if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(mod_data, DefData, item.span);
-            self.dumper.dump_def(&access_from!(self.save_ctxt, item.owner_id.def_id), mod_data);
-        }
-    }
-
-    fn dump_path_ref(&mut self, id: hir::HirId, path: &hir::QPath<'tcx>) {
-        let path_data = self.save_ctxt.get_path_data(id, path);
-        if let Some(path_data) = path_data {
-            self.dumper.dump_ref(path_data);
-        }
-    }
-
-    fn dump_path_segment_ref(&mut self, id: hir::HirId, segment: &hir::PathSegment<'tcx>) {
-        let segment_data = self.save_ctxt.get_path_segment_data_with_id(segment, id);
-        if let Some(segment_data) = segment_data {
-            self.dumper.dump_ref(segment_data);
-        }
-    }
-
-    fn process_path(&mut self, id: hir::HirId, path: &hir::QPath<'tcx>) {
-        if self.span.filter_generated(path.span()) {
-            return;
-        }
-        self.dump_path_ref(id, path);
-
-        // Type arguments
-        let segments = match path {
-            hir::QPath::Resolved(ty, path) => {
-                if let Some(ty) = ty {
-                    self.visit_ty(ty);
-                }
-                path.segments
-            }
-            hir::QPath::TypeRelative(ty, segment) => {
-                self.visit_ty(ty);
-                std::slice::from_ref(*segment)
-            }
-            hir::QPath::LangItem(..) => return,
-        };
-        for seg in segments {
-            if let Some(ref generic_args) = seg.args {
-                for arg in generic_args.args {
-                    if let hir::GenericArg::Type(ref ty) = arg {
-                        self.visit_ty(ty);
-                    }
-                }
-            }
-        }
-
-        if let hir::QPath::Resolved(_, path) = path {
-            self.write_sub_paths_truncated(path);
-        }
-    }
-
-    fn process_struct_lit(
-        &mut self,
-        ex: &'tcx hir::Expr<'tcx>,
-        path: &'tcx hir::QPath<'tcx>,
-        fields: &'tcx [hir::ExprField<'tcx>],
-        variant: &'tcx ty::VariantDef,
-        rest: Option<&'tcx hir::Expr<'tcx>>,
-    ) {
-        if let Some(_ex_res_data) = self.save_ctxt.get_expr_data(ex) {
-            if let hir::QPath::Resolved(_, path) = path {
-                self.write_sub_paths_truncated(path);
-            }
-            // For MyEnum::MyVariant, get_expr_data gives us MyEnum, not MyVariant.
-            // For recording the span's ref id, we want MyVariant.
-            if !generated_code(ex.span) {
-                let sub_span = path.last_segment_span();
-                let span = self.save_ctxt.span_from_span(sub_span);
-                let reff =
-                    Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(variant.def_id) };
-                self.dumper.dump_ref(reff);
-            }
-
-            for field in fields {
-                if let Some(field_data) = self.save_ctxt.get_field_ref_data(field, variant) {
-                    self.dumper.dump_ref(field_data);
-                }
-
-                self.visit_expr(&field.expr)
-            }
-        }
-
-        if let Some(base) = rest {
-            self.visit_expr(&base);
-        }
-    }
-
-    fn process_method_call(
-        &mut self,
-        ex: &'tcx hir::Expr<'tcx>,
-        seg: &'tcx hir::PathSegment<'tcx>,
-        receiver: &'tcx hir::Expr<'tcx>,
-        args: &'tcx [hir::Expr<'tcx>],
-    ) {
-        debug!("process_method_call {:?} {:?}", ex, ex.span);
-        if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
-            down_cast_data!(mcd, RefData, ex.span);
-            if !generated_code(ex.span) {
-                self.dumper.dump_ref(mcd);
-            }
-        }
-
-        // Explicit types in the turbo-fish.
-        if let Some(generic_args) = seg.args {
-            for arg in generic_args.args {
-                if let hir::GenericArg::Type(ty) = arg {
-                    self.visit_ty(&ty)
-                };
-            }
-        }
-
-        // walk receiver and args
-        self.visit_expr(receiver);
-        walk_list!(self, visit_expr, args);
-    }
-
-    fn process_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
-        match p.kind {
-            hir::PatKind::Struct(ref _path, fields, _) => {
-                // FIXME do something with _path?
-                let adt = match self.save_ctxt.typeck_results().node_type_opt(p.hir_id) {
-                    Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
-                    _ => {
-                        intravisit::walk_pat(self, p);
-                        return;
-                    }
-                };
-                let variant = adt.variant_of_res(self.save_ctxt.get_path_res(p.hir_id));
-
-                for field in fields {
-                    if let Some(index) = self.tcx.find_field_index(field.ident, variant) {
-                        if !self.span.filter_generated(field.ident.span) {
-                            let span = self.span_from_span(field.ident.span);
-                            self.dumper.dump_ref(Ref {
-                                kind: RefKind::Variable,
-                                span,
-                                ref_id: id_from_def_id(variant.fields[index].did),
-                            });
-                        }
-                    }
-                    self.visit_pat(&field.pat);
-                }
-            }
-            _ => intravisit::walk_pat(self, p),
-        }
-    }
-
-    fn process_var_decl(&mut self, pat: &'tcx hir::Pat<'tcx>) {
-        // The pattern could declare multiple new vars,
-        // we must walk the pattern and collect them all.
-        let mut collector = PathCollector::new(self.tcx);
-        collector.visit_pat(&pat);
-        self.visit_pat(&pat);
-
-        // Process collected paths.
-        for (id, ident, _) in collector.collected_idents {
-            let res = self.save_ctxt.get_path_res(id);
-            match res {
-                Res::Local(hir_id) => {
-                    let typ = self
-                        .save_ctxt
-                        .typeck_results()
-                        .node_type_opt(hir_id)
-                        .map(|t| t.to_string())
-                        .unwrap_or_default();
-
-                    // Rust uses the id of the pattern for var lookups, so we'll use it too.
-                    if !self.span.filter_generated(ident.span) {
-                        let qualname = format!("{}${}", ident, hir_id);
-                        let id = id_from_hir_id(hir_id);
-                        let span = self.span_from_span(ident.span);
-
-                        self.dumper.dump_def(
-                            &Access { public: false, reachable: false },
-                            Def {
-                                kind: DefKind::Local,
-                                id,
-                                span,
-                                name: ident.to_string(),
-                                qualname,
-                                value: typ,
-                                parent: None,
-                                children: vec![],
-                                decl_id: None,
-                                docs: String::new(),
-                                sig: None,
-                                attributes: vec![],
-                            },
-                        );
-                    }
-                }
-                Res::Def(
-                    HirDefKind::Ctor(..)
-                    | HirDefKind::Const
-                    | HirDefKind::AssocConst
-                    | HirDefKind::Struct
-                    | HirDefKind::Variant
-                    | HirDefKind::TyAlias
-                    | HirDefKind::AssocTy,
-                    _,
-                )
-                | Res::SelfTyParam { .. }
-                | Res::SelfTyAlias { .. } => {
-                    self.dump_path_segment_ref(
-                        id,
-                        &hir::PathSegment::new(ident, hir::HirId::INVALID, Res::Err),
-                    );
-                }
-                def => {
-                    error!("unexpected definition kind when processing collected idents: {:?}", def)
-                }
-            }
-        }
-
-        for (id, ref path) in collector.collected_paths {
-            self.process_path(id, path);
-        }
-    }
-
-    /// Extracts macro use and definition information from the AST node defined
-    /// by the given NodeId, using the expansion information from the node's
-    /// span.
-    ///
-    /// If the span is not macro-generated, do nothing, else use callee and
-    /// callsite spans to record macro definition and use data, using the
-    /// mac_uses and mac_defs sets to prevent multiples.
-    fn process_macro_use(&mut self, _span: Span) {
-        // FIXME if we're not dumping the defs (see below), there is no point
-        // dumping refs either.
-        // let source_span = span.source_callsite();
-        // if !self.macro_calls.insert(source_span) {
-        //     return;
-        // }
-
-        // let data = match self.save_ctxt.get_macro_use_data(span) {
-        //     None => return,
-        //     Some(data) => data,
-        // };
-
-        // self.dumper.macro_use(data);
-
-        // FIXME write the macro def
-        // let mut hasher = DefaultHasher::new();
-        // data.callee_span.hash(&mut hasher);
-        // let hash = hasher.finish();
-        // let qualname = format!("{}::{}", data.name, hash);
-        // Don't write macro definition for imported macros
-        // if !self.mac_defs.contains(&data.callee_span)
-        //     && !data.imported {
-        //     self.mac_defs.insert(data.callee_span);
-        //     if let Some(sub_span) = self.span.span_for_macro_def_name(data.callee_span) {
-        //         self.dumper.macro_data(MacroData {
-        //             span: sub_span,
-        //             name: data.name.clone(),
-        //             qualname: qualname.clone(),
-        //             // FIXME where do macro docs come from?
-        //             docs: String::new(),
-        //         }.lower(self.tcx));
-        //     }
-        // }
-    }
-
-    fn process_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>, trait_id: DefId) {
-        self.process_macro_use(trait_item.span);
-        match trait_item.kind {
-            hir::TraitItemKind::Const(ref ty, body) => {
-                let body = body.map(|b| self.tcx.hir().body(b).value);
-                let attrs = self.tcx.hir().attrs(trait_item.hir_id());
-                self.process_assoc_const(
-                    trait_item.owner_id,
-                    trait_item.ident,
-                    &ty,
-                    body,
-                    trait_id,
-                    attrs,
-                );
-            }
-            hir::TraitItemKind::Fn(ref sig, ref trait_fn) => {
-                let body =
-                    if let hir::TraitFn::Provided(body) = trait_fn { Some(*body) } else { None };
-                self.process_method(
-                    sig,
-                    body,
-                    trait_item.owner_id,
-                    trait_item.ident,
-                    &trait_item.generics,
-                    trait_item.span,
-                );
-            }
-            hir::TraitItemKind::Type(ref bounds, ref default_ty) => {
-                // FIXME do something with _bounds (for type refs)
-                let name = trait_item.ident.name.to_string();
-                let qualname =
-                    format!("::{}", self.tcx.def_path_str(trait_item.owner_id.to_def_id()));
-
-                if !self.span.filter_generated(trait_item.ident.span) {
-                    let span = self.span_from_span(trait_item.ident.span);
-                    let id = id_from_def_id(trait_item.owner_id.to_def_id());
-                    let attrs = self.tcx.hir().attrs(trait_item.hir_id());
-
-                    self.dumper.dump_def(
-                        &Access { public: true, reachable: true },
-                        Def {
-                            kind: DefKind::Type,
-                            id,
-                            span,
-                            name,
-                            qualname,
-                            value: self.span.snippet(trait_item.span),
-                            parent: Some(id_from_def_id(trait_id)),
-                            children: vec![],
-                            decl_id: None,
-                            docs: self.save_ctxt.docs_for_attrs(attrs),
-                            sig: sig::assoc_type_signature(
-                                trait_item.owner_id,
-                                trait_item.ident,
-                                Some(bounds),
-                                default_ty.as_deref(),
-                                &self.save_ctxt,
-                            ),
-                            attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
-                        },
-                    );
-                }
-
-                if let Some(default_ty) = default_ty {
-                    self.visit_ty(default_ty)
-                }
-            }
-        }
-    }
-
-    fn process_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>, impl_id: DefId) {
-        self.process_macro_use(impl_item.span);
-        match impl_item.kind {
-            hir::ImplItemKind::Const(ref ty, body) => {
-                let body = self.tcx.hir().body(body);
-                let attrs = self.tcx.hir().attrs(impl_item.hir_id());
-                self.process_assoc_const(
-                    impl_item.owner_id,
-                    impl_item.ident,
-                    &ty,
-                    Some(&body.value),
-                    impl_id,
-                    attrs,
-                );
-            }
-            hir::ImplItemKind::Fn(ref sig, body) => {
-                self.process_method(
-                    sig,
-                    Some(body),
-                    impl_item.owner_id,
-                    impl_item.ident,
-                    &impl_item.generics,
-                    impl_item.span,
-                );
-            }
-            hir::ImplItemKind::Type(ref ty) => {
-                // FIXME: uses of the assoc type should ideally point to this
-                // 'def' and the name here should be a ref to the def in the
-                // trait.
-                self.visit_ty(ty)
-            }
-        }
-    }
-
-    pub(crate) fn process_crate(&mut self) {
-        let qualname = format!("::{}", self.tcx.def_path_str(CRATE_DEF_ID.to_def_id()));
-
-        let sm = self.tcx.sess.source_map();
-        let krate_mod = self.tcx.hir().root_module();
-        let filename = sm.span_to_filename(krate_mod.spans.inner_span);
-        let data_id = id_from_def_id(CRATE_DEF_ID.to_def_id());
-        let children =
-            krate_mod.item_ids.iter().map(|i| id_from_def_id(i.owner_id.to_def_id())).collect();
-        let span = self.span_from_span(krate_mod.spans.inner_span);
-        let attrs = self.tcx.hir().attrs(hir::CRATE_HIR_ID);
-
-        self.dumper.dump_def(
-            &Access { public: true, reachable: true },
-            Def {
-                kind: DefKind::Mod,
-                id: data_id,
-                name: String::new(),
-                qualname,
-                span,
-                value: filename.prefer_remapped().to_string(),
-                children,
-                parent: None,
-                decl_id: None,
-                docs: self.save_ctxt.docs_for_attrs(attrs),
-                sig: None,
-                attributes: lower_attributes(attrs.to_owned(), &self.save_ctxt),
-            },
-        );
-        self.tcx.hir().walk_toplevel_module(self);
-    }
-
-    fn process_bounds(&mut self, bounds: hir::GenericBounds<'tcx>) {
-        for bound in bounds {
-            if let hir::GenericBound::Trait(ref trait_ref, _) = *bound {
-                self.process_path(
-                    trait_ref.trait_ref.hir_ref_id,
-                    &hir::QPath::Resolved(None, &trait_ref.trait_ref.path),
-                )
-            }
-        }
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
-        self.process_macro_use(item.span);
-        match item.kind {
-            hir::ItemKind::Use(path, hir::UseKind::Single) => {
-                let sub_span = path.segments.last().unwrap().ident.span;
-                if !self.span.filter_generated(sub_span) {
-                    let access = access_from!(self.save_ctxt, item.owner_id.def_id);
-                    let ref_id = self.lookup_def_id(item.hir_id()).map(id_from_def_id);
-                    let span = self.span_from_span(sub_span);
-                    let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
-                    self.dumper.import(
-                        &access,
-                        Import {
-                            kind: ImportKind::Use,
-                            ref_id,
-                            span,
-                            alias_span: None,
-                            name: item.ident.to_string(),
-                            value: String::new(),
-                            parent: Some(id_from_def_id(parent.to_def_id())),
-                        },
-                    );
-                    self.write_sub_paths_truncated(&path);
-                }
-            }
-            hir::ItemKind::Use(path, hir::UseKind::Glob) => {
-                // Make a comma-separated list of names of imported modules.
-                let names = self.tcx.names_imported_by_glob_use(item.owner_id.def_id);
-                let names: Vec<_> = names.iter().map(|n| n.to_string()).collect();
-
-                // Otherwise it's a span with wrong macro expansion info, which
-                // we don't want to track anyway, since it's probably macro-internal `use`
-                if let Some(sub_span) = self.span.sub_span_of_star(item.span) {
-                    if !self.span.filter_generated(item.span) {
-                        let access = access_from!(self.save_ctxt, item.owner_id.def_id);
-                        let span = self.span_from_span(sub_span);
-                        let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
-                        self.dumper.import(
-                            &access,
-                            Import {
-                                kind: ImportKind::GlobUse,
-                                ref_id: None,
-                                span,
-                                alias_span: None,
-                                name: "*".to_owned(),
-                                value: names.join(", "),
-                                parent: Some(id_from_def_id(parent.to_def_id())),
-                            },
-                        );
-                        self.write_sub_paths(&path);
-                    }
-                }
-            }
-            hir::ItemKind::ExternCrate(_) => {
-                let name_span = item.ident.span;
-                if !self.span.filter_generated(name_span) {
-                    let span = self.span_from_span(name_span);
-                    let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
-                    self.dumper.import(
-                        &Access { public: false, reachable: false },
-                        Import {
-                            kind: ImportKind::ExternCrate,
-                            ref_id: None,
-                            span,
-                            alias_span: None,
-                            name: item.ident.to_string(),
-                            value: String::new(),
-                            parent: Some(id_from_def_id(parent.to_def_id())),
-                        },
-                    );
-                }
-            }
-            hir::ItemKind::Fn(ref sig, ref ty_params, body) => {
-                self.process_fn(item, sig.decl, &sig.header, ty_params, body)
-            }
-            hir::ItemKind::Static(ref typ, _, body) => {
-                let body = self.tcx.hir().body(body);
-                self.process_static_or_const_item(item, typ, &body.value)
-            }
-            hir::ItemKind::Const(ref typ, body) => {
-                let body = self.tcx.hir().body(body);
-                self.process_static_or_const_item(item, typ, &body.value)
-            }
-            hir::ItemKind::Struct(ref def, ref ty_params)
-            | hir::ItemKind::Union(ref def, ref ty_params) => {
-                self.process_struct(item, def, ty_params)
-            }
-            hir::ItemKind::Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
-            hir::ItemKind::Impl(ref impl_) => self.process_impl(item, impl_),
-            hir::ItemKind::Trait(_, _, ref generics, ref trait_refs, methods) => {
-                self.process_trait(item, generics, trait_refs, methods)
-            }
-            hir::ItemKind::Mod(ref m) => {
-                self.process_mod(item);
-                intravisit::walk_mod(self, m, item.hir_id());
-            }
-            hir::ItemKind::TyAlias(ty, ref generics) => {
-                let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id()));
-                let value = ty_to_string(&ty);
-                if !self.span.filter_generated(item.ident.span) {
-                    let span = self.span_from_span(item.ident.span);
-                    let id = id_from_def_id(item.owner_id.to_def_id());
-                    let attrs = self.tcx.hir().attrs(item.hir_id());
-
-                    self.dumper.dump_def(
-                        &access_from!(self.save_ctxt, item.owner_id.def_id),
-                        Def {
-                            kind: DefKind::Type,
-                            id,
-                            span,
-                            name: item.ident.to_string(),
-                            qualname: qualname.clone(),
-                            value,
-                            parent: None,
-                            children: vec![],
-                            decl_id: None,
-                            docs: self.save_ctxt.docs_for_attrs(attrs),
-                            sig: sig::item_signature(item, &self.save_ctxt),
-                            attributes: lower_attributes(attrs.to_vec(), &self.save_ctxt),
-                        },
-                    );
-                }
-
-                self.visit_ty(ty);
-                self.process_generic_params(generics, &qualname, item.hir_id());
-            }
-            _ => intravisit::walk_item(self, item),
-        }
-    }
-
-    fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
-        for param in generics.params {
-            match param.kind {
-                hir::GenericParamKind::Lifetime { .. } => {}
-                hir::GenericParamKind::Type { ref default, .. } => {
-                    if let Some(ref ty) = default {
-                        self.visit_ty(ty);
-                    }
-                }
-                hir::GenericParamKind::Const { ref ty, ref default } => {
-                    self.visit_ty(ty);
-                    if let Some(default) = default {
-                        self.visit_anon_const(default);
-                    }
-                }
-            }
-        }
-        for pred in generics.predicates {
-            if let hir::WherePredicate::BoundPredicate(ref wbp) = *pred {
-                self.process_bounds(wbp.bounds);
-                self.visit_ty(wbp.bounded_ty);
-            }
-        }
-    }
-
-    fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) {
-        self.process_macro_use(t.span);
-        match t.kind {
-            hir::TyKind::Path(ref path) => {
-                if generated_code(t.span) {
-                    return;
-                }
-
-                if let Some(id) = self.lookup_def_id(t.hir_id) {
-                    let sub_span = path.last_segment_span();
-                    let span = self.span_from_span(sub_span);
-                    self.dumper.dump_ref(Ref {
-                        kind: RefKind::Type,
-                        span,
-                        ref_id: id_from_def_id(id),
-                    });
-                }
-
-                if let hir::QPath::Resolved(_, path) = path {
-                    self.write_sub_paths_truncated(path);
-                }
-                intravisit::walk_qpath(self, path, t.hir_id);
-            }
-            hir::TyKind::Array(ref ty, ref length) => {
-                self.visit_ty(ty);
-                let map = self.tcx.hir();
-                match length {
-                    // FIXME(generic_arg_infer): We probably want to
-                    // output the inferred type here? :shrug:
-                    hir::ArrayLen::Infer(..) => {}
-                    hir::ArrayLen::Body(anon_const) => self
-                        .nest_typeck_results(anon_const.def_id, |v| {
-                            v.visit_expr(&map.body(anon_const.body).value)
-                        }),
-                }
-            }
-            hir::TyKind::OpaqueDef(item_id, _, _) => {
-                let item = self.tcx.hir().item(item_id);
-                self.nest_typeck_results(item_id.owner_id.def_id, |v| v.visit_item(item));
-            }
-            _ => intravisit::walk_ty(self, t),
-        }
-    }
-
-    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
-        debug!("visit_expr {:?}", ex.kind);
-        self.process_macro_use(ex.span);
-        match ex.kind {
-            hir::ExprKind::Struct(ref path, ref fields, ref rest) => {
-                let hir_expr = self.save_ctxt.tcx.hir().expect_expr(ex.hir_id);
-                let adt = match self.save_ctxt.typeck_results().expr_ty_opt(&hir_expr) {
-                    Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(),
-                    _ => {
-                        intravisit::walk_expr(self, ex);
-                        return;
-                    }
-                };
-                let res = self.save_ctxt.get_path_res(hir_expr.hir_id);
-                self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *rest)
-            }
-            hir::ExprKind::MethodCall(ref seg, receiver, args, _) => {
-                self.process_method_call(ex, seg, receiver, args)
-            }
-            hir::ExprKind::Field(ref sub_ex, _) => {
-                self.visit_expr(&sub_ex);
-
-                if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
-                    down_cast_data!(field_data, RefData, ex.span);
-                    if !generated_code(ex.span) {
-                        self.dumper.dump_ref(field_data);
-                    }
-                }
-            }
-            hir::ExprKind::Closure(&hir::Closure { ref fn_decl, body, def_id, .. }) => {
-                let id = format!("${}", ex.hir_id);
-
-                // walk arg and return types
-                for ty in fn_decl.inputs {
-                    self.visit_ty(ty);
-                }
-
-                if let hir::FnRetTy::Return(ref ret_ty) = fn_decl.output {
-                    self.visit_ty(ret_ty);
-                }
-
-                // walk the body
-                let map = self.tcx.hir();
-                self.nest_typeck_results(def_id, |v| {
-                    let body = map.body(body);
-                    v.process_formals(body.params, &id);
-                    v.visit_expr(&body.value)
-                });
-            }
-            hir::ExprKind::Repeat(ref expr, ref length) => {
-                self.visit_expr(expr);
-                let map = self.tcx.hir();
-                match length {
-                    // FIXME(generic_arg_infer): We probably want to
-                    // output the inferred type here? :shrug:
-                    hir::ArrayLen::Infer(..) => {}
-                    hir::ArrayLen::Body(anon_const) => self
-                        .nest_typeck_results(anon_const.def_id, |v| {
-                            v.visit_expr(&map.body(anon_const.body).value)
-                        }),
-                }
-            }
-            // In particular, we take this branch for call and path expressions,
-            // where we'll index the idents involved just by continuing to walk.
-            _ => intravisit::walk_expr(self, ex),
-        }
-    }
-
-    fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
-        self.process_macro_use(p.span);
-        self.process_pat(p);
-    }
-
-    fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
-        self.process_var_decl(&arm.pat);
-        if let Some(hir::Guard::If(expr)) = &arm.guard {
-            self.visit_expr(expr);
-        }
-        self.visit_expr(&arm.body);
-    }
-
-    fn visit_qpath(&mut self, path: &'tcx hir::QPath<'tcx>, id: hir::HirId, _: Span) {
-        self.process_path(id, path);
-    }
-
-    fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) {
-        self.process_macro_use(s.span);
-        intravisit::walk_stmt(self, s)
-    }
-
-    fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
-        self.process_macro_use(l.span);
-        self.process_var_decl(&l.pat);
-
-        // Just walk the initializer, the else branch and type (don't want to walk the pattern again).
-        walk_list!(self, visit_ty, &l.ty);
-        walk_list!(self, visit_expr, &l.init);
-        walk_list!(self, visit_block, l.els);
-    }
-
-    fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
-        let access = access_from!(self.save_ctxt, item.owner_id.def_id);
-
-        match item.kind {
-            hir::ForeignItemKind::Fn(decl, _, ref generics) => {
-                if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) {
-                    down_cast_data!(fn_data, DefData, item.span);
-
-                    self.process_generic_params(generics, &fn_data.qualname, item.hir_id());
-                    self.dumper.dump_def(&access, fn_data);
-                }
-
-                for ty in decl.inputs {
-                    self.visit_ty(ty);
-                }
-
-                if let hir::FnRetTy::Return(ref ret_ty) = decl.output {
-                    self.visit_ty(ret_ty);
-                }
-            }
-            hir::ForeignItemKind::Static(ref ty, _) => {
-                if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
-                    down_cast_data!(var_data, DefData, item.span);
-                    self.dumper.dump_def(&access, var_data);
-                }
-
-                self.visit_ty(ty);
-            }
-            hir::ForeignItemKind::Type => {
-                if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) {
-                    down_cast_data!(var_data, DefData, item.span);
-                    self.dumper.dump_def(&access, var_data);
-                }
-            }
-        }
-    }
-}
diff --git a/compiler/rustc_save_analysis/src/dumper.rs b/compiler/rustc_save_analysis/src/dumper.rs
deleted file mode 100644
index 5a2628287d6..00000000000
--- a/compiler/rustc_save_analysis/src/dumper.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-use rls_data::config::Config;
-use rls_data::{
-    self, Analysis, CompilationOptions, CratePreludeData, Def, DefKind, Impl, Import, MacroRef,
-    Ref, RefKind, Relation,
-};
-use rls_span::{Column, Row};
-
-#[derive(Debug)]
-pub struct Access {
-    pub reachable: bool,
-    pub public: bool,
-}
-
-pub struct Dumper {
-    result: Analysis,
-    config: Config,
-}
-
-impl Dumper {
-    pub fn new(config: Config) -> Dumper {
-        Dumper { config: config.clone(), result: Analysis::new(config) }
-    }
-
-    pub fn analysis(&self) -> &Analysis {
-        &self.result
-    }
-}
-
-impl Dumper {
-    pub fn crate_prelude(&mut self, data: CratePreludeData) {
-        self.result.prelude = Some(data)
-    }
-
-    pub fn compilation_opts(&mut self, data: CompilationOptions) {
-        self.result.compilation = Some(data);
-    }
-
-    pub fn _macro_use(&mut self, data: MacroRef) {
-        if self.config.pub_only || self.config.reachable_only {
-            return;
-        }
-        self.result.macro_refs.push(data);
-    }
-
-    pub fn import(&mut self, access: &Access, import: Import) {
-        if !access.public && self.config.pub_only || !access.reachable && self.config.reachable_only
-        {
-            return;
-        }
-        self.result.imports.push(import);
-    }
-
-    pub fn dump_ref(&mut self, data: Ref) {
-        if self.config.pub_only || self.config.reachable_only {
-            return;
-        }
-        self.result.refs.push(data);
-    }
-
-    pub fn dump_def(&mut self, access: &Access, mut data: Def) {
-        if !access.public && self.config.pub_only || !access.reachable && self.config.reachable_only
-        {
-            return;
-        }
-        if data.kind == DefKind::Mod && data.span.file_name.to_str().unwrap() != data.value {
-            // If the module is an out-of-line definition, then we'll make the
-            // definition the first character in the module's file and turn
-            // the declaration into a reference to it.
-            let rf = Ref { kind: RefKind::Mod, span: data.span, ref_id: data.id };
-            self.result.refs.push(rf);
-            data.span = rls_data::SpanData {
-                file_name: data.value.clone().into(),
-                byte_start: 0,
-                byte_end: 0,
-                line_start: Row::new_one_indexed(1),
-                line_end: Row::new_one_indexed(1),
-                column_start: Column::new_one_indexed(1),
-                column_end: Column::new_one_indexed(1),
-            }
-        }
-        self.result.defs.push(data);
-    }
-
-    pub fn dump_relation(&mut self, data: Relation) {
-        self.result.relations.push(data);
-    }
-
-    pub fn dump_impl(&mut self, data: Impl) {
-        self.result.impls.push(data);
-    }
-}
diff --git a/compiler/rustc_save_analysis/src/errors.rs b/compiler/rustc_save_analysis/src/errors.rs
deleted file mode 100644
index 585aac8c1c3..00000000000
--- a/compiler/rustc_save_analysis/src/errors.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use rustc_macros::Diagnostic;
-
-use std::path::Path;
-
-#[derive(Diagnostic)]
-#[diag(save_analysis_could_not_open)]
-pub(crate) struct CouldNotOpen<'a> {
-    pub file_name: &'a Path,
-    pub err: std::io::Error,
-}
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
deleted file mode 100644
index ad151bc2e1b..00000000000
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ /dev/null
@@ -1,1067 +0,0 @@
-#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![feature(if_let_guard)]
-#![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
-#![feature(never_type)]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
-
-#[macro_use]
-extern crate tracing;
-
-mod dump_visitor;
-mod dumper;
-#[macro_use]
-mod span_utils;
-mod errors;
-mod sig;
-
-use rustc_ast as ast;
-use rustc_ast::util::comments::beautify_doc_string;
-use rustc_ast_pretty::pprust::attribute_to_string;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind as HirDefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::Node;
-use rustc_hir_pretty::{enum_def_to_string, fn_to_string, ty_to_string};
-use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::EffectiveVisibilities;
-use rustc_middle::ty::{self, print::with_no_trimmed_paths, DefIdTree, TyCtxt};
-use rustc_middle::{bug, span_bug};
-use rustc_session::config::{CrateType, Input, OutputType};
-use rustc_session::cstore::ExternCrate;
-use rustc_session::output::{filename_for_metadata, out_filename};
-use rustc_span::symbol::Ident;
-use rustc_span::*;
-
-use std::cell::Cell;
-use std::env;
-use std::fs::File;
-use std::io::BufWriter;
-use std::path::{Path, PathBuf};
-
-use dump_visitor::DumpVisitor;
-use span_utils::SpanUtils;
-
-use rls_data::config::Config;
-use rls_data::{
-    Analysis, Def, DefKind, ExternalCrateData, GlobalCrateId, Impl, ImplKind, MacroRef, Ref,
-    RefKind, Relation, RelationKind, SpanData,
-};
-
-pub struct SaveContext<'tcx> {
-    tcx: TyCtxt<'tcx>,
-    maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
-    effective_visibilities: &'tcx EffectiveVisibilities,
-    span_utils: SpanUtils<'tcx>,
-    config: Config,
-    impl_counter: Cell<u32>,
-}
-
-#[derive(Debug)]
-pub enum Data {
-    RefData(Ref),
-    DefData(Def),
-    RelationData(Relation, Impl),
-}
-
-impl<'tcx> SaveContext<'tcx> {
-    /// Gets the type-checking results for the current body.
-    /// As this will ICE if called outside bodies, only call when working with
-    /// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
-    #[track_caller]
-    fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
-        self.maybe_typeck_results.expect("`SaveContext::typeck_results` called outside of body")
-    }
-
-    fn span_from_span(&self, span: Span) -> SpanData {
-        use rls_span::{Column, Row};
-
-        let sm = self.tcx.sess.source_map();
-        let start = sm.lookup_char_pos(span.lo());
-        let end = sm.lookup_char_pos(span.hi());
-
-        SpanData {
-            file_name: start.file.name.prefer_remapped().to_string().into(),
-            byte_start: span.lo().0,
-            byte_end: span.hi().0,
-            line_start: Row::new_one_indexed(start.line as u32),
-            line_end: Row::new_one_indexed(end.line as u32),
-            column_start: Column::new_one_indexed(start.col.0 as u32 + 1),
-            column_end: Column::new_one_indexed(end.col.0 as u32 + 1),
-        }
-    }
-
-    /// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
-    pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf {
-        let sess = &self.tcx.sess;
-        // Save-analysis is emitted per whole session, not per each crate type
-        let crate_type = sess.crate_types()[0];
-        let outputs = &*self.tcx.output_filenames(());
-
-        if outputs.outputs.contains_key(&OutputType::Metadata) {
-            filename_for_metadata(sess, crate_name, outputs)
-        } else if outputs.outputs.should_codegen() {
-            out_filename(sess, crate_type, outputs, crate_name)
-        } else {
-            // Otherwise it's only a DepInfo, in which case we return early and
-            // not even reach the analysis stage.
-            unreachable!()
-        }
-    }
-
-    /// List external crates used by the current crate.
-    pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
-        let mut result = Vec::with_capacity(self.tcx.crates(()).len());
-
-        for &n in self.tcx.crates(()).iter() {
-            let Some(&ExternCrate { span, .. }) = self.tcx.extern_crate(n.as_def_id()) else {
-                debug!("skipping crate {}, no data", n);
-                continue;
-            };
-            let lo_loc = self.span_utils.sess.source_map().lookup_char_pos(span.lo());
-            result.push(ExternalCrateData {
-                // FIXME: change file_name field to PathBuf in rls-data
-                // https://github.com/nrc/rls-data/issues/7
-                file_name: self.span_utils.make_filename_string(&lo_loc.file),
-                num: n.as_u32(),
-                id: GlobalCrateId {
-                    name: self.tcx.crate_name(n).to_string(),
-                    disambiguator: (
-                        self.tcx.def_path_hash(n.as_def_id()).stable_crate_id().to_u64(),
-                        0,
-                    ),
-                },
-            });
-        }
-
-        result
-    }
-
-    pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option<Data> {
-        let def_id = item.owner_id.to_def_id();
-        let qualname = format!("::{}", self.tcx.def_path_str(def_id));
-        let attrs = self.tcx.hir().attrs(item.hir_id());
-        match item.kind {
-            hir::ForeignItemKind::Fn(ref decl, arg_names, ref generics) => {
-                filter!(self.span_utils, item.ident.span);
-
-                Some(Data::DefData(Def {
-                    kind: DefKind::ForeignFunction,
-                    id: id_from_def_id(def_id),
-                    span: self.span_from_span(item.ident.span),
-                    name: item.ident.to_string(),
-                    qualname,
-                    value: fn_to_string(
-                        decl,
-                        hir::FnHeader {
-                            // functions in extern block are implicitly unsafe
-                            unsafety: hir::Unsafety::Unsafe,
-                            // functions in extern block cannot be const
-                            constness: hir::Constness::NotConst,
-                            abi: self.tcx.hir().get_foreign_abi(item.hir_id()),
-                            // functions in extern block cannot be async
-                            asyncness: hir::IsAsync::NotAsync,
-                        },
-                        Some(item.ident.name),
-                        generics,
-                        arg_names,
-                        None,
-                    ),
-                    parent: None,
-                    children: vec![],
-                    decl_id: None,
-                    docs: self.docs_for_attrs(attrs),
-                    sig: sig::foreign_item_signature(item, self),
-                    attributes: lower_attributes(attrs.to_vec(), self),
-                }))
-            }
-            hir::ForeignItemKind::Static(ref ty, _) => {
-                filter!(self.span_utils, item.ident.span);
-
-                let id = id_from_def_id(def_id);
-                let span = self.span_from_span(item.ident.span);
-
-                Some(Data::DefData(Def {
-                    kind: DefKind::ForeignStatic,
-                    id,
-                    span,
-                    name: item.ident.to_string(),
-                    qualname,
-                    value: ty_to_string(ty),
-                    parent: None,
-                    children: vec![],
-                    decl_id: None,
-                    docs: self.docs_for_attrs(attrs),
-                    sig: sig::foreign_item_signature(item, self),
-                    attributes: lower_attributes(attrs.to_vec(), self),
-                }))
-            }
-            // FIXME(plietar): needs a new DefKind in rls-data
-            hir::ForeignItemKind::Type => None,
-        }
-    }
-
-    pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> {
-        let def_id = item.owner_id.to_def_id();
-        let attrs = self.tcx.hir().attrs(item.hir_id());
-        match item.kind {
-            hir::ItemKind::Fn(ref sig, ref generics, _) => {
-                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
-                filter!(self.span_utils, item.ident.span);
-                Some(Data::DefData(Def {
-                    kind: DefKind::Function,
-                    id: id_from_def_id(def_id),
-                    span: self.span_from_span(item.ident.span),
-                    name: item.ident.to_string(),
-                    qualname,
-                    value: fn_to_string(
-                        sig.decl,
-                        sig.header,
-                        Some(item.ident.name),
-                        generics,
-                        &[],
-                        None,
-                    ),
-                    parent: None,
-                    children: vec![],
-                    decl_id: None,
-                    docs: self.docs_for_attrs(attrs),
-                    sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(attrs.to_vec(), self),
-                }))
-            }
-            hir::ItemKind::Static(ref typ, ..) => {
-                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
-
-                filter!(self.span_utils, item.ident.span);
-
-                let id = id_from_def_id(def_id);
-                let span = self.span_from_span(item.ident.span);
-
-                Some(Data::DefData(Def {
-                    kind: DefKind::Static,
-                    id,
-                    span,
-                    name: item.ident.to_string(),
-                    qualname,
-                    value: ty_to_string(&typ),
-                    parent: None,
-                    children: vec![],
-                    decl_id: None,
-                    docs: self.docs_for_attrs(attrs),
-                    sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(attrs.to_vec(), self),
-                }))
-            }
-            hir::ItemKind::Const(ref typ, _) => {
-                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
-                filter!(self.span_utils, item.ident.span);
-
-                let id = id_from_def_id(def_id);
-                let span = self.span_from_span(item.ident.span);
-
-                Some(Data::DefData(Def {
-                    kind: DefKind::Const,
-                    id,
-                    span,
-                    name: item.ident.to_string(),
-                    qualname,
-                    value: ty_to_string(typ),
-                    parent: None,
-                    children: vec![],
-                    decl_id: None,
-                    docs: self.docs_for_attrs(attrs),
-                    sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(attrs.to_vec(), self),
-                }))
-            }
-            hir::ItemKind::Mod(ref m) => {
-                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
-
-                let sm = self.tcx.sess.source_map();
-                let filename = sm.span_to_filename(m.spans.inner_span);
-
-                filter!(self.span_utils, item.ident.span);
-
-                Some(Data::DefData(Def {
-                    kind: DefKind::Mod,
-                    id: id_from_def_id(def_id),
-                    name: item.ident.to_string(),
-                    qualname,
-                    span: self.span_from_span(item.ident.span),
-                    value: filename.prefer_remapped().to_string(),
-                    parent: None,
-                    children: m
-                        .item_ids
-                        .iter()
-                        .map(|i| id_from_def_id(i.owner_id.to_def_id()))
-                        .collect(),
-                    decl_id: None,
-                    docs: self.docs_for_attrs(attrs),
-                    sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(attrs.to_vec(), self),
-                }))
-            }
-            hir::ItemKind::Enum(ref def, ref generics) => {
-                let name = item.ident.to_string();
-                let qualname = format!("::{}", self.tcx.def_path_str(def_id));
-                filter!(self.span_utils, item.ident.span);
-                let value =
-                    enum_def_to_string(def, generics, item.ident.name, item.span);
-                Some(Data::DefData(Def {
-                    kind: DefKind::Enum,
-                    id: id_from_def_id(def_id),
-                    span: self.span_from_span(item.ident.span),
-                    name,
-                    qualname,
-                    value,
-                    parent: None,
-                    children: def.variants.iter().map(|v| id_from_def_id(v.def_id.to_def_id())).collect(),
-                    decl_id: None,
-                    docs: self.docs_for_attrs(attrs),
-                    sig: sig::item_signature(item, self),
-                    attributes: lower_attributes(attrs.to_vec(), self),
-                }))
-            }
-            hir::ItemKind::Impl(hir::Impl { ref of_trait, ref self_ty, ref items, .. })
-                if let hir::TyKind::Path(hir::QPath::Resolved(_, ref path)) = self_ty.kind =>
-            {
-                // Common case impl for a struct or something basic.
-                if generated_code(path.span) {
-                    return None;
-                }
-                let sub_span = path.segments.last().unwrap().ident.span;
-                filter!(self.span_utils, sub_span);
-
-                let impl_id = self.next_impl_id();
-                let span = self.span_from_span(sub_span);
-
-                let type_data = self.lookup_def_id(self_ty.hir_id);
-                type_data.map(|type_data| {
-                    Data::RelationData(
-                        Relation {
-                            kind: RelationKind::Impl { id: impl_id },
-                            span: span.clone(),
-                            from: id_from_def_id(type_data),
-                            to: of_trait
-                                .as_ref()
-                                .and_then(|t| self.lookup_def_id(t.hir_ref_id))
-                                .map(id_from_def_id)
-                                .unwrap_or_else(null_id),
-                        },
-                        Impl {
-                            id: impl_id,
-                            kind: match *of_trait {
-                                Some(_) => ImplKind::Direct,
-                                None => ImplKind::Inherent,
-                            },
-                            span,
-                            value: String::new(),
-                            parent: None,
-                            children: items
-                                .iter()
-                                .map(|i| id_from_def_id(i.id.owner_id.to_def_id()))
-                                .collect(),
-                            docs: String::new(),
-                            sig: None,
-                            attributes: vec![],
-                        },
-                    )
-                })
-            }
-            hir::ItemKind::Impl(_) => None,
-            _ => {
-                // FIXME
-                bug!();
-            }
-        }
-    }
-
-    pub fn get_field_data(&self, field: &hir::FieldDef<'_>, scope: LocalDefId) -> Option<Def> {
-        let name = field.ident.to_string();
-        let qualname = format!("::{}::{}", self.tcx.def_path_str(scope.to_def_id()), field.ident);
-        filter!(self.span_utils, field.ident.span);
-        let field_def_id = field.def_id.to_def_id();
-        let typ = self.tcx.type_of(field_def_id).to_string();
-
-        let id = id_from_def_id(field_def_id);
-        let span = self.span_from_span(field.ident.span);
-        let attrs = self.tcx.hir().attrs(field.hir_id);
-
-        Some(Def {
-            kind: DefKind::Field,
-            id,
-            span,
-            name,
-            qualname,
-            value: typ,
-            parent: Some(id_from_def_id(scope.to_def_id())),
-            children: vec![],
-            decl_id: None,
-            docs: self.docs_for_attrs(attrs),
-            sig: sig::field_signature(field, self),
-            attributes: lower_attributes(attrs.to_vec(), self),
-        })
-    }
-
-    // FIXME would be nice to take a MethodItem here, but the ast provides both
-    // trait and impl flavours, so the caller must do the disassembly.
-    pub fn get_method_data(&self, owner_id: hir::OwnerId, ident: Ident, span: Span) -> Option<Def> {
-        // The qualname for a method is the trait name or name of the struct in an impl in
-        // which the method is declared in, followed by the method's name.
-        let (qualname, parent_scope, decl_id, docs, attributes) =
-            match self.tcx.impl_of_method(owner_id.to_def_id()) {
-                Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) {
-                    Some(Node::Item(item)) => match item.kind {
-                        hir::ItemKind::Impl(hir::Impl { ref self_ty, .. }) => {
-                            let hir = self.tcx.hir();
-
-                            let mut qualname = String::from("<");
-                            qualname
-                                .push_str(&rustc_hir_pretty::id_to_string(&hir, self_ty.hir_id));
-
-                            let trait_id = self.tcx.trait_id_of_impl(impl_id);
-                            let mut docs = String::new();
-                            let mut attrs = vec![];
-                            if let Some(Node::ImplItem(_)) = hir.find(owner_id.into()) {
-                                attrs = self.tcx.hir().attrs(owner_id.into()).to_vec();
-                                docs = self.docs_for_attrs(&attrs);
-                            }
-
-                            let mut decl_id = None;
-                            if let Some(def_id) = trait_id {
-                                // A method in a trait impl.
-                                qualname.push_str(" as ");
-                                qualname.push_str(&self.tcx.def_path_str(def_id));
-
-                                decl_id = self
-                                    .tcx
-                                    .associated_items(def_id)
-                                    .filter_by_name_unhygienic(ident.name)
-                                    .next()
-                                    .map(|item| item.def_id);
-                            }
-                            qualname.push('>');
-
-                            (qualname, trait_id, decl_id, docs, attrs)
-                        }
-                        _ => {
-                            span_bug!(
-                                span,
-                                "Container {:?} for method {:?} not an impl?",
-                                impl_id,
-                                owner_id,
-                            );
-                        }
-                    },
-                    r => {
-                        span_bug!(
-                            span,
-                            "Container {:?} for method {:?} is not a node item {:?}",
-                            impl_id,
-                            owner_id,
-                            r
-                        );
-                    }
-                },
-                None => match self.tcx.trait_of_item(owner_id.to_def_id()) {
-                    Some(def_id) => {
-                        let mut docs = String::new();
-                        let mut attrs = vec![];
-
-                        if let Some(Node::TraitItem(_)) = self.tcx.hir().find(owner_id.into()) {
-                            attrs = self.tcx.hir().attrs(owner_id.into()).to_vec();
-                            docs = self.docs_for_attrs(&attrs);
-                        }
-
-                        (
-                            format!("::{}", self.tcx.def_path_str(def_id)),
-                            Some(def_id),
-                            None,
-                            docs,
-                            attrs,
-                        )
-                    }
-                    None => {
-                        debug!("could not find container for method {:?} at {:?}", owner_id, span);
-                        // This is not necessarily a bug, if there was a compilation error,
-                        // the typeck results we need might not exist.
-                        return None;
-                    }
-                },
-            };
-
-        let qualname = format!("{}::{}", qualname, ident.name);
-
-        filter!(self.span_utils, ident.span);
-
-        Some(Def {
-            kind: DefKind::Method,
-            id: id_from_def_id(owner_id.to_def_id()),
-            span: self.span_from_span(ident.span),
-            name: ident.name.to_string(),
-            qualname,
-            // FIXME you get better data here by using the visitor.
-            value: String::new(),
-            parent: parent_scope.map(id_from_def_id),
-            children: vec![],
-            decl_id: decl_id.map(id_from_def_id),
-            docs,
-            sig: None,
-            attributes: lower_attributes(attributes, self),
-        })
-    }
-
-    pub fn get_expr_data(&self, expr: &hir::Expr<'_>) -> Option<Data> {
-        let ty = self.typeck_results().expr_ty_adjusted_opt(expr)?;
-        if matches!(ty.kind(), ty::Error(_)) {
-            return None;
-        }
-        match expr.kind {
-            hir::ExprKind::Field(ref sub_ex, ident) => {
-                match self.typeck_results().expr_ty_adjusted(&sub_ex).kind() {
-                    ty::Adt(def, _) if !def.is_enum() => {
-                        let variant = &def.non_enum_variant();
-                        filter!(self.span_utils, ident.span);
-                        let span = self.span_from_span(ident.span);
-                        Some(Data::RefData(Ref {
-                            kind: RefKind::Variable,
-                            span,
-                            ref_id: self
-                                .tcx
-                                .find_field_index(ident, variant)
-                                .map(|index| id_from_def_id(variant.fields[index].did))
-                                .unwrap_or_else(null_id),
-                        }))
-                    }
-                    ty::Tuple(..) => None,
-                    _ => {
-                        debug!("expected struct or union type, found {:?}", ty);
-                        None
-                    }
-                }
-            }
-            hir::ExprKind::Struct(qpath, ..) => match ty.kind() {
-                ty::Adt(def, _) => {
-                    let sub_span = qpath.last_segment_span();
-                    filter!(self.span_utils, sub_span);
-                    let span = self.span_from_span(sub_span);
-                    Some(Data::RefData(Ref {
-                        kind: RefKind::Type,
-                        span,
-                        ref_id: id_from_def_id(def.did()),
-                    }))
-                }
-                _ => {
-                    debug!("expected adt, found {:?}", ty);
-                    None
-                }
-            },
-            hir::ExprKind::MethodCall(ref seg, ..) => {
-                let Some(method_id) = self.typeck_results().type_dependent_def_id(expr.hir_id) else {
-                    debug!("could not resolve method id for {:?}", expr);
-                    return None;
-                };
-                let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
-                    ty::ImplContainer => (Some(method_id), None),
-                    ty::TraitContainer => (None, Some(method_id)),
-                };
-                let sub_span = seg.ident.span;
-                filter!(self.span_utils, sub_span);
-                let span = self.span_from_span(sub_span);
-                Some(Data::RefData(Ref {
-                    kind: RefKind::Function,
-                    span,
-                    ref_id: def_id.or(decl_id).map(id_from_def_id).unwrap_or_else(null_id),
-                }))
-            }
-            hir::ExprKind::Path(ref path) => {
-                self.get_path_data(expr.hir_id, path).map(Data::RefData)
-            }
-            _ => {
-                // FIXME
-                bug!("invalid expression: {:?}", expr);
-            }
-        }
-    }
-
-    pub fn get_path_res(&self, hir_id: hir::HirId) -> Res {
-        match self.tcx.hir().get(hir_id) {
-            Node::TraitRef(tr) => tr.path.res,
-
-            Node::Item(&hir::Item { kind: hir::ItemKind::Use(path, _), .. }) => {
-                path.res.get(0).copied().unwrap_or(Res::Err)
-            }
-            Node::PathSegment(seg) => {
-                if seg.res != Res::Err {
-                    seg.res
-                } else {
-                    let parent_node = self.tcx.hir().parent_id(hir_id);
-                    self.get_path_res(parent_node)
-                }
-            }
-
-            Node::Expr(&hir::Expr { kind: hir::ExprKind::Struct(ref qpath, ..), .. }) => {
-                self.typeck_results().qpath_res(qpath, hir_id)
-            }
-
-            Node::Expr(&hir::Expr { kind: hir::ExprKind::Path(ref qpath), .. })
-            | Node::Pat(&hir::Pat {
-                kind:
-                    hir::PatKind::Path(ref qpath)
-                    | hir::PatKind::Struct(ref qpath, ..)
-                    | hir::PatKind::TupleStruct(ref qpath, ..),
-                ..
-            })
-            | Node::Ty(&hir::Ty { kind: hir::TyKind::Path(ref qpath), .. }) => match qpath {
-                hir::QPath::Resolved(_, path) => path.res,
-                hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => {
-                    // #75962: `self.typeck_results` may be different from the `hir_id`'s result.
-                    if self.tcx.has_typeck_results(hir_id.owner.to_def_id()) {
-                        self.tcx.typeck(hir_id.owner.def_id).qpath_res(qpath, hir_id)
-                    } else {
-                        Res::Err
-                    }
-                }
-            },
-
-            Node::Pat(&hir::Pat { kind: hir::PatKind::Binding(_, canonical_id, ..), .. }) => {
-                Res::Local(canonical_id)
-            }
-
-            _ => Res::Err,
-        }
-    }
-
-    pub fn get_path_data(&self, id: hir::HirId, path: &hir::QPath<'_>) -> Option<Ref> {
-        let segment = match path {
-            hir::QPath::Resolved(_, path) => path.segments.last(),
-            hir::QPath::TypeRelative(_, segment) => Some(*segment),
-            hir::QPath::LangItem(..) => None,
-        };
-        segment.and_then(|seg| {
-            self.get_path_segment_data(seg).or_else(|| self.get_path_segment_data_with_id(seg, id))
-        })
-    }
-
-    pub fn get_path_segment_data(&self, path_seg: &hir::PathSegment<'_>) -> Option<Ref> {
-        self.get_path_segment_data_with_id(path_seg, path_seg.hir_id)
-    }
-
-    pub fn get_path_segment_data_with_id(
-        &self,
-        path_seg: &hir::PathSegment<'_>,
-        id: hir::HirId,
-    ) -> Option<Ref> {
-        // Returns true if the path is function type sugar, e.g., `Fn(A) -> B`.
-        fn fn_type(seg: &hir::PathSegment<'_>) -> bool {
-            seg.args.map_or(false, |args| args.parenthesized)
-        }
-
-        let res = self.get_path_res(id);
-        let span = path_seg.ident.span;
-        filter!(self.span_utils, span);
-        let span = self.span_from_span(span);
-
-        match res {
-            Res::Local(id) => {
-                Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_hir_id(id) })
-            }
-            Res::Def(HirDefKind::Trait, def_id) if fn_type(path_seg) => {
-                Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) })
-            }
-            Res::Def(
-                HirDefKind::Struct
-                | HirDefKind::Variant
-                | HirDefKind::Union
-                | HirDefKind::Enum
-                | HirDefKind::TyAlias
-                | HirDefKind::ForeignTy
-                | HirDefKind::TraitAlias
-                | HirDefKind::AssocTy
-                | HirDefKind::Trait
-                | HirDefKind::OpaqueTy
-                | HirDefKind::ImplTraitPlaceholder
-                | HirDefKind::TyParam,
-                def_id,
-            ) => Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(def_id) }),
-            Res::Def(HirDefKind::ConstParam, def_id) => {
-                Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(def_id) })
-            }
-            Res::Def(HirDefKind::Ctor(..), def_id) => {
-                // This is a reference to a tuple struct or an enum variant where the def_id points
-                // to an invisible constructor function. That is not a very useful
-                // def, so adjust to point to the tuple struct or enum variant itself.
-                let parent_def_id = self.tcx.parent(def_id);
-                Some(Ref { kind: RefKind::Type, span, ref_id: id_from_def_id(parent_def_id) })
-            }
-            Res::Def(HirDefKind::Static(_) | HirDefKind::Const | HirDefKind::AssocConst, _) => {
-                Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(res.def_id()) })
-            }
-            Res::Def(HirDefKind::AssocFn, decl_id) => {
-                let def_id = if decl_id.is_local() {
-                    if self.tcx.impl_defaultness(decl_id).has_value() {
-                        Some(decl_id)
-                    } else {
-                        None
-                    }
-                } else {
-                    None
-                };
-                Some(Ref {
-                    kind: RefKind::Function,
-                    span,
-                    ref_id: id_from_def_id(def_id.unwrap_or(decl_id)),
-                })
-            }
-            Res::Def(HirDefKind::Fn, def_id) => {
-                Some(Ref { kind: RefKind::Function, span, ref_id: id_from_def_id(def_id) })
-            }
-            Res::Def(HirDefKind::Mod, def_id) => {
-                Some(Ref { kind: RefKind::Mod, span, ref_id: id_from_def_id(def_id) })
-            }
-
-            Res::Def(
-                HirDefKind::Macro(..)
-                | HirDefKind::ExternCrate
-                | HirDefKind::ForeignMod
-                | HirDefKind::LifetimeParam
-                | HirDefKind::AnonConst
-                | HirDefKind::InlineConst
-                | HirDefKind::Use
-                | HirDefKind::Field
-                | HirDefKind::GlobalAsm
-                | HirDefKind::Impl { .. }
-                | HirDefKind::Closure
-                | HirDefKind::Generator,
-                _,
-            )
-            | Res::PrimTy(..)
-            | Res::SelfTyParam { .. }
-            | Res::SelfTyAlias { .. }
-            | Res::ToolMod
-            | Res::NonMacroAttr(..)
-            | Res::SelfCtor(..)
-            | Res::Err => None,
-        }
-    }
-
-    pub fn get_field_ref_data(
-        &self,
-        field_ref: &hir::ExprField<'_>,
-        variant: &ty::VariantDef,
-    ) -> Option<Ref> {
-        filter!(self.span_utils, field_ref.ident.span);
-        self.tcx.find_field_index(field_ref.ident, variant).map(|index| {
-            let span = self.span_from_span(field_ref.ident.span);
-            Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(variant.fields[index].did) }
-        })
-    }
-
-    /// Attempt to return MacroRef for any AST node.
-    ///
-    /// For a given piece of AST defined by the supplied Span and NodeId,
-    /// returns `None` if the node is not macro-generated or the span is malformed,
-    /// else uses the expansion callsite and callee to return some MacroRef.
-    ///
-    /// FIXME: [`DumpVisitor::process_macro_use`] should actually dump this data
-    #[allow(dead_code)]
-    fn get_macro_use_data(&self, span: Span) -> Option<MacroRef> {
-        if !generated_code(span) {
-            return None;
-        }
-        // Note we take care to use the source callsite/callee, to handle
-        // nested expansions and ensure we only generate data for source-visible
-        // macro uses.
-        let callsite = span.source_callsite();
-        let callsite_span = self.span_from_span(callsite);
-        let callee = span.source_callee()?;
-
-        let mac_name = match callee.kind {
-            ExpnKind::Macro(kind, name) => match kind {
-                MacroKind::Bang => name,
-
-                // Ignore attribute macros, their spans are usually mangled
-                // FIXME(eddyb) is this really the case anymore?
-                MacroKind::Attr | MacroKind::Derive => return None,
-            },
-
-            // These are not macros.
-            // FIXME(eddyb) maybe there is a way to handle them usefully?
-            ExpnKind::Inlined | ExpnKind::Root | ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => {
-                return None;
-            }
-        };
-
-        let callee_span = self.span_from_span(callee.def_site);
-        Some(MacroRef {
-            span: callsite_span,
-            qualname: mac_name.to_string(), // FIXME: generate the real qualname
-            callee_span,
-        })
-    }
-
-    fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
-        match self.get_path_res(ref_id) {
-            Res::PrimTy(_) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => None,
-            def => def.opt_def_id(),
-        }
-    }
-
-    fn docs_for_attrs(&self, attrs: &[ast::Attribute]) -> String {
-        let mut result = String::new();
-
-        for attr in attrs {
-            if let Some((val, kind)) = attr.doc_str_and_comment_kind() {
-                // FIXME: Should save-analysis beautify doc strings itself or leave it to users?
-                result.push_str(beautify_doc_string(val, kind).as_str());
-                result.push('\n');
-            }
-        }
-
-        if !self.config.full_docs {
-            if let Some(index) = result.find("\n\n") {
-                result.truncate(index);
-            }
-        }
-
-        result
-    }
-
-    fn next_impl_id(&self) -> u32 {
-        let next = self.impl_counter.get();
-        self.impl_counter.set(next + 1);
-        next
-    }
-}
-
-// An AST visitor for collecting paths (e.g., the names of structs) and formal
-// variables (idents) from patterns.
-struct PathCollector<'l> {
-    tcx: TyCtxt<'l>,
-    collected_paths: Vec<(hir::HirId, &'l hir::QPath<'l>)>,
-    collected_idents: Vec<(hir::HirId, Ident, hir::Mutability)>,
-}
-
-impl<'l> PathCollector<'l> {
-    fn new(tcx: TyCtxt<'l>) -> PathCollector<'l> {
-        PathCollector { tcx, collected_paths: vec![], collected_idents: vec![] }
-    }
-}
-
-impl<'l> Visitor<'l> for PathCollector<'l> {
-    type NestedFilter = nested_filter::All;
-
-    fn nested_visit_map(&mut self) -> Self::Map {
-        self.tcx.hir()
-    }
-
-    fn visit_pat(&mut self, p: &'l hir::Pat<'l>) {
-        match p.kind {
-            hir::PatKind::Struct(ref path, ..) => {
-                self.collected_paths.push((p.hir_id, path));
-            }
-            hir::PatKind::TupleStruct(ref path, ..) | hir::PatKind::Path(ref path) => {
-                self.collected_paths.push((p.hir_id, path));
-            }
-            hir::PatKind::Binding(hir::BindingAnnotation(_, mutbl), _, ident, _) => {
-                debug!(
-                    "PathCollector, visit ident in pat {}: {:?} {:?}",
-                    ident, p.span, ident.span
-                );
-                self.collected_idents.push((p.hir_id, ident, mutbl));
-            }
-            _ => {}
-        }
-        intravisit::walk_pat(self, p);
-    }
-}
-
-/// Defines what to do with the results of saving the analysis.
-pub trait SaveHandler {
-    fn save(&mut self, save_ctxt: &SaveContext<'_>, analysis: &Analysis);
-}
-
-/// Dump the save-analysis results to a file.
-pub struct DumpHandler<'a> {
-    odir: Option<&'a Path>,
-    cratename: String,
-}
-
-impl<'a> DumpHandler<'a> {
-    pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> {
-        DumpHandler { odir, cratename: cratename.to_string() }
-    }
-
-    fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) {
-        let sess = &ctx.tcx.sess;
-        let file_name = match ctx.config.output_file {
-            Some(ref s) => PathBuf::from(s),
-            None => {
-                let mut root_path = match self.odir {
-                    Some(val) => val.join("save-analysis"),
-                    None => PathBuf::from("save-analysis-temp"),
-                };
-
-                if let Err(e) = std::fs::create_dir_all(&root_path) {
-                    error!("Could not create directory {}: {}", root_path.display(), e);
-                }
-
-                let executable = sess.crate_types().iter().any(|ct| *ct == CrateType::Executable);
-                let mut out_name = if executable { String::new() } else { "lib".to_owned() };
-                out_name.push_str(&self.cratename);
-                out_name.push_str(&sess.opts.cg.extra_filename);
-                out_name.push_str(".json");
-                root_path.push(&out_name);
-
-                root_path
-            }
-        };
-
-        info!("Writing output to {}", file_name.display());
-
-        let output_file = BufWriter::new(File::create(&file_name).unwrap_or_else(|e| {
-            sess.emit_fatal(errors::CouldNotOpen { file_name: file_name.as_path(), err: e })
-        }));
-
-        (output_file, file_name)
-    }
-}
-
-impl SaveHandler for DumpHandler<'_> {
-    fn save(&mut self, save_ctxt: &SaveContext<'_>, analysis: &Analysis) {
-        let sess = &save_ctxt.tcx.sess;
-        let (output, file_name) = self.output_file(&save_ctxt);
-        if let Err(e) = serde_json::to_writer(output, &analysis) {
-            error!("Can't serialize save-analysis: {:?}", e);
-        }
-
-        if sess.opts.json_artifact_notifications {
-            sess.parse_sess.span_diagnostic.emit_artifact_notification(&file_name, "save-analysis");
-        }
-    }
-}
-
-/// Call a callback with the results of save-analysis.
-pub struct CallbackHandler<'b> {
-    pub callback: &'b mut dyn FnMut(&rls_data::Analysis),
-}
-
-impl SaveHandler for CallbackHandler<'_> {
-    fn save(&mut self, _: &SaveContext<'_>, analysis: &Analysis) {
-        (self.callback)(analysis)
-    }
-}
-
-pub fn process_crate<H: SaveHandler>(
-    tcx: TyCtxt<'_>,
-    cratename: Symbol,
-    input: &Input,
-    config: Option<Config>,
-    mut handler: H,
-) {
-    with_no_trimmed_paths!({
-        tcx.dep_graph.with_ignore(|| {
-            info!("Dumping crate {}", cratename);
-
-            // Privacy checking must be done outside of type inference; use a
-            // fallback in case effective visibilities couldn't have been correctly computed.
-            let effective_visibilities = match tcx.sess.compile_status() {
-                Ok(..) => tcx.effective_visibilities(()),
-                Err(..) => tcx.arena.alloc(EffectiveVisibilities::default()),
-            };
-
-            let save_ctxt = SaveContext {
-                tcx,
-                maybe_typeck_results: None,
-                effective_visibilities: &effective_visibilities,
-                span_utils: SpanUtils::new(&tcx.sess),
-                config: find_config(config),
-                impl_counter: Cell::new(0),
-            };
-
-            let mut visitor = DumpVisitor::new(save_ctxt);
-
-            visitor.dump_crate_info(cratename);
-            visitor.dump_compilation_options(input, cratename);
-            visitor.process_crate();
-
-            handler.save(&visitor.save_ctxt, &visitor.analysis())
-        })
-    })
-}
-
-fn find_config(supplied: Option<Config>) -> Config {
-    if let Some(config) = supplied {
-        return config;
-    }
-
-    match env::var_os("RUST_SAVE_ANALYSIS_CONFIG") {
-        None => Config::default(),
-        Some(config) => config
-            .to_str()
-            .ok_or(())
-            .map_err(|_| error!("`RUST_SAVE_ANALYSIS_CONFIG` isn't UTF-8"))
-            .and_then(|cfg| {
-                serde_json::from_str(cfg)
-                    .map_err(|_| error!("Could not deserialize save-analysis config"))
-            })
-            .unwrap_or_default(),
-    }
-}
-
-// Utility functions for the module.
-
-// Helper function to escape quotes in a string
-fn escape(s: String) -> String {
-    s.replace('\"', "\"\"")
-}
-
-// Helper function to determine if a span came from a
-// macro expansion or syntax extension.
-fn generated_code(span: Span) -> bool {
-    span.from_expansion() || span.is_dummy()
-}
-
-// DefId::index is a newtype and so the JSON serialisation is ugly. Therefore
-// we use our own Id which is the same, but without the newtype.
-fn id_from_def_id(id: DefId) -> rls_data::Id {
-    rls_data::Id { krate: id.krate.as_u32(), index: id.index.as_u32() }
-}
-
-fn id_from_hir_id(id: hir::HirId) -> rls_data::Id {
-    // Create a *fake* `DefId` out of a `HirId` by combining the owner
-    // `local_def_index` and the `local_id`.
-    // This will work unless you have *billions* of definitions in a single
-    // crate (very unlikely to actually happen).
-    rls_data::Id {
-        krate: LOCAL_CRATE.as_u32(),
-        index: id.owner.def_id.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(),
-    }
-}
-
-fn null_id() -> rls_data::Id {
-    rls_data::Id { krate: u32::MAX, index: u32::MAX }
-}
-
-fn lower_attributes(attrs: Vec<ast::Attribute>, scx: &SaveContext<'_>) -> Vec<rls_data::Attribute> {
-    attrs
-        .into_iter()
-        // Only retain real attributes. Doc comments are lowered separately.
-        .filter(|attr| !attr.has_name(sym::doc))
-        .map(|mut attr| {
-            // Remove the surrounding '#[..]' or '#![..]' of the pretty printed
-            // attribute. First normalize all inner attribute (#![..]) to outer
-            // ones (#[..]), then remove the two leading and the one trailing character.
-            attr.style = ast::AttrStyle::Outer;
-            let value = attribute_to_string(&attr);
-            // This str slicing works correctly, because the leading and trailing characters
-            // are in the ASCII range and thus exactly one byte each.
-            let value = value[2..value.len() - 1].to_string();
-
-            rls_data::Attribute { value, span: scx.span_from_span(attr.span) }
-        })
-        .collect()
-}
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
deleted file mode 100644
index a50a8178de3..00000000000
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ /dev/null
@@ -1,931 +0,0 @@
-// A signature is a string representation of an item's type signature, excluding
-// any body. It also includes ids for any defs or refs in the signature. For
-// example:
-//
-// ```
-// fn foo(x: String) {
-//     println!("{}", x);
-// }
-// ```
-// The signature string is something like "fn foo(x: String) {}" and the signature
-// will have defs for `foo` and `x` and a ref for `String`.
-//
-// All signature text should parse in the correct context (i.e., in a module or
-// impl, etc.). Clients may want to trim trailing `{}` or `;`. The text of a
-// signature is not guaranteed to be stable (it may improve or change as the
-// syntax changes, or whitespace or punctuation may change). It is also likely
-// not to be pretty - no attempt is made to prettify the text. It is recommended
-// that clients run the text through Rustfmt.
-//
-// This module generates Signatures for items by walking the AST and looking up
-// references.
-//
-// Signatures do not include visibility info. I'm not sure if this is a feature
-// or an omission (FIXME).
-//
-// FIXME where clauses need implementing, defs/refs in generics are mostly missing.
-
-use crate::{id_from_def_id, SaveContext};
-
-use rls_data::{SigElement, Signature};
-
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir_pretty::id_to_string;
-use rustc_hir_pretty::{bounds_to_string, path_segment_to_string, path_to_string, ty_to_string};
-use rustc_span::def_id::LocalDefId;
-use rustc_span::symbol::{Ident, Symbol};
-
-pub fn item_signature(item: &hir::Item<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
-    if !scx.config.signatures {
-        return None;
-    }
-    item.make(0, None, scx).ok()
-}
-
-pub fn foreign_item_signature(
-    item: &hir::ForeignItem<'_>,
-    scx: &SaveContext<'_>,
-) -> Option<Signature> {
-    if !scx.config.signatures {
-        return None;
-    }
-    item.make(0, None, scx).ok()
-}
-
-/// Signature for a struct or tuple field declaration.
-/// Does not include a trailing comma.
-pub fn field_signature(field: &hir::FieldDef<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
-    if !scx.config.signatures {
-        return None;
-    }
-    field.make(0, None, scx).ok()
-}
-
-/// Does not include a trailing comma.
-pub fn variant_signature(variant: &hir::Variant<'_>, scx: &SaveContext<'_>) -> Option<Signature> {
-    if !scx.config.signatures {
-        return None;
-    }
-    variant.make(0, None, scx).ok()
-}
-
-pub fn method_signature(
-    id: hir::OwnerId,
-    ident: Ident,
-    generics: &hir::Generics<'_>,
-    m: &hir::FnSig<'_>,
-    scx: &SaveContext<'_>,
-) -> Option<Signature> {
-    if !scx.config.signatures {
-        return None;
-    }
-    make_method_signature(id, ident, generics, m, scx).ok()
-}
-
-pub fn assoc_const_signature(
-    id: hir::OwnerId,
-    ident: Symbol,
-    ty: &hir::Ty<'_>,
-    default: Option<&hir::Expr<'_>>,
-    scx: &SaveContext<'_>,
-) -> Option<Signature> {
-    if !scx.config.signatures {
-        return None;
-    }
-    make_assoc_const_signature(id, ident, ty, default, scx).ok()
-}
-
-pub fn assoc_type_signature(
-    id: hir::OwnerId,
-    ident: Ident,
-    bounds: Option<hir::GenericBounds<'_>>,
-    default: Option<&hir::Ty<'_>>,
-    scx: &SaveContext<'_>,
-) -> Option<Signature> {
-    if !scx.config.signatures {
-        return None;
-    }
-    make_assoc_type_signature(id, ident, bounds, default, scx).ok()
-}
-
-type Result = std::result::Result<Signature, &'static str>;
-
-trait Sig {
-    type Parent;
-    fn make(&self, offset: usize, id: Option<Self::Parent>, scx: &SaveContext<'_>) -> Result;
-}
-
-fn extend_sig(
-    mut sig: Signature,
-    text: String,
-    defs: Vec<SigElement>,
-    refs: Vec<SigElement>,
-) -> Signature {
-    sig.text = text;
-    sig.defs.extend(defs.into_iter());
-    sig.refs.extend(refs.into_iter());
-    sig
-}
-
-fn replace_text(mut sig: Signature, text: String) -> Signature {
-    sig.text = text;
-    sig
-}
-
-fn merge_sigs(text: String, sigs: Vec<Signature>) -> Signature {
-    let mut result = Signature { text, defs: vec![], refs: vec![] };
-
-    let (defs, refs): (Vec<_>, Vec<_>) = sigs.into_iter().map(|s| (s.defs, s.refs)).unzip();
-
-    result.defs.extend(defs.into_iter().flat_map(|ds| ds.into_iter()));
-    result.refs.extend(refs.into_iter().flat_map(|rs| rs.into_iter()));
-
-    result
-}
-
-fn text_sig(text: String) -> Signature {
-    Signature { text, defs: vec![], refs: vec![] }
-}
-
-impl<'hir> Sig for hir::Ty<'hir> {
-    type Parent = hir::HirId;
-    fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
-        let id = Some(self.hir_id);
-        match self.kind {
-            hir::TyKind::Slice(ref ty) => {
-                let nested = ty.make(offset + 1, id, scx)?;
-                let text = format!("[{}]", nested.text);
-                Ok(replace_text(nested, text))
-            }
-            hir::TyKind::Ptr(ref mt) => {
-                let prefix = match mt.mutbl {
-                    hir::Mutability::Mut => "*mut ",
-                    hir::Mutability::Not => "*const ",
-                };
-                let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
-                let text = format!("{}{}", prefix, nested.text);
-                Ok(replace_text(nested, text))
-            }
-            hir::TyKind::Ref(ref lifetime, ref mt) => {
-                let mut prefix = "&".to_owned();
-                prefix.push_str(&lifetime.ident.to_string());
-                prefix.push(' ');
-                if mt.mutbl.is_mut() {
-                    prefix.push_str("mut ");
-                };
-
-                let nested = mt.ty.make(offset + prefix.len(), id, scx)?;
-                let text = format!("{}{}", prefix, nested.text);
-                Ok(replace_text(nested, text))
-            }
-            hir::TyKind::Never => Ok(text_sig("!".to_owned())),
-            hir::TyKind::Tup(ts) => {
-                let mut text = "(".to_owned();
-                let mut defs = vec![];
-                let mut refs = vec![];
-                for t in ts {
-                    let nested = t.make(offset + text.len(), id, scx)?;
-                    text.push_str(&nested.text);
-                    text.push(',');
-                    defs.extend(nested.defs.into_iter());
-                    refs.extend(nested.refs.into_iter());
-                }
-                text.push(')');
-                Ok(Signature { text, defs, refs })
-            }
-            hir::TyKind::BareFn(ref f) => {
-                let mut text = String::new();
-                if !f.generic_params.is_empty() {
-                    // FIXME defs, bounds on lifetimes
-                    text.push_str("for<");
-                    text.push_str(
-                        &f.generic_params
-                            .iter()
-                            .filter_map(|param| match param.kind {
-                                hir::GenericParamKind::Lifetime { .. } => {
-                                    Some(param.name.ident().to_string())
-                                }
-                                _ => None,
-                            })
-                            .collect::<Vec<_>>()
-                            .join(", "),
-                    );
-                    text.push('>');
-                }
-
-                if let hir::Unsafety::Unsafe = f.unsafety {
-                    text.push_str("unsafe ");
-                }
-                text.push_str("fn(");
-
-                let mut defs = vec![];
-                let mut refs = vec![];
-                for i in f.decl.inputs {
-                    let nested = i.make(offset + text.len(), Some(i.hir_id), scx)?;
-                    text.push_str(&nested.text);
-                    text.push(',');
-                    defs.extend(nested.defs.into_iter());
-                    refs.extend(nested.refs.into_iter());
-                }
-                text.push(')');
-                if let hir::FnRetTy::Return(ref t) = f.decl.output {
-                    text.push_str(" -> ");
-                    let nested = t.make(offset + text.len(), None, scx)?;
-                    text.push_str(&nested.text);
-                    text.push(',');
-                    defs.extend(nested.defs.into_iter());
-                    refs.extend(nested.refs.into_iter());
-                }
-
-                Ok(Signature { text, defs, refs })
-            }
-            hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => path.make(offset, id, scx),
-            hir::TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref path)) => {
-                let nested_ty = qself.make(offset + 1, id, scx)?;
-                let prefix = format!(
-                    "<{} as {}>::",
-                    nested_ty.text,
-                    path_segment_to_string(&path.segments[0])
-                );
-
-                let name = path_segment_to_string(path.segments.last().ok_or("Bad path")?);
-                let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
-                let id = id_from_def_id(res.def_id());
-                if path.segments.len() == 2 {
-                    let start = offset + prefix.len();
-                    let end = start + name.len();
-
-                    Ok(Signature {
-                        text: prefix + &name,
-                        defs: vec![],
-                        refs: vec![SigElement { id, start, end }],
-                    })
-                } else {
-                    let start = offset + prefix.len() + 5;
-                    let end = start + name.len();
-                    // FIXME should put the proper path in there, not ellipsis.
-                    Ok(Signature {
-                        text: prefix + "...::" + &name,
-                        defs: vec![],
-                        refs: vec![SigElement { id, start, end }],
-                    })
-                }
-            }
-            hir::TyKind::Path(hir::QPath::TypeRelative(ty, segment)) => {
-                let nested_ty = ty.make(offset + 1, id, scx)?;
-                let prefix = format!("<{}>::", nested_ty.text);
-
-                let name = path_segment_to_string(segment);
-                let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
-                let id = id_from_def_id(res.def_id());
-
-                let start = offset + prefix.len();
-                let end = start + name.len();
-                Ok(Signature {
-                    text: prefix + &name,
-                    defs: vec![],
-                    refs: vec![SigElement { id, start, end }],
-                })
-            }
-            hir::TyKind::Path(hir::QPath::LangItem(lang_item, _, _)) => {
-                Ok(text_sig(format!("#[lang = \"{}\"]", lang_item.name())))
-            }
-            hir::TyKind::TraitObject(bounds, ..) => {
-                // FIXME recurse into bounds
-                let bounds: Vec<hir::GenericBound<'_>> = bounds
-                    .iter()
-                    .map(|hir::PolyTraitRef { bound_generic_params, trait_ref, span }| {
-                        hir::GenericBound::Trait(
-                            hir::PolyTraitRef {
-                                bound_generic_params,
-                                trait_ref: hir::TraitRef {
-                                    path: trait_ref.path,
-                                    hir_ref_id: trait_ref.hir_ref_id,
-                                },
-                                span: *span,
-                            },
-                            hir::TraitBoundModifier::None,
-                        )
-                    })
-                    .collect();
-                let nested = bounds_to_string(&bounds);
-                Ok(text_sig(nested))
-            }
-            hir::TyKind::Array(ref ty, ref length) => {
-                let nested_ty = ty.make(offset + 1, id, scx)?;
-                let expr = id_to_string(&scx.tcx.hir(), length.hir_id()).replace('\n', " ");
-                let text = format!("[{}; {}]", nested_ty.text, expr);
-                Ok(replace_text(nested_ty, text))
-            }
-            hir::TyKind::OpaqueDef(item_id, _, _) => {
-                let item = scx.tcx.hir().item(item_id);
-                item.make(offset, Some(item_id.hir_id()), scx)
-            }
-            hir::TyKind::Typeof(_) | hir::TyKind::Infer | hir::TyKind::Err => Err("Ty"),
-        }
-    }
-}
-
-impl<'hir> Sig for hir::Item<'hir> {
-    type Parent = hir::HirId;
-    fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
-        let id = Some(self.hir_id());
-
-        match self.kind {
-            hir::ItemKind::Static(ref ty, m, ref body) => {
-                let mut text = "static ".to_owned();
-                if m.is_mut() {
-                    text.push_str("mut ");
-                }
-                let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_def_id(self.owner_id.to_def_id()),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
-                text.push_str(&name);
-                text.push_str(": ");
-
-                let ty = ty.make(offset + text.len(), id, scx)?;
-                text.push_str(&ty.text);
-
-                text.push_str(" = ");
-                let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
-                text.push_str(&expr);
-
-                text.push(';');
-
-                Ok(extend_sig(ty, text, defs, vec![]))
-            }
-            hir::ItemKind::Const(ref ty, ref body) => {
-                let mut text = "const ".to_owned();
-                let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_def_id(self.owner_id.to_def_id()),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
-                text.push_str(&name);
-                text.push_str(": ");
-
-                let ty = ty.make(offset + text.len(), id, scx)?;
-                text.push_str(&ty.text);
-
-                text.push_str(" = ");
-                let expr = id_to_string(&scx.tcx.hir(), body.hir_id).replace('\n', " ");
-                text.push_str(&expr);
-
-                text.push(';');
-
-                Ok(extend_sig(ty, text, defs, vec![]))
-            }
-            hir::ItemKind::Fn(hir::FnSig { ref decl, header, span: _ }, ref generics, _) => {
-                let mut text = String::new();
-                if let hir::Constness::Const = header.constness {
-                    text.push_str("const ");
-                }
-                if hir::IsAsync::Async == header.asyncness {
-                    text.push_str("async ");
-                }
-                if let hir::Unsafety::Unsafe = header.unsafety {
-                    text.push_str("unsafe ");
-                }
-                text.push_str("fn ");
-
-                let mut sig =
-                    name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
-
-                sig.text.push('(');
-                for i in decl.inputs {
-                    // FIXME should descend into patterns to add defs.
-                    sig.text.push_str(": ");
-                    let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
-                    sig.text.push_str(&nested.text);
-                    sig.text.push(',');
-                    sig.defs.extend(nested.defs.into_iter());
-                    sig.refs.extend(nested.refs.into_iter());
-                }
-                sig.text.push(')');
-
-                if let hir::FnRetTy::Return(ref t) = decl.output {
-                    sig.text.push_str(" -> ");
-                    let nested = t.make(offset + sig.text.len(), None, scx)?;
-                    sig.text.push_str(&nested.text);
-                    sig.defs.extend(nested.defs.into_iter());
-                    sig.refs.extend(nested.refs.into_iter());
-                }
-                sig.text.push_str(" {}");
-
-                Ok(sig)
-            }
-            hir::ItemKind::Macro(..) => {
-                let mut text = "macro".to_owned();
-                let name = self.ident.to_string();
-                text.push_str(&name);
-                text.push_str(&"! {}");
-
-                Ok(text_sig(text))
-            }
-            hir::ItemKind::Mod(ref _mod) => {
-                let mut text = "mod ".to_owned();
-                let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_def_id(self.owner_id.to_def_id()),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
-                text.push_str(&name);
-                // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
-                text.push(';');
-
-                Ok(Signature { text, defs, refs: vec![] })
-            }
-            hir::ItemKind::TyAlias(ref ty, ref generics) => {
-                let text = "type ".to_owned();
-                let mut sig =
-                    name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
-
-                sig.text.push_str(" = ");
-                let ty = ty.make(offset + sig.text.len(), id, scx)?;
-                sig.text.push_str(&ty.text);
-                sig.text.push(';');
-
-                Ok(merge_sigs(sig.text.clone(), vec![sig, ty]))
-            }
-            hir::ItemKind::Enum(_, ref generics) => {
-                let text = "enum ".to_owned();
-                let mut sig =
-                    name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
-                sig.text.push_str(" {}");
-                Ok(sig)
-            }
-            hir::ItemKind::Struct(_, ref generics) => {
-                let text = "struct ".to_owned();
-                let mut sig =
-                    name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
-                sig.text.push_str(" {}");
-                Ok(sig)
-            }
-            hir::ItemKind::Union(_, ref generics) => {
-                let text = "union ".to_owned();
-                let mut sig =
-                    name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
-                sig.text.push_str(" {}");
-                Ok(sig)
-            }
-            hir::ItemKind::Trait(is_auto, unsafety, ref generics, bounds, _) => {
-                let mut text = String::new();
-
-                if is_auto == hir::IsAuto::Yes {
-                    text.push_str("auto ");
-                }
-
-                if let hir::Unsafety::Unsafe = unsafety {
-                    text.push_str("unsafe ");
-                }
-                text.push_str("trait ");
-                let mut sig =
-                    name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
-
-                if !bounds.is_empty() {
-                    sig.text.push_str(": ");
-                    sig.text.push_str(&bounds_to_string(bounds));
-                }
-                // FIXME where clause
-                sig.text.push_str(" {}");
-
-                Ok(sig)
-            }
-            hir::ItemKind::TraitAlias(ref generics, bounds) => {
-                let mut text = String::new();
-                text.push_str("trait ");
-                let mut sig =
-                    name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
-
-                if !bounds.is_empty() {
-                    sig.text.push_str(" = ");
-                    sig.text.push_str(&bounds_to_string(bounds));
-                }
-                // FIXME where clause
-                sig.text.push(';');
-
-                Ok(sig)
-            }
-            hir::ItemKind::Impl(hir::Impl {
-                unsafety,
-                polarity,
-                defaultness,
-                defaultness_span: _,
-                constness,
-                ref generics,
-                ref of_trait,
-                ref self_ty,
-                items: _,
-            }) => {
-                let mut text = String::new();
-                if let hir::Defaultness::Default { .. } = defaultness {
-                    text.push_str("default ");
-                }
-                if let hir::Unsafety::Unsafe = unsafety {
-                    text.push_str("unsafe ");
-                }
-                text.push_str("impl");
-                if let hir::Constness::Const = constness {
-                    text.push_str(" const");
-                }
-
-                let generics_sig =
-                    generics.make(offset + text.len(), Some(self.owner_id.def_id), scx)?;
-                text.push_str(&generics_sig.text);
-
-                text.push(' ');
-
-                let trait_sig = if let Some(ref t) = *of_trait {
-                    if let hir::ImplPolarity::Negative(_) = polarity {
-                        text.push('!');
-                    }
-                    let trait_sig = t.path.make(offset + text.len(), id, scx)?;
-                    text.push_str(&trait_sig.text);
-                    text.push_str(" for ");
-                    trait_sig
-                } else {
-                    text_sig(String::new())
-                };
-
-                let ty_sig = self_ty.make(offset + text.len(), id, scx)?;
-                text.push_str(&ty_sig.text);
-
-                text.push_str(" {}");
-
-                Ok(merge_sigs(text, vec![generics_sig, trait_sig, ty_sig]))
-
-                // FIXME where clause
-            }
-            hir::ItemKind::ForeignMod { .. } => Err("extern mod"),
-            hir::ItemKind::GlobalAsm(_) => Err("global asm"),
-            hir::ItemKind::ExternCrate(_) => Err("extern crate"),
-            hir::ItemKind::OpaqueTy(ref opaque) => {
-                if opaque.in_trait {
-                    Err("opaque type in trait")
-                } else {
-                    Err("opaque type")
-                }
-            }
-            // FIXME should implement this (e.g., pub use).
-            hir::ItemKind::Use(..) => Err("import"),
-        }
-    }
-}
-
-impl<'hir> Sig for hir::Path<'hir> {
-    type Parent = hir::HirId;
-    fn make(&self, offset: usize, id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
-        let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
-
-        let (name, start, end) = match res {
-            Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => {
-                return Ok(Signature { text: path_to_string(self), defs: vec![], refs: vec![] });
-            }
-            Res::Def(DefKind::AssocConst | DefKind::Variant | DefKind::Ctor(..), _) => {
-                let len = self.segments.len();
-                if len < 2 {
-                    return Err("Bad path");
-                }
-                // FIXME: really we should descend into the generics here and add SigElements for
-                // them.
-                // FIXME: would be nice to have a def for the first path segment.
-                let seg1 = path_segment_to_string(&self.segments[len - 2]);
-                let seg2 = path_segment_to_string(&self.segments[len - 1]);
-                let start = offset + seg1.len() + 2;
-                (format!("{}::{}", seg1, seg2), start, start + seg2.len())
-            }
-            _ => {
-                let name = path_segment_to_string(self.segments.last().ok_or("Bad path")?);
-                let end = offset + name.len();
-                (name, offset, end)
-            }
-        };
-
-        let id = id_from_def_id(res.def_id());
-        Ok(Signature { text: name, defs: vec![], refs: vec![SigElement { id, start, end }] })
-    }
-}
-
-// This does not cover the where clause, which must be processed separately.
-impl<'hir> Sig for hir::Generics<'hir> {
-    type Parent = LocalDefId;
-    fn make(&self, offset: usize, _parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
-        if self.params.is_empty() {
-            return Ok(text_sig(String::new()));
-        }
-
-        let mut text = "<".to_owned();
-
-        let mut defs = Vec::with_capacity(self.params.len());
-        for param in self.params {
-            let mut param_text = String::new();
-            if let hir::GenericParamKind::Const { .. } = param.kind {
-                param_text.push_str("const ");
-            }
-            param_text.push_str(param.name.ident().as_str());
-            defs.push(SigElement {
-                id: id_from_def_id(param.def_id.to_def_id()),
-                start: offset + text.len(),
-                end: offset + text.len() + param_text.as_str().len(),
-            });
-            if let hir::GenericParamKind::Const { ref ty, default } = param.kind {
-                param_text.push_str(": ");
-                param_text.push_str(&ty_to_string(&ty));
-                if let Some(default) = default {
-                    param_text.push_str(" = ");
-                    param_text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
-                }
-            }
-            text.push_str(&param_text);
-            text.push(',');
-        }
-
-        text.push('>');
-        Ok(Signature { text, defs, refs: vec![] })
-    }
-}
-
-impl<'hir> Sig for hir::FieldDef<'hir> {
-    type Parent = LocalDefId;
-    fn make(&self, offset: usize, _parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
-        let mut text = String::new();
-
-        text.push_str(&self.ident.to_string());
-        let defs = Some(SigElement {
-            id: id_from_def_id(self.def_id.to_def_id()),
-            start: offset,
-            end: offset + text.len(),
-        });
-        text.push_str(": ");
-
-        let mut ty_sig = self.ty.make(offset + text.len(), Some(self.hir_id), scx)?;
-        text.push_str(&ty_sig.text);
-        ty_sig.text = text;
-        ty_sig.defs.extend(defs.into_iter());
-        Ok(ty_sig)
-    }
-}
-
-impl<'hir> Sig for hir::Variant<'hir> {
-    type Parent = LocalDefId;
-    fn make(&self, offset: usize, parent_id: Option<LocalDefId>, scx: &SaveContext<'_>) -> Result {
-        let mut text = self.ident.to_string();
-        match self.data {
-            hir::VariantData::Struct(fields, r) => {
-                let id = parent_id.ok_or("Missing id for Variant's parent")?;
-                let name_def = SigElement {
-                    id: id_from_def_id(id.to_def_id()),
-                    start: offset,
-                    end: offset + text.len(),
-                };
-                text.push_str(" { ");
-                let mut defs = vec![name_def];
-                let mut refs = vec![];
-                if r {
-                    text.push_str("/* parse error */ ");
-                } else {
-                    for f in fields {
-                        let field_sig = f.make(offset + text.len(), Some(id), scx)?;
-                        text.push_str(&field_sig.text);
-                        text.push_str(", ");
-                        defs.extend(field_sig.defs.into_iter());
-                        refs.extend(field_sig.refs.into_iter());
-                    }
-                }
-                text.push('}');
-                Ok(Signature { text, defs, refs })
-            }
-            hir::VariantData::Tuple(fields, _, def_id) => {
-                let name_def = SigElement {
-                    id: id_from_def_id(def_id.to_def_id()),
-                    start: offset,
-                    end: offset + text.len(),
-                };
-                text.push('(');
-                let mut defs = vec![name_def];
-                let mut refs = vec![];
-                for f in fields {
-                    let field_sig = f.make(offset + text.len(), Some(def_id), scx)?;
-                    text.push_str(&field_sig.text);
-                    text.push_str(", ");
-                    defs.extend(field_sig.defs.into_iter());
-                    refs.extend(field_sig.refs.into_iter());
-                }
-                text.push(')');
-                Ok(Signature { text, defs, refs })
-            }
-            hir::VariantData::Unit(_, def_id) => {
-                let name_def = SigElement {
-                    id: id_from_def_id(def_id.to_def_id()),
-                    start: offset,
-                    end: offset + text.len(),
-                };
-                Ok(Signature { text, defs: vec![name_def], refs: vec![] })
-            }
-        }
-    }
-}
-
-impl<'hir> Sig for hir::ForeignItem<'hir> {
-    type Parent = hir::HirId;
-    fn make(&self, offset: usize, _parent_id: Option<hir::HirId>, scx: &SaveContext<'_>) -> Result {
-        let id = Some(self.hir_id());
-        match self.kind {
-            hir::ForeignItemKind::Fn(decl, _, ref generics) => {
-                let mut text = String::new();
-                text.push_str("fn ");
-
-                let mut sig =
-                    name_and_generics(text, offset, generics, self.owner_id, self.ident, scx)?;
-
-                sig.text.push('(');
-                for i in decl.inputs {
-                    sig.text.push_str(": ");
-                    let nested = i.make(offset + sig.text.len(), Some(i.hir_id), scx)?;
-                    sig.text.push_str(&nested.text);
-                    sig.text.push(',');
-                    sig.defs.extend(nested.defs.into_iter());
-                    sig.refs.extend(nested.refs.into_iter());
-                }
-                sig.text.push(')');
-
-                if let hir::FnRetTy::Return(ref t) = decl.output {
-                    sig.text.push_str(" -> ");
-                    let nested = t.make(offset + sig.text.len(), None, scx)?;
-                    sig.text.push_str(&nested.text);
-                    sig.defs.extend(nested.defs.into_iter());
-                    sig.refs.extend(nested.refs.into_iter());
-                }
-                sig.text.push(';');
-
-                Ok(sig)
-            }
-            hir::ForeignItemKind::Static(ref ty, m) => {
-                let mut text = "static ".to_owned();
-                text.push_str(m.prefix_str());
-
-                let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_def_id(self.owner_id.to_def_id()),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
-                text.push_str(&name);
-                text.push_str(": ");
-
-                let ty_sig = ty.make(offset + text.len(), id, scx)?;
-                text.push(';');
-
-                Ok(extend_sig(ty_sig, text, defs, vec![]))
-            }
-            hir::ForeignItemKind::Type => {
-                let mut text = "type ".to_owned();
-                let name = self.ident.to_string();
-                let defs = vec![SigElement {
-                    id: id_from_def_id(self.owner_id.to_def_id()),
-                    start: offset + text.len(),
-                    end: offset + text.len() + name.len(),
-                }];
-                text.push_str(&name);
-                text.push(';');
-
-                Ok(Signature { text, defs, refs: vec![] })
-            }
-        }
-    }
-}
-
-fn name_and_generics(
-    mut text: String,
-    offset: usize,
-    generics: &hir::Generics<'_>,
-    id: hir::OwnerId,
-    name: Ident,
-    scx: &SaveContext<'_>,
-) -> Result {
-    let name = name.to_string();
-    let def = SigElement {
-        id: id_from_def_id(id.to_def_id()),
-        start: offset + text.len(),
-        end: offset + text.len() + name.len(),
-    };
-    text.push_str(&name);
-    let generics: Signature = generics.make(offset + text.len(), Some(id.def_id), scx)?;
-    // FIXME where clause
-    let text = format!("{}{}", text, generics.text);
-    Ok(extend_sig(generics, text, vec![def], vec![]))
-}
-
-fn make_assoc_type_signature(
-    id: hir::OwnerId,
-    ident: Ident,
-    bounds: Option<hir::GenericBounds<'_>>,
-    default: Option<&hir::Ty<'_>>,
-    scx: &SaveContext<'_>,
-) -> Result {
-    let mut text = "type ".to_owned();
-    let name = ident.to_string();
-    let mut defs = vec![SigElement {
-        id: id_from_def_id(id.to_def_id()),
-        start: text.len(),
-        end: text.len() + name.len(),
-    }];
-    let mut refs = vec![];
-    text.push_str(&name);
-    if let Some(bounds) = bounds {
-        text.push_str(": ");
-        // FIXME should descend into bounds
-        text.push_str(&bounds_to_string(bounds));
-    }
-    if let Some(default) = default {
-        text.push_str(" = ");
-        let ty_sig = default.make(text.len(), Some(id.into()), scx)?;
-        text.push_str(&ty_sig.text);
-        defs.extend(ty_sig.defs.into_iter());
-        refs.extend(ty_sig.refs.into_iter());
-    }
-    text.push(';');
-    Ok(Signature { text, defs, refs })
-}
-
-fn make_assoc_const_signature(
-    id: hir::OwnerId,
-    ident: Symbol,
-    ty: &hir::Ty<'_>,
-    default: Option<&hir::Expr<'_>>,
-    scx: &SaveContext<'_>,
-) -> Result {
-    let mut text = "const ".to_owned();
-    let name = ident.to_string();
-    let mut defs = vec![SigElement {
-        id: id_from_def_id(id.to_def_id()),
-        start: text.len(),
-        end: text.len() + name.len(),
-    }];
-    let mut refs = vec![];
-    text.push_str(&name);
-    text.push_str(": ");
-
-    let ty_sig = ty.make(text.len(), Some(id.into()), scx)?;
-    text.push_str(&ty_sig.text);
-    defs.extend(ty_sig.defs.into_iter());
-    refs.extend(ty_sig.refs.into_iter());
-
-    if let Some(default) = default {
-        text.push_str(" = ");
-        text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id));
-    }
-    text.push(';');
-    Ok(Signature { text, defs, refs })
-}
-
-fn make_method_signature(
-    id: hir::OwnerId,
-    ident: Ident,
-    generics: &hir::Generics<'_>,
-    m: &hir::FnSig<'_>,
-    scx: &SaveContext<'_>,
-) -> Result {
-    // FIXME code dup with function signature
-    let mut text = String::new();
-    if let hir::Constness::Const = m.header.constness {
-        text.push_str("const ");
-    }
-    if hir::IsAsync::Async == m.header.asyncness {
-        text.push_str("async ");
-    }
-    if let hir::Unsafety::Unsafe = m.header.unsafety {
-        text.push_str("unsafe ");
-    }
-    text.push_str("fn ");
-
-    let mut sig = name_and_generics(text, 0, generics, id, ident, scx)?;
-
-    sig.text.push('(');
-    for i in m.decl.inputs {
-        sig.text.push_str(": ");
-        let nested = i.make(sig.text.len(), Some(i.hir_id), scx)?;
-        sig.text.push_str(&nested.text);
-        sig.text.push(',');
-        sig.defs.extend(nested.defs.into_iter());
-        sig.refs.extend(nested.refs.into_iter());
-    }
-    sig.text.push(')');
-
-    if let hir::FnRetTy::Return(ref t) = m.decl.output {
-        sig.text.push_str(" -> ");
-        let nested = t.make(sig.text.len(), None, scx)?;
-        sig.text.push_str(&nested.text);
-        sig.defs.extend(nested.defs.into_iter());
-        sig.refs.extend(nested.refs.into_iter());
-    }
-    sig.text.push_str(" {}");
-
-    Ok(sig)
-}
diff --git a/compiler/rustc_save_analysis/src/span_utils.rs b/compiler/rustc_save_analysis/src/span_utils.rs
deleted file mode 100644
index e65d57bb3db..00000000000
--- a/compiler/rustc_save_analysis/src/span_utils.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-use crate::generated_code;
-use rustc_data_structures::sync::Lrc;
-use rustc_lexer::{tokenize, TokenKind};
-use rustc_session::Session;
-use rustc_span::*;
-
-#[derive(Clone)]
-pub struct SpanUtils<'a> {
-    pub sess: &'a Session,
-}
-
-impl<'a> SpanUtils<'a> {
-    pub fn new(sess: &'a Session) -> SpanUtils<'a> {
-        SpanUtils { sess }
-    }
-
-    pub fn make_filename_string(&self, file: &SourceFile) -> String {
-        match &file.name {
-            FileName::Real(RealFileName::LocalPath(path)) => {
-                if path.is_absolute() {
-                    self.sess.source_map().path_mapping().map_prefix(path).0.display().to_string()
-                } else {
-                    self.sess
-                        .opts
-                        .working_dir
-                        .remapped_path_if_available()
-                        .join(&path)
-                        .display()
-                        .to_string()
-                }
-            }
-            filename => filename.prefer_remapped().to_string(),
-        }
-    }
-
-    pub fn snippet(&self, span: Span) -> String {
-        match self.sess.source_map().span_to_snippet(span) {
-            Ok(s) => s,
-            Err(_) => String::new(),
-        }
-    }
-
-    /// Finds the span of `*` token withing the larger `span`.
-    pub fn sub_span_of_star(&self, mut span: Span) -> Option<Span> {
-        let begin = self.sess.source_map().lookup_byte_offset(span.lo());
-        let end = self.sess.source_map().lookup_byte_offset(span.hi());
-        // Make the range zero-length if the span is invalid.
-        if begin.sf.start_pos != end.sf.start_pos {
-            span = span.shrink_to_lo();
-        }
-
-        let sf = Lrc::clone(&begin.sf);
-
-        self.sess.source_map().ensure_source_file_source_present(Lrc::clone(&sf));
-        let src =
-            sf.src.clone().or_else(|| sf.external_src.borrow().get_source().map(Lrc::clone))?;
-        let to_index = |pos: BytePos| -> usize { (pos - sf.start_pos).0 as usize };
-        let text = &src[to_index(span.lo())..to_index(span.hi())];
-        let start_pos = {
-            let mut pos = 0;
-            tokenize(text)
-                .map(|token| {
-                    let start = pos;
-                    pos += token.len;
-                    (start, token)
-                })
-                .find(|(_pos, token)| token.kind == TokenKind::Star)?
-                .0
-        };
-        let lo = span.lo() + BytePos(start_pos as u32);
-        let hi = lo + BytePos(1);
-        Some(span.with_lo(lo).with_hi(hi))
-    }
-
-    /// Return true if the span is generated code, and
-    /// it is not a subspan of the root callsite.
-    ///
-    /// Used to filter out spans of minimal value,
-    /// such as references to macro internal variables.
-    pub fn filter_generated(&self, span: Span) -> bool {
-        if generated_code(span) {
-            return true;
-        }
-
-        //If the span comes from a fake source_file, filter it.
-        !self.sess.source_map().lookup_char_pos(span.lo()).file.is_real_file()
-    }
-}
-
-macro_rules! filter {
-    ($util: expr, $parent: expr) => {
-        if $util.filter_generated($parent) {
-            return None;
-        }
-    };
-}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 81f7f6d72ae..d9e68320f8f 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1629,9 +1629,6 @@ options! {
     saturating_float_casts: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "make float->int casts UB-free: numbers outside the integer type's range are clipped to \
         the max/min integer respectively, and NaN is mapped to 0 (default: yes)"),
-    save_analysis: bool = (false, parse_bool, [UNTRACKED],
-        "write syntax and type analysis (in JSON format) information, in \
-        addition to normal output (default: no)"),
     self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
         parse_switch_with_opt_path, [UNTRACKED],
         "run the self profiler and output the raw event data"),
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index b4fc1d4f28d..952c70cec1c 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -780,7 +780,6 @@ impl<'a> Builder<'a> {
                 install::Clippy,
                 install::Miri,
                 install::LlvmTools,
-                install::Analysis,
                 install::Src,
                 install::Rustc
             ),
@@ -1802,16 +1801,6 @@ impl<'a> Builder<'a> {
             }
         }
 
-        if mode == Mode::Std && self.config.extended && compiler.is_final_stage(self) {
-            rustflags.arg("-Zsave-analysis");
-            cargo.env(
-                "RUST_SAVE_ANALYSIS_CONFIG",
-                "{\"output_file\": null,\"full_docs\": false,\
-                       \"pub_only\": true,\"reachable_only\": false,\
-                       \"distro_crate\": true,\"signatures\": false,\"borrow_data\": false}",
-            );
-        }
-
         // If Control Flow Guard is enabled, pass the `control-flow-guard` flag to rustc
         // when compiling the standard library, since this might be linked into the final outputs
         // produced by rustc. Since this mitigation is only available on Windows, only enable it
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 02e35d2436e..9b2b549612d 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -12,6 +12,7 @@ use std::collections::HashSet;
 use std::env;
 use std::ffi::OsStr;
 use std::fs;
+use std::io::Write;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 
@@ -753,7 +754,7 @@ impl Step for Analysis {
         });
     }
 
-    /// Creates a tarball of save-analysis metadata, if available.
+    /// Creates a tarball of (degenerate) save-analysis metadata, if available.
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let compiler = self.compiler;
         let target = self.target;
@@ -761,7 +762,6 @@ impl Step for Analysis {
             return None;
         }
 
-        builder.ensure(compile::Std::new(compiler, target));
         let src = builder
             .stage_out(compiler, Mode::Std)
             .join(target.triple)
@@ -769,6 +769,13 @@ impl Step for Analysis {
             .join("deps")
             .join("save-analysis");
 
+        // Write a file indicating that this component has been removed.
+        t!(std::fs::create_dir_all(&src));
+        let mut removed = src.clone();
+        removed.push("removed.json");
+        let mut f = t!(std::fs::File::create(removed));
+        t!(write!(f, r#"{{ "warning": "The `rust-analysis` component has been removed." }}"#));
+
         let mut tarball = Tarball::new(builder, "rust-analysis", &target.triple);
         tarball.include_target_in_component_name(true);
         tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index 1815a097307..ac3843c3344 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -243,18 +243,6 @@ install!((self, builder, _config),
             );
         }
     };
-    Analysis, alias = "analysis", Self::should_build(_config), only_hosts: false, {
-        // `expect` should be safe, only None with host != build, but this
-        // only uses the `build` compiler
-        let tarball = builder.ensure(dist::Analysis {
-            // Find the actual compiler (handling the full bootstrap option) which
-            // produced the save-analysis data because that data isn't copied
-            // through the sysroot uplifting.
-            compiler: builder.compiler_for(builder.top_stage, builder.config.build, self.target),
-            target: self.target
-        }).expect("missing analysis");
-        install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
-    };
     Rustc, path = "compiler/rustc", true, only_hosts: true, {
         let tarball = builder.ensure(dist::Rustc {
             compiler: builder.compiler(builder.top_stage, self.target),
diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md
index efbf861eaa6..d8843280b84 100644
--- a/src/doc/rustc/src/json.md
+++ b/src/doc/rustc/src/json.md
@@ -223,7 +223,6 @@ flag][option-emit] documentation.
        - "link": The generated crate as specified by the crate-type.
        - "dep-info": The `.d` file with dependency information in a Makefile-like syntax.
        - "metadata": The Rust `.rmeta` file containing metadata about the crate.
-       - "save-analysis": A JSON file emitted by the `-Zsave-analysis` feature.
     */
     "emit": "link"
 }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index c4b994af13b..4c93f8a16b6 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -192,8 +192,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "regex-automata",
     "regex-syntax",
     "remove_dir_all",
-    "rls-data",
-    "rls-span",
     "rustc-demangle",
     "rustc-hash",
     "rustc-rayon",
diff --git a/tests/run-make-fulldeps/issues-41478-43796/Makefile b/tests/run-make-fulldeps/issues-41478-43796/Makefile
deleted file mode 100644
index e451cb03126..00000000000
--- a/tests/run-make-fulldeps/issues-41478-43796/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
-all:
-	# Work in /tmp, because we need to create the `save-analysis-temp` folder.
-	cp a.rs $(TMPDIR)/
-	cd $(TMPDIR) && $(RUSTC) -Zsave-analysis $(TMPDIR)/a.rs 2> $(TMPDIR)/stderr.txt || ( cat $(TMPDIR)/stderr.txt && exit 1 )
-	[ ! -s $(TMPDIR)/stderr.txt ] || ( cat $(TMPDIR)/stderr.txt && exit 1 )
-	[ -f $(TMPDIR)/save-analysis/liba.json ] || ( ls -la $(TMPDIR) && exit 1 )
diff --git a/tests/run-make-fulldeps/issues-41478-43796/a.rs b/tests/run-make-fulldeps/issues-41478-43796/a.rs
deleted file mode 100644
index b072235b5bc..00000000000
--- a/tests/run-make-fulldeps/issues-41478-43796/a.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-#![crate_type = "lib"]
-pub struct V<S>(#[allow(unused_tuple_struct_fields)] S);
-pub trait An {
-    type U;
-}
-pub trait F<A> {
-}
-impl<A: An> F<A> for V<<A as An>::U> {
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/Makefile b/tests/run-make-fulldeps/save-analysis-fail/Makefile
deleted file mode 100644
index 69a2b274694..00000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-include ../tools.mk
-all: code
-krate2: krate2.rs
-	$(RUSTC) $<
-code: foo.rs krate2
-	$(RUSTC) foo.rs -Zsave-analysis || exit 0
diff --git a/tests/run-make-fulldeps/save-analysis-fail/SameDir.rs b/tests/run-make-fulldeps/save-analysis-fail/SameDir.rs
deleted file mode 100644
index 2c690d5f759..00000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/SameDir.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// sub-module in the same directory as the main crate file
-
-pub struct SameStruct {
-    pub name: String
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/SameDir3.rs b/tests/run-make-fulldeps/save-analysis-fail/SameDir3.rs
deleted file mode 100644
index fab03ee2e3d..00000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/SameDir3.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub fn hello(x: isize) {
-    println!("macro {} :-(", x);
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs b/tests/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs
deleted file mode 100644
index 511721d92a3..00000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/SubDir/mod.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// sub-module in a sub-directory
-
-use sub::sub2 as msalias;
-use sub::sub2;
-
-static yy: usize = 25;
-
-mod sub {
-    pub mod sub2 {
-        pub mod sub3 {
-            pub fn hello() {
-                println!("hello from module 3");
-            }
-        }
-        pub fn hello() {
-            println!("hello from a module");
-        }
-
-        pub struct nested_struct {
-            pub field2: u32,
-        }
-    }
-}
-
-pub struct SubStruct {
-    pub name: String
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/foo.rs b/tests/run-make-fulldeps/save-analysis-fail/foo.rs
deleted file mode 100644
index c5a70605e04..00000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/foo.rs
+++ /dev/null
@@ -1,463 +0,0 @@
-#![crate_name = "test"]
-#![feature(rustc_private)]
-
-extern crate rustc_graphviz;
-// A simple rust project
-
-extern crate krate2;
-extern crate krate2 as krate3;
-
-use rustc_graphviz::RenderOption;
-use std::cell::RefCell;
-use std::collections::{HashMap, HashSet};
-use std::io::Write;
-
-use sub::sub2 as msalias;
-use sub::sub2;
-use sub::sub2::nested_struct as sub_struct;
-
-use std::mem::size_of;
-
-use std::char::from_u32;
-
-static uni: &'static str = "Les Miséééééééérables";
-static yy: usize = 25;
-
-static bob: Option<graphviz::RenderOption> = None;
-
-// buglink test - see issue #1337.
-
-fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
-    let s = sub_struct { field2: 45u32 };
-
-    // import tests
-    fn foo(x: &Write) {}
-    let _: Option<_> = from_u32(45);
-
-    let x = 42usize;
-
-    krate2::hello();
-    krate3::hello();
-
-    let x = (3isize, 4usize);
-    let y = x.1;
-}
-
-// Issue #37700
-const LUT_BITS: usize = 3;
-pub struct HuffmanTable {
-    ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>,
-}
-
-struct TupStruct(isize, isize, Box<str>);
-
-fn test_tup_struct(x: TupStruct) -> isize {
-    x.1
-}
-
-fn println(s: &str) {
-    std::io::stdout().write_all(s.as_bytes());
-}
-
-mod sub {
-    pub mod sub2 {
-        use std::io::Write;
-        pub mod sub3 {
-            use std::io::Write;
-            pub fn hello() {
-                ::println("hello from module 3");
-            }
-        }
-        pub fn hello() {
-            ::println("hello from a module");
-        }
-
-        pub struct nested_struct {
-            pub field2: u32,
-        }
-
-        pub enum nested_enum {
-            Nest2 = 2,
-            Nest3 = 3,
-        }
-    }
-}
-
-pub mod SameDir;
-pub mod SubDir;
-
-#[path = "SameDir3.rs"]
-pub mod SameDir2;
-
-struct nofields;
-
-#[derive(Clone)]
-struct some_fields {
-    field1: u32,
-}
-
-type SF = some_fields;
-
-trait SuperTrait {
-    fn qux(&self) {
-        panic!();
-    }
-}
-
-trait SomeTrait: SuperTrait {
-    fn Method(&self, x: u32) -> u32;
-
-    fn prov(&self, x: u32) -> u32 {
-        println(&x.to_string());
-        42
-    }
-    fn provided_method(&self) -> u32 {
-        42
-    }
-}
-
-trait SubTrait: SomeTrait {
-    fn stat2(x: &Self) -> u32 {
-        32
-    }
-}
-
-trait SizedTrait: Sized {}
-
-fn error(s: &SizedTrait) {
-    let foo = 42;
-    println!("Hello world! {}", foo);
-}
-
-impl SomeTrait for some_fields {
-    fn Method(&self, x: u32) -> u32 {
-        println(&x.to_string());
-        self.field1
-    }
-}
-
-impl SuperTrait for some_fields {}
-
-impl SubTrait for some_fields {}
-
-impl some_fields {
-    fn stat(x: u32) -> u32 {
-        println(&x.to_string());
-        42
-    }
-    fn stat2(x: &some_fields) -> u32 {
-        42
-    }
-
-    fn align_to<T>(&mut self) {}
-
-    fn test(&mut self) {
-        self.align_to::<bool>();
-    }
-}
-
-impl SuperTrait for nofields {}
-impl SomeTrait for nofields {
-    fn Method(&self, x: u32) -> u32 {
-        self.Method(x);
-        43
-    }
-
-    fn provided_method(&self) -> u32 {
-        21
-    }
-}
-
-impl SubTrait for nofields {}
-
-impl SuperTrait for (Box<nofields>, Box<some_fields>) {}
-
-fn f_with_params<T: SomeTrait>(x: &T) {
-    x.Method(41);
-}
-
-type MyType = Box<some_fields>;
-
-enum SomeEnum<'a> {
-    Ints(isize, isize),
-    Floats(f64, f64),
-    Strings(&'a str, &'a str, &'a str),
-    MyTypes(MyType, MyType),
-}
-
-#[derive(Copy, Clone)]
-enum SomeOtherEnum {
-    SomeConst1,
-    SomeConst2,
-    SomeConst3,
-}
-
-enum SomeStructEnum {
-    EnumStruct { a: isize, b: isize },
-    EnumStruct2 { f1: MyType, f2: MyType },
-    EnumStruct3 { f1: MyType, f2: MyType, f3: SomeEnum<'static> },
-}
-
-fn matchSomeEnum(val: SomeEnum) {
-    match val {
-        SomeEnum::Ints(int1, int2) => {
-            println(&(int1 + int2).to_string());
-        }
-        SomeEnum::Floats(float1, float2) => {
-            println(&(float2 * float1).to_string());
-        }
-        SomeEnum::Strings(.., s3) => {
-            println(s3);
-        }
-        SomeEnum::MyTypes(mt1, mt2) => {
-            println(&(mt1.field1 - mt2.field1).to_string());
-        }
-    }
-}
-
-fn matchSomeStructEnum(se: SomeStructEnum) {
-    match se {
-        SomeStructEnum::EnumStruct { a: a, .. } => println(&a.to_string()),
-        SomeStructEnum::EnumStruct2 { f1: f1, f2: f_2 } => println(&f_2.field1.to_string()),
-        SomeStructEnum::EnumStruct3 { f1, .. } => println(&f1.field1.to_string()),
-    }
-}
-
-fn matchSomeStructEnum2(se: SomeStructEnum) {
-    use SomeStructEnum::*;
-    match se {
-        EnumStruct { a: ref aaa, .. } => println(&aaa.to_string()),
-        EnumStruct2 { f1, f2: f2 } => println(&f1.field1.to_string()),
-        EnumStruct3 { f1, f3: SomeEnum::Ints(..), f2 } => println(&f1.field1.to_string()),
-        _ => {}
-    }
-}
-
-fn matchSomeOtherEnum(val: SomeOtherEnum) {
-    use SomeOtherEnum::{SomeConst2, SomeConst3};
-    match val {
-        SomeOtherEnum::SomeConst1 => {
-            println("I'm const1.");
-        }
-        SomeConst2 | SomeConst3 => {
-            println("I'm const2 or const3.");
-        }
-    }
-}
-
-fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) {
-    SameDir2::hello(43);
-
-    println(&yy.to_string());
-    let (x, y): (u32, u32) = (5, 3);
-    println(&x.to_string());
-    println(&z.to_string());
-    let x: u32 = x;
-    println(&x.to_string());
-    let x = "hello";
-    println(x);
-
-    let x = 32.0f32;
-    let _ = (x + ((x * x) + 1.0).sqrt()).ln();
-
-    let s: Box<SomeTrait> = Box::new(some_fields { field1: 43 });
-    let s2: Box<some_fields> = Box::new(some_fields { field1: 43 });
-    let s3 = Box::new(nofields);
-
-    s.Method(43);
-    s3.Method(43);
-    s2.Method(43);
-
-    ex.prov(43);
-
-    let y: u32 = 56;
-    // static method on struct
-    let r = some_fields::stat(y);
-    // trait static method, calls default
-    let r = SubTrait::stat2(&*s3);
-
-    let s4 = s3 as Box<SomeTrait>;
-    s4.Method(43);
-
-    s4.provided_method();
-    s2.prov(45);
-
-    let closure = |x: u32, s: &SomeTrait| {
-        s.Method(23);
-        return x + y;
-    };
-
-    let z = closure(10, &*s);
-}
-
-pub struct blah {
-    used_link_args: RefCell<[&'static str; 0]>,
-}
-
-#[macro_use]
-mod macro_use_test {
-    macro_rules! test_rec {
-        (q, $src: expr) => {{
-            print!("{}", $src);
-            test_rec!($src);
-        }};
-        ($src: expr) => {
-            print!("{}", $src);
-        };
-    }
-
-    macro_rules! internal_vars {
-        ($src: ident) => {{
-            let mut x = $src;
-            x += 100;
-        }};
-    }
-}
-
-fn main() {
-    // foo
-    let s = Box::new(some_fields { field1: 43 });
-    hello((43, "a".to_string()), *s);
-    sub::sub2::hello();
-    sub2::sub3::hello();
-
-    let h = sub2::sub3::hello;
-    h();
-
-    // utf8 chars
-    let ut = "Les Miséééééééérables";
-
-    // For some reason, this pattern of macro_rules foiled our generated code
-    // avoiding strategy.
-    macro_rules! variable_str(($name:expr) => (
-        some_fields {
-            field1: $name,
-        }
-    ));
-    let vs = variable_str!(32);
-
-    let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
-    let _ = blah { used_link_args: RefCell::new([]) };
-    let s1 = nofields;
-    let s2 = SF { field1: 55 };
-    let s3: some_fields = some_fields { field1: 55 };
-    let s4: msalias::nested_struct = sub::sub2::nested_struct { field2: 55 };
-    let s4: msalias::nested_struct = sub2::nested_struct { field2: 55 };
-    println(&s2.field1.to_string());
-    let s5: MyType = Box::new(some_fields { field1: 55 });
-    let s = SameDir::SameStruct { name: "Bob".to_string() };
-    let s = SubDir::SubStruct { name: "Bob".to_string() };
-    let s6: SomeEnum = SomeEnum::MyTypes(Box::new(s2.clone()), s5);
-    let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
-    matchSomeEnum(s6);
-    matchSomeEnum(s7);
-    let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
-    matchSomeOtherEnum(s8);
-    let s9: SomeStructEnum =
-        SomeStructEnum::EnumStruct2 { f1: Box::new(some_fields { field1: 10 }), f2: Box::new(s2) };
-    matchSomeStructEnum(s9);
-
-    for x in &vec![1, 2, 3] {
-        let _y = x;
-    }
-
-    let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
-    if let SomeEnum::Strings(..) = s7 {
-        println!("hello!");
-    }
-
-    for i in 0..5 {
-        foo_foo(i);
-    }
-
-    if let Some(x) = None {
-        foo_foo(x);
-    }
-
-    if false {
-    } else if let Some(y) = None {
-        foo_foo(y);
-    }
-
-    while let Some(z) = None {
-        foo_foo(z);
-    }
-
-    let mut x = 4;
-    test_rec!(q, "Hello");
-    assert_eq!(x, 4);
-    internal_vars!(x);
-}
-
-fn foo_foo(_: i32) {}
-
-impl Iterator for nofields {
-    type Item = (usize, usize);
-
-    fn next(&mut self) -> Option<(usize, usize)> {
-        panic!()
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        panic!()
-    }
-}
-
-trait Pattern<'a> {
-    type Searcher;
-}
-
-struct CharEqPattern;
-
-impl<'a> Pattern<'a> for CharEqPattern {
-    type Searcher = CharEqPattern;
-}
-
-struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
-
-pub trait Error {}
-
-impl Error + 'static {
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        panic!()
-    }
-}
-
-impl Error + 'static + Send {
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        <Error + 'static>::is::<T>(self)
-    }
-}
-extern crate serialize;
-#[derive(Clone, Copy, Hash, Encodable, Decodable, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
-struct AllDerives(i32);
-
-fn test_format_args() {
-    let x = 1;
-    let y = 2;
-    let name = "Joe Blogg";
-    println!("Hello {}", name);
-    print!("Hello {0}", name);
-    print!("{0} + {} = {}", x, y);
-    print!("x is {}, y is {1}, name is {n}", x, y, n = name);
-}
-
-extern "C" {
-    static EXTERN_FOO: u8;
-    fn extern_foo(a: u8, b: i32) -> String;
-}
-
-struct Rls699 {
-    f: u32,
-}
-
-fn new(f: u32) -> Rls699 {
-    Rls699 { fs }
-}
-
-fn invalid_tuple_struct_access() {
-    bar.0;
-
-    struct S;
-    S.0;
-}
diff --git a/tests/run-make-fulldeps/save-analysis-fail/krate2.rs b/tests/run-make-fulldeps/save-analysis-fail/krate2.rs
deleted file mode 100644
index 7d787e0c987..00000000000
--- a/tests/run-make-fulldeps/save-analysis-fail/krate2.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![ crate_name = "krate2" ]
-#![ crate_type = "lib" ]
-
-use std::io::Write;
-
-pub fn hello() {
-    std::io::stdout().write_all(b"hello world!\n");
-}
diff --git a/tests/run-make-fulldeps/save-analysis-rfc2126/Makefile b/tests/run-make-fulldeps/save-analysis-rfc2126/Makefile
deleted file mode 100644
index 30f57034bba..00000000000
--- a/tests/run-make-fulldeps/save-analysis-rfc2126/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
-all: extern_absolute_paths.rs krate2
-	$(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018 --extern krate2
-	cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py
-
-krate2: krate2.rs
-	$(RUSTC) $<
diff --git a/tests/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs b/tests/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs
deleted file mode 100644
index 7a8e3fff098..00000000000
--- a/tests/run-make-fulldeps/save-analysis-rfc2126/extern_absolute_paths.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-use krate2::hello;
-
-fn main() {
-    hello();
-    ::krate2::hello();
-}
diff --git a/tests/run-make-fulldeps/save-analysis-rfc2126/krate2.rs b/tests/run-make-fulldeps/save-analysis-rfc2126/krate2.rs
deleted file mode 100644
index d24c68862b0..00000000000
--- a/tests/run-make-fulldeps/save-analysis-rfc2126/krate2.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![crate_name = "krate2"]
-#![crate_type = "lib"]
-
-pub fn hello() {
-}
diff --git a/tests/run-make-fulldeps/save-analysis-rfc2126/validate_json.py b/tests/run-make-fulldeps/save-analysis-rfc2126/validate_json.py
deleted file mode 100644
index 882d29a8beb..00000000000
--- a/tests/run-make-fulldeps/save-analysis-rfc2126/validate_json.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python
-
-import sys
-import json
-
-crates = json.loads(sys.stdin.readline().strip())["prelude"]["external_crates"]
-assert any(map(lambda c: c["id"]["name"] == "krate2", crates))
diff --git a/tests/run-make-fulldeps/save-analysis/Makefile b/tests/run-make-fulldeps/save-analysis/Makefile
deleted file mode 100644
index b8b6be13dbd..00000000000
--- a/tests/run-make-fulldeps/save-analysis/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-include ../tools.mk
-all: code
-krate2: krate2.rs
-	$(RUSTC) $<
-code: foo.rs krate2
-	$(RUSTC) foo.rs -Zsave-analysis
diff --git a/tests/run-make-fulldeps/save-analysis/SameDir.rs b/tests/run-make-fulldeps/save-analysis/SameDir.rs
deleted file mode 100644
index 2c690d5f759..00000000000
--- a/tests/run-make-fulldeps/save-analysis/SameDir.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// sub-module in the same directory as the main crate file
-
-pub struct SameStruct {
-    pub name: String
-}
diff --git a/tests/run-make-fulldeps/save-analysis/SameDir3.rs b/tests/run-make-fulldeps/save-analysis/SameDir3.rs
deleted file mode 100644
index fab03ee2e3d..00000000000
--- a/tests/run-make-fulldeps/save-analysis/SameDir3.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub fn hello(x: isize) {
-    println!("macro {} :-(", x);
-}
diff --git a/tests/run-make-fulldeps/save-analysis/SubDir/mod.rs b/tests/run-make-fulldeps/save-analysis/SubDir/mod.rs
deleted file mode 100644
index 511721d92a3..00000000000
--- a/tests/run-make-fulldeps/save-analysis/SubDir/mod.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// sub-module in a sub-directory
-
-use sub::sub2 as msalias;
-use sub::sub2;
-
-static yy: usize = 25;
-
-mod sub {
-    pub mod sub2 {
-        pub mod sub3 {
-            pub fn hello() {
-                println!("hello from module 3");
-            }
-        }
-        pub fn hello() {
-            println!("hello from a module");
-        }
-
-        pub struct nested_struct {
-            pub field2: u32,
-        }
-    }
-}
-
-pub struct SubStruct {
-    pub name: String
-}
diff --git a/tests/run-make-fulldeps/save-analysis/extra-docs.md b/tests/run-make-fulldeps/save-analysis/extra-docs.md
deleted file mode 100644
index 0605ca517ff..00000000000
--- a/tests/run-make-fulldeps/save-analysis/extra-docs.md
+++ /dev/null
@@ -1 +0,0 @@
-Extra docs for this struct.
diff --git a/tests/run-make-fulldeps/save-analysis/foo.rs b/tests/run-make-fulldeps/save-analysis/foo.rs
deleted file mode 100644
index 384589de3b4..00000000000
--- a/tests/run-make-fulldeps/save-analysis/foo.rs
+++ /dev/null
@@ -1,465 +0,0 @@
-#![crate_name = "test"]
-#![feature(rustc_private)]
-#![feature(associated_type_defaults)]
-
-extern crate rustc_graphviz;
-// A simple rust project
-
-// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
-// files.
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
-
-extern crate krate2;
-extern crate krate2 as krate3;
-
-use rustc_graphviz::RenderOption;
-use std::cell::RefCell;
-use std::collections::{HashMap, HashSet};
-use std::io::Write;
-
-use sub::sub2 as msalias;
-use sub::sub2;
-use sub::sub2::nested_struct as sub_struct;
-
-use std::mem::size_of;
-
-use std::char::from_u32;
-
-static uni: &'static str = "Les Miséééééééérables";
-static yy: usize = 25;
-
-static bob: Option<rustc_graphviz::RenderOption> = None;
-
-// buglink test - see issue #1337.
-
-fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
-    let s = sub_struct { field2: 45u32 };
-
-    // import tests
-    fn foo(x: &Write) {}
-    let _: Option<_> = from_u32(45);
-
-    let x = 42usize;
-
-    krate2::hello();
-    krate3::hello();
-
-    let x = (3isize, 4usize);
-    let y = x.1;
-}
-
-// Issue #37700
-const LUT_BITS: usize = 3;
-pub struct HuffmanTable {
-    ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>,
-}
-
-struct TupStruct(isize, isize, Box<str>);
-
-fn test_tup_struct(x: TupStruct) -> isize {
-    x.1
-}
-
-fn println(s: &str) {
-    std::io::stdout().write_all(s.as_bytes());
-}
-
-mod sub {
-    pub mod sub2 {
-        use std::io::Write;
-        pub mod sub3 {
-            use std::io::Write;
-            pub fn hello() {
-                ::println("hello from module 3");
-            }
-        }
-        pub fn hello() {
-            ::println("hello from a module");
-        }
-
-        pub struct nested_struct {
-            pub field2: u32,
-        }
-
-        pub enum nested_enum {
-            Nest2 = 2,
-            Nest3 = 3,
-        }
-    }
-}
-
-pub mod SameDir;
-pub mod SubDir;
-
-#[path = "SameDir3.rs"]
-pub mod SameDir2;
-
-struct nofields;
-
-#[derive(Clone)]
-struct some_fields {
-    field1: u32,
-}
-
-type SF = some_fields;
-
-trait SuperTrait {
-    fn qux(&self) {
-        panic!();
-    }
-}
-
-trait SomeTrait: SuperTrait {
-    fn Method(&self, x: u32) -> u32;
-
-    fn prov(&self, x: u32) -> u32 {
-        println(&x.to_string());
-        42
-    }
-    fn provided_method(&self) -> u32 {
-        42
-    }
-}
-
-trait SubTrait: SomeTrait {
-    fn stat2(x: &Self) -> u32 {
-        32
-    }
-}
-
-impl SomeTrait for some_fields {
-    fn Method(&self, x: u32) -> u32 {
-        println(&x.to_string());
-        self.field1
-    }
-}
-
-impl SuperTrait for some_fields {}
-
-impl SubTrait for some_fields {}
-
-impl some_fields {
-    fn stat(x: u32) -> u32 {
-        println(&x.to_string());
-        42
-    }
-    fn stat2(x: &some_fields) -> u32 {
-        42
-    }
-
-    fn align_to<T>(&mut self) {}
-
-    fn test(&mut self) {
-        self.align_to::<bool>();
-    }
-}
-
-impl SuperTrait for nofields {}
-impl SomeTrait for nofields {
-    fn Method(&self, x: u32) -> u32 {
-        self.Method(x);
-        43
-    }
-
-    fn provided_method(&self) -> u32 {
-        21
-    }
-}
-
-impl SubTrait for nofields {}
-
-impl SuperTrait for (Box<nofields>, Box<some_fields>) {}
-
-fn f_with_params<T: SomeTrait>(x: &T) {
-    x.Method(41);
-}
-
-type MyType = Box<some_fields>;
-
-enum SomeEnum<'a> {
-    Ints(isize, isize),
-    Floats(f64, f64),
-    Strings(&'a str, &'a str, &'a str),
-    MyTypes(MyType, MyType),
-}
-
-#[derive(Copy, Clone)]
-enum SomeOtherEnum {
-    SomeConst1,
-    SomeConst2,
-    SomeConst3,
-}
-
-enum SomeStructEnum {
-    EnumStruct { a: isize, b: isize },
-    EnumStruct2 { f1: MyType, f2: MyType },
-    EnumStruct3 { f1: MyType, f2: MyType, f3: SomeEnum<'static> },
-}
-
-fn matchSomeEnum(val: SomeEnum) {
-    match val {
-        SomeEnum::Ints(int1, int2) => {
-            println(&(int1 + int2).to_string());
-        }
-        SomeEnum::Floats(float1, float2) => {
-            println(&(float2 * float1).to_string());
-        }
-        SomeEnum::Strings(.., s3) => {
-            println(s3);
-        }
-        SomeEnum::MyTypes(mt1, mt2) => {
-            println(&(mt1.field1 - mt2.field1).to_string());
-        }
-    }
-}
-
-fn matchSomeStructEnum(se: SomeStructEnum) {
-    match se {
-        SomeStructEnum::EnumStruct { a: a, .. } => println(&a.to_string()),
-        SomeStructEnum::EnumStruct2 { f1: f1, f2: f_2 } => println(&f_2.field1.to_string()),
-        SomeStructEnum::EnumStruct3 { f1, .. } => println(&f1.field1.to_string()),
-    }
-}
-
-fn matchSomeStructEnum2(se: SomeStructEnum) {
-    use SomeStructEnum::*;
-    match se {
-        EnumStruct { a: ref aaa, .. } => println(&aaa.to_string()),
-        EnumStruct2 { f1, f2: f2 } => println(&f1.field1.to_string()),
-        EnumStruct3 { f1, f3: SomeEnum::Ints(..), f2 } => println(&f1.field1.to_string()),
-        _ => {}
-    }
-}
-
-fn matchSomeOtherEnum(val: SomeOtherEnum) {
-    use SomeOtherEnum::{SomeConst2, SomeConst3};
-    match val {
-        SomeOtherEnum::SomeConst1 => {
-            println("I'm const1.");
-        }
-        SomeConst2 | SomeConst3 => {
-            println("I'm const2 or const3.");
-        }
-    }
-}
-
-fn hello<X: SomeTrait>((z, a): (u32, String), ex: X) {
-    SameDir2::hello(43);
-
-    println(&yy.to_string());
-    let (x, y): (u32, u32) = (5, 3);
-    println(&x.to_string());
-    println(&z.to_string());
-    let x: u32 = x;
-    println(&x.to_string());
-    let x = "hello";
-    println(x);
-
-    let x = 32.0f32;
-    let _ = (x + ((x * x) + 1.0).sqrt()).ln();
-
-    let s: Box<SomeTrait> = Box::new(some_fields { field1: 43 });
-    let s2: Box<some_fields> = Box::new(some_fields { field1: 43 });
-    let s3 = Box::new(nofields);
-
-    s.Method(43);
-    s3.Method(43);
-    s2.Method(43);
-
-    ex.prov(43);
-
-    let y: u32 = 56;
-    // static method on struct
-    let r = some_fields::stat(y);
-    // trait static method, calls default
-    let r = SubTrait::stat2(&*s3);
-
-    let s4 = s3 as Box<SomeTrait>;
-    s4.Method(43);
-
-    s4.provided_method();
-    s2.prov(45);
-
-    let closure = |x: u32, s: &SomeTrait| {
-        s.Method(23);
-        return x + y;
-    };
-
-    let z = closure(10, &*s);
-}
-
-pub struct blah {
-    used_link_args: RefCell<[&'static str; 0]>,
-}
-
-#[macro_use]
-mod macro_use_test {
-    macro_rules! test_rec {
-        (q, $src: expr) => {{
-            print!("{}", $src);
-            test_rec!($src);
-        }};
-        ($src: expr) => {
-            print!("{}", $src);
-        };
-    }
-
-    macro_rules! internal_vars {
-        ($src: ident) => {{
-            let mut x = $src;
-            x += 100;
-        }};
-    }
-}
-
-fn main() {
-    // foo
-    let s = Box::new(some_fields { field1: 43 });
-    hello((43, "a".to_string()), *s);
-    sub::sub2::hello();
-    sub2::sub3::hello();
-
-    let h = sub2::sub3::hello;
-    h();
-
-    // utf8 chars
-    let ut = "Les Miséééééééérables";
-
-    // For some reason, this pattern of macro_rules foiled our generated code
-    // avoiding strategy.
-    macro_rules! variable_str(($name:expr) => (
-        some_fields {
-            field1: $name,
-        }
-    ));
-    let vs = variable_str!(32);
-
-    let mut candidates: RefCell<HashMap<&'static str, &'static str>> = RefCell::new(HashMap::new());
-    let _ = blah { used_link_args: RefCell::new([]) };
-    let s1 = nofields;
-    let s2 = SF { field1: 55 };
-    let s3: some_fields = some_fields { field1: 55 };
-    let s4: msalias::nested_struct = sub::sub2::nested_struct { field2: 55 };
-    let s4: msalias::nested_struct = sub2::nested_struct { field2: 55 };
-    println(&s2.field1.to_string());
-    let s5: MyType = Box::new(some_fields { field1: 55 });
-    let s = SameDir::SameStruct { name: "Bob".to_string() };
-    let s = SubDir::SubStruct { name: "Bob".to_string() };
-    let s6: SomeEnum = SomeEnum::MyTypes(Box::new(s2.clone()), s5);
-    let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
-    matchSomeEnum(s6);
-    matchSomeEnum(s7);
-    let s8: SomeOtherEnum = SomeOtherEnum::SomeConst2;
-    matchSomeOtherEnum(s8);
-    let s9: SomeStructEnum =
-        SomeStructEnum::EnumStruct2 { f1: Box::new(some_fields { field1: 10 }), f2: Box::new(s2) };
-    matchSomeStructEnum(s9);
-
-    for x in &vec![1, 2, 3] {
-        let _y = x;
-    }
-
-    let s7: SomeEnum = SomeEnum::Strings("one", "two", "three");
-    if let SomeEnum::Strings(..) = s7 {
-        println!("hello!");
-    }
-
-    for i in 0..5 {
-        foo_foo(i);
-    }
-
-    if let Some(x) = None {
-        foo_foo(x);
-    }
-
-    if false {
-    } else if let Some(y) = None {
-        foo_foo(y);
-    }
-
-    while let Some(z) = None {
-        foo_foo(z);
-    }
-
-    let mut x = 4;
-    test_rec!(q, "Hello");
-    assert_eq!(x, 4);
-    internal_vars!(x);
-}
-
-fn foo_foo(_: i32) {}
-
-impl Iterator for nofields {
-    type Item = (usize, usize);
-
-    fn next(&mut self) -> Option<(usize, usize)> {
-        panic!()
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        panic!()
-    }
-}
-
-trait Pattern<'a> {
-    type Searcher;
-}
-
-struct CharEqPattern;
-
-impl<'a> Pattern<'a> for CharEqPattern {
-    type Searcher = CharEqPattern;
-}
-
-struct CharSearcher<'a>(<CharEqPattern as Pattern<'a>>::Searcher);
-
-pub trait Error {}
-
-impl Error + 'static {
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        panic!()
-    }
-}
-
-impl Error + 'static + Send {
-    pub fn is<T: Error + 'static>(&self) -> bool {
-        <Error + 'static>::is::<T>(self)
-    }
-}
-extern crate rustc_serialize;
-#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Default)]
-struct AllDerives(i32);
-
-fn test_format_args() {
-    let x = 1;
-    let y = 2;
-    let name = "Joe Blogg";
-    println!("Hello {}", name);
-    print!("Hello {0}", name);
-    print!("{0} + {} = {}", x, y);
-    print!("x is {}, y is {1}, name is {n}", x, y, n = name);
-}
-
-union TestUnion {
-    f1: u32,
-}
-
-struct FrameBuffer;
-
-struct SilenceGenerator;
-
-impl Iterator for SilenceGenerator {
-    type Item = FrameBuffer;
-
-    fn next(&mut self) -> Option<Self::Item> {
-        panic!();
-    }
-}
-
-#[doc = include_str!("extra-docs.md")]
-struct StructWithDocs;
-
-trait Foo {
-    type Bar = FrameBuffer;
-}
diff --git a/tests/run-make-fulldeps/save-analysis/krate2.rs b/tests/run-make-fulldeps/save-analysis/krate2.rs
deleted file mode 100644
index 7d787e0c987..00000000000
--- a/tests/run-make-fulldeps/save-analysis/krate2.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![ crate_name = "krate2" ]
-#![ crate_type = "lib" ]
-
-use std::io::Write;
-
-pub fn hello() {
-    std::io::stdout().write_all(b"hello world!\n");
-}
diff --git a/tests/rustdoc-ui/z-help.stdout b/tests/rustdoc-ui/z-help.stdout
index 96329f31723..8d0155151b8 100644
--- a/tests/rustdoc-ui/z-help.stdout
+++ b/tests/rustdoc-ui/z-help.stdout
@@ -146,7 +146,6 @@
     -Z          sanitizer-memory-track-origins=val -- enable origins tracking in MemorySanitizer
     -Z                       sanitizer-recover=val -- enable recovery for selected sanitizers
     -Z                  saturating-float-casts=val -- make float->int casts UB-free: numbers outside the integer type's range are clipped to the max/min integer respectively, and NaN is mapped to 0 (default: yes)
-    -Z                           save-analysis=val -- write syntax and type analysis (in JSON format) information, in addition to normal output (default: no)
     -Z                            self-profile=val -- run the self profiler and output the raw event data
     -Z                    self-profile-counter=val -- counter used by the self profiler (default: `wall-time`), one of:
         `wall-time` (monotonic clock, i.e. `std::time::Instant`)
diff --git a/tests/ui/asm/issue-72570.rs b/tests/ui/asm/issue-72570.rs
index bb13816348d..ac589de2303 100644
--- a/tests/ui/asm/issue-72570.rs
+++ b/tests/ui/asm/issue-72570.rs
@@ -1,6 +1,4 @@
-// compile-flags: -Zsave-analysis
 // needs-asm-support
-// Also test for #72960
 
 use std::arch::asm;
 
diff --git a/tests/ui/asm/issue-72570.stderr b/tests/ui/asm/issue-72570.stderr
index fa5792688b2..49013a23ced 100644
--- a/tests/ui/asm/issue-72570.stderr
+++ b/tests/ui/asm/issue-72570.stderr
@@ -1,5 +1,5 @@
 error: invalid register `invalid`: unknown register
-  --> $DIR/issue-72570.rs:9:18
+  --> $DIR/issue-72570.rs:7:18
    |
 LL |         asm!("", in("invalid") "".len());
    |                  ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr
index f1f3a9c3de0..82030731cc1 100644
--- a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr
+++ b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr
@@ -1,5 +1,5 @@
 error[E0658]: a non-static lifetime is not allowed in a `const`
-  --> $DIR/const-argument-non-static-lifetime.rs:15:17
+  --> $DIR/const-argument-non-static-lifetime.rs:14:17
    |
 LL |         let _: &'a ();
    |                 ^^
diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.rs b/tests/ui/const-generics/const-argument-non-static-lifetime.rs
index 36a569784ad..0357e4ed59f 100644
--- a/tests/ui/const-generics/const-argument-non-static-lifetime.rs
+++ b/tests/ui/const-generics/const-argument-non-static-lifetime.rs
@@ -2,7 +2,6 @@
 // revisions: full min
 
 // regression test for #78180
-// compile-flags: -Zsave-analysis
 
 #![cfg_attr(full, feature(generic_const_exprs))]
 #![cfg_attr(full, allow(incomplete_features))]
diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
index 781f50e6173..b776f2017fa 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
+++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.rs
@@ -1,6 +1,3 @@
-// compile-flags: -Zsave-analysis
-// Regression test for #69414 ^
-
 use std::marker::PhantomData;
 
 struct B<T, const N: T>(PhantomData<[T; N]>);
diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
index 8e14defd65d..9c5c97befd8 100644
--- a/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
+++ b/tests/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
@@ -1,5 +1,5 @@
 error[E0770]: the type of const parameters must not depend on other generic parameters
-  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:6:22
+  --> $DIR/const-param-type-depends-on-type-param-ungated.rs:3:22
    |
 LL | struct B<T, const N: T>(PhantomData<[T; N]>);
    |                      ^ the type must not depend on the parameter `T`
diff --git a/tests/ui/const-generics/issues/issue-73260.rs b/tests/ui/const-generics/issues/issue-73260.rs
index d762f9c8b26..aa7ae90a363 100644
--- a/tests/ui/const-generics/issues/issue-73260.rs
+++ b/tests/ui/const-generics/issues/issue-73260.rs
@@ -1,4 +1,3 @@
-// compile-flags: -Zsave-analysis
 #![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
 struct Arr<const N: usize>
diff --git a/tests/ui/const-generics/issues/issue-73260.stderr b/tests/ui/const-generics/issues/issue-73260.stderr
index 7670032e5b7..f9ff0f28d51 100644
--- a/tests/ui/const-generics/issues/issue-73260.stderr
+++ b/tests/ui/const-generics/issues/issue-73260.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-73260.rs:16:12
+  --> $DIR/issue-73260.rs:15:12
    |
 LL |     let x: Arr<{usize::MAX}> = Arr {};
    |            ^^^^^^^^^^^^^^^^^ expected `false`, found `true`
@@ -7,7 +7,7 @@ LL |     let x: Arr<{usize::MAX}> = Arr {};
    = note: expected constant `false`
               found constant `true`
 note: required by a bound in `Arr`
-  --> $DIR/issue-73260.rs:6:37
+  --> $DIR/issue-73260.rs:5:37
    |
 LL | struct Arr<const N: usize>
    |        --- required by a bound in this
@@ -16,7 +16,7 @@ LL |     Assert::<{N < usize::MAX / 2}>: IsTrue,
    |                                     ^^^^^^ required by this bound in `Arr`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-73260.rs:16:32
+  --> $DIR/issue-73260.rs:15:32
    |
 LL |     let x: Arr<{usize::MAX}> = Arr {};
    |                                ^^^ expected `false`, found `true`
@@ -24,7 +24,7 @@ LL |     let x: Arr<{usize::MAX}> = Arr {};
    = note: expected constant `false`
               found constant `true`
 note: required by a bound in `Arr`
-  --> $DIR/issue-73260.rs:6:37
+  --> $DIR/issue-73260.rs:5:37
    |
 LL | struct Arr<const N: usize>
    |        --- required by a bound in this
diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
index 4e020327447..49fb10e6029 100644
--- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
+++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.rs
@@ -1,6 +1,3 @@
-// compile-flags: -Zsave-analysis
-// This is also a regression test for #69415 and the above flag is needed.
-
 use std::mem::ManuallyDrop;
 
 trait Tr1 { type As1: Copy; }
diff --git a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
index 6f2919b6c09..edbbf7db565 100644
--- a/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
+++ b/tests/ui/feature-gates/feature-gate-associated_type_bounds.stderr
@@ -1,5 +1,5 @@
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:15:22
+  --> $DIR/feature-gate-associated_type_bounds.rs:12:22
    |
 LL |     type A: Iterator<Item: Copy>;
    |                      ^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     type A: Iterator<Item: Copy>;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:19:22
+  --> $DIR/feature-gate-associated_type_bounds.rs:16:22
    |
 LL |     type B: Iterator<Item: 'static>;
    |                      ^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ LL |     type B: Iterator<Item: 'static>;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:23:20
+  --> $DIR/feature-gate-associated_type_bounds.rs:20:20
    |
 LL | struct _St1<T: Tr1<As1: Tr2>> {
    |                    ^^^^^^^^
@@ -26,7 +26,7 @@ LL | struct _St1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:30:18
+  --> $DIR/feature-gate-associated_type_bounds.rs:27:18
    |
 LL | enum _En1<T: Tr1<As1: Tr2>> {
    |                  ^^^^^^^^
@@ -35,7 +35,7 @@ LL | enum _En1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:37:19
+  --> $DIR/feature-gate-associated_type_bounds.rs:34:19
    |
 LL | union _Un1<T: Tr1<As1: Tr2>> {
    |                   ^^^^^^^^
@@ -44,7 +44,7 @@ LL | union _Un1<T: Tr1<As1: Tr2>> {
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:44:37
+  --> $DIR/feature-gate-associated_type_bounds.rs:41:37
    |
 LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
    |                                     ^^^^^^^^^^
@@ -53,7 +53,7 @@ LL | type _TaWhere1<T> where T: Iterator<Item: Copy> = T;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:47:22
+  --> $DIR/feature-gate-associated_type_bounds.rs:44:22
    |
 LL | fn _apit(_: impl Tr1<As1: Copy>) {}
    |                      ^^^^^^^^^
@@ -62,7 +62,7 @@ LL | fn _apit(_: impl Tr1<As1: Copy>) {}
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:49:26
+  --> $DIR/feature-gate-associated_type_bounds.rs:46:26
    |
 LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
    |                          ^^^^^^^^^
@@ -71,7 +71,7 @@ LL | fn _apit_dyn(_: &dyn Tr1<As1: Copy>) {}
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:52:24
+  --> $DIR/feature-gate-associated_type_bounds.rs:49:24
    |
 LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
    |                        ^^^^^^^^^
@@ -80,7 +80,7 @@ LL | fn _rpit() -> impl Tr1<As1: Copy> { S1 }
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:55:31
+  --> $DIR/feature-gate-associated_type_bounds.rs:52:31
    |
 LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
    |                               ^^^^^^^^^
@@ -89,7 +89,7 @@ LL | fn _rpit_dyn() -> Box<dyn Tr1<As1: Copy>> { Box::new(S1) }
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:58:23
+  --> $DIR/feature-gate-associated_type_bounds.rs:55:23
    |
 LL | const _cdef: impl Tr1<As1: Copy> = S1;
    |                       ^^^^^^^^^
@@ -98,7 +98,7 @@ LL | const _cdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:64:24
+  --> $DIR/feature-gate-associated_type_bounds.rs:61:24
    |
 LL | static _sdef: impl Tr1<As1: Copy> = S1;
    |                        ^^^^^^^^^
@@ -107,7 +107,7 @@ LL | static _sdef: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0658]: associated type bounds are unstable
-  --> $DIR/feature-gate-associated_type_bounds.rs:71:21
+  --> $DIR/feature-gate-associated_type_bounds.rs:68:21
    |
 LL |     let _: impl Tr1<As1: Copy> = S1;
    |                     ^^^^^^^^^
@@ -116,25 +116,25 @@ LL |     let _: impl Tr1<As1: Copy> = S1;
    = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const type
-  --> $DIR/feature-gate-associated_type_bounds.rs:58:14
+  --> $DIR/feature-gate-associated_type_bounds.rs:55:14
    |
 LL | const _cdef: impl Tr1<As1: Copy> = S1;
    |              ^^^^^^^^^^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in const type
-  --> $DIR/feature-gate-associated_type_bounds.rs:64:15
+  --> $DIR/feature-gate-associated_type_bounds.rs:61:15
    |
 LL | static _sdef: impl Tr1<As1: Copy> = S1;
    |               ^^^^^^^^^^^^^^^^^^^
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in variable binding
-  --> $DIR/feature-gate-associated_type_bounds.rs:71:12
+  --> $DIR/feature-gate-associated_type_bounds.rs:68:12
    |
 LL |     let _: impl Tr1<As1: Copy> = S1;
    |            ^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `<<Self as _Tr3>::A as Iterator>::Item: Copy` is not satisfied
-  --> $DIR/feature-gate-associated_type_bounds.rs:15:28
+  --> $DIR/feature-gate-associated_type_bounds.rs:12:28
    |
 LL |     type A: Iterator<Item: Copy>;
    |                            ^^^^ the trait `Copy` is not implemented for `<<Self as _Tr3>::A as Iterator>::Item`
diff --git a/tests/ui/impl-trait/bound-normalization-pass.rs b/tests/ui/impl-trait/bound-normalization-pass.rs
index 51718079d2c..5613c1916c6 100644
--- a/tests/ui/impl-trait/bound-normalization-pass.rs
+++ b/tests/ui/impl-trait/bound-normalization-pass.rs
@@ -1,8 +1,6 @@
 // check-pass
 // edition:2018
 // revisions: default sa
-//[sa] compile-flags: -Z save-analysis
-//-^ To make this the regression test for #75962.
 
 #![feature(type_alias_impl_trait)]
 
diff --git a/tests/ui/issues/issue-3763.rs b/tests/ui/issues/issue-3763.rs
index 25ad6b319f9..2e72d39cb32 100644
--- a/tests/ui/issues/issue-3763.rs
+++ b/tests/ui/issues/issue-3763.rs
@@ -1,5 +1,4 @@
-// compile-flags: -Zsave-analysis
-// Also regression test for #69416
+// Regression test for #3763
 
 mod my_mod {
     pub struct MyStruct {
diff --git a/tests/ui/issues/issue-3763.stderr b/tests/ui/issues/issue-3763.stderr
index 6f4567546d0..a09c8421bb7 100644
--- a/tests/ui/issues/issue-3763.stderr
+++ b/tests/ui/issues/issue-3763.stderr
@@ -1,17 +1,17 @@
 error[E0616]: field `priv_field` of struct `MyStruct` is private
-  --> $DIR/issue-3763.rs:18:32
+  --> $DIR/issue-3763.rs:17:32
    |
 LL |     let _woohoo = (&my_struct).priv_field;
    |                                ^^^^^^^^^^ private field
 
 error[E0616]: field `priv_field` of struct `MyStruct` is private
-  --> $DIR/issue-3763.rs:21:41
+  --> $DIR/issue-3763.rs:20:41
    |
 LL |     let _woohoo = (Box::new(my_struct)).priv_field;
    |                                         ^^^^^^^^^^ private field
 
 error[E0624]: associated function `happyfun` is private
-  --> $DIR/issue-3763.rs:24:18
+  --> $DIR/issue-3763.rs:23:18
    |
 LL |         fn happyfun(&self) {}
    |         ------------------ private associated function defined here
@@ -20,7 +20,7 @@ LL |     (&my_struct).happyfun();
    |                  ^^^^^^^^ private associated function
 
 error[E0624]: associated function `happyfun` is private
-  --> $DIR/issue-3763.rs:26:27
+  --> $DIR/issue-3763.rs:25:27
    |
 LL |         fn happyfun(&self) {}
    |         ------------------ private associated function defined here
@@ -29,7 +29,7 @@ LL |     (Box::new(my_struct)).happyfun();
    |                           ^^^^^^^^ private associated function
 
 error[E0616]: field `priv_field` of struct `MyStruct` is private
-  --> $DIR/issue-3763.rs:27:26
+  --> $DIR/issue-3763.rs:26:26
    |
 LL |     let nope = my_struct.priv_field;
    |                          ^^^^^^^^^^ private field
diff --git a/tests/ui/methods/assign-to-method.rs b/tests/ui/methods/assign-to-method.rs
index 85beaee8df0..71e40759c84 100644
--- a/tests/ui/methods/assign-to-method.rs
+++ b/tests/ui/methods/assign-to-method.rs
@@ -1,5 +1,4 @@
-// compile-flags: -Zsave-analysis
-// Also regression test for #69409
+// Regression test for #69409
 
 struct Cat {
     meows : usize,
diff --git a/tests/ui/methods/assign-to-method.stderr b/tests/ui/methods/assign-to-method.stderr
index cafe9abae04..a1fc57cae21 100644
--- a/tests/ui/methods/assign-to-method.stderr
+++ b/tests/ui/methods/assign-to-method.stderr
@@ -1,5 +1,5 @@
 error[E0615]: attempted to take value of method `speak` on type `Cat`
-  --> $DIR/assign-to-method.rs:22:10
+  --> $DIR/assign-to-method.rs:21:10
    |
 LL |     nyan.speak = || println!("meow");
    |          ^^^^^ method, not a field
@@ -7,7 +7,7 @@ LL |     nyan.speak = || println!("meow");
    = help: methods are immutable and cannot be assigned to
 
 error[E0615]: attempted to take value of method `speak` on type `Cat`
-  --> $DIR/assign-to-method.rs:23:10
+  --> $DIR/assign-to-method.rs:22:10
    |
 LL |     nyan.speak += || println!("meow");
    |          ^^^^^ method, not a field
diff --git a/tests/ui/save-analysis/emit-notifications.polonius.stderr b/tests/ui/save-analysis/emit-notifications.polonius.stderr
deleted file mode 100644
index a1a1b8c63da..00000000000
--- a/tests/ui/save-analysis/emit-notifications.polonius.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.polonius/save-analysis/libemit_notifications.json","emit":"save-analysis"}
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications.polonius/libemit_notifications.rlib","emit":"link"}
diff --git a/tests/ui/save-analysis/emit-notifications.rs b/tests/ui/save-analysis/emit-notifications.rs
deleted file mode 100644
index 9179944a620..00000000000
--- a/tests/ui/save-analysis/emit-notifications.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// build-pass (FIXME(62277): could be check-pass?)
-// compile-flags: -Zsave-analysis --json artifacts
-// compile-flags: --crate-type rlib --error-format=json
-// ignore-pass
-// ^-- needed because otherwise, the .stderr file changes with --pass check
-
-pub fn foo() {}
diff --git a/tests/ui/save-analysis/emit-notifications.stderr b/tests/ui/save-analysis/emit-notifications.stderr
deleted file mode 100644
index e16f60f8b5f..00000000000
--- a/tests/ui/save-analysis/emit-notifications.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications/save-analysis/libemit_notifications.json","emit":"save-analysis"}
-{"artifact":"$TEST_BUILD_DIR/save-analysis/emit-notifications/libemit_notifications.rlib","emit":"link"}
diff --git a/tests/ui/save-analysis/issue-26459.rs b/tests/ui/save-analysis/issue-26459.rs
deleted file mode 100644
index 2ba05a0a47e..00000000000
--- a/tests/ui/save-analysis/issue-26459.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-fn main() {
-    match 'a' {
-        char{ch} => true
-        //~^ ERROR expected struct, variant or union type, found builtin type `char`
-    };
-}
diff --git a/tests/ui/save-analysis/issue-26459.stderr b/tests/ui/save-analysis/issue-26459.stderr
deleted file mode 100644
index 9f594990c6d..00000000000
--- a/tests/ui/save-analysis/issue-26459.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0574]: expected struct, variant or union type, found builtin type `char`
-  --> $DIR/issue-26459.rs:5:9
-   |
-LL |         char{ch} => true
-   |         ^^^^ not a struct, variant or union type
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0574`.
diff --git a/tests/ui/save-analysis/issue-37323.rs b/tests/ui/save-analysis/issue-37323.rs
deleted file mode 100644
index 55f5c5a9581..00000000000
--- a/tests/ui/save-analysis/issue-37323.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-
-#![feature(rustc_attrs)]
-#![allow(warnings)]
-
-#[derive(Debug)]
-struct Point {
-}
-
-struct NestedA<'a, 'b> {
-    x: &'a NestedB<'b>
-}
-
-struct NestedB<'a> {
-    x: &'a i32,
-}
-
-fn main() {
-}
diff --git a/tests/ui/save-analysis/issue-59134-0.rs b/tests/ui/save-analysis/issue-59134-0.rs
deleted file mode 100644
index a0871ca1809..00000000000
--- a/tests/ui/save-analysis/issue-59134-0.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-// Check that this doesn't ICE when processing associated const (field expr).
-
-pub fn f() {
-    trait Trait {}
-    impl dyn Trait {
-        const FLAG: u32 = bogus.field; //~ ERROR cannot find value `bogus`
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-59134-0.stderr b/tests/ui/save-analysis/issue-59134-0.stderr
deleted file mode 100644
index 4e9b2e6fdeb..00000000000
--- a/tests/ui/save-analysis/issue-59134-0.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `bogus` in this scope
-  --> $DIR/issue-59134-0.rs:8:27
-   |
-LL |         const FLAG: u32 = bogus.field;
-   |                           ^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/save-analysis/issue-59134-1.rs b/tests/ui/save-analysis/issue-59134-1.rs
deleted file mode 100644
index 3cb629777a4..00000000000
--- a/tests/ui/save-analysis/issue-59134-1.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-// Check that this doesn't ICE when processing associated const (type).
-
-fn func() {
-    trait Trait {
-        type MyType;
-        const CONST: Self::MyType = bogus.field; //~ ERROR cannot find value `bogus`
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-59134-1.stderr b/tests/ui/save-analysis/issue-59134-1.stderr
deleted file mode 100644
index bdc335eaac0..00000000000
--- a/tests/ui/save-analysis/issue-59134-1.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0425]: cannot find value `bogus` in this scope
-  --> $DIR/issue-59134-1.rs:8:37
-   |
-LL |         const CONST: Self::MyType = bogus.field;
-   |                                     ^^^^^ not found in this scope
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/save-analysis/issue-63663.rs b/tests/ui/save-analysis/issue-63663.rs
deleted file mode 100644
index 92e85884f66..00000000000
--- a/tests/ui/save-analysis/issue-63663.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-
-pub trait Trait {
-    type Assoc;
-}
-
-pub struct A;
-
-trait Generic<T> {}
-impl<T> Generic<T> for () {}
-
-// Don't ICE when resolving type paths in return type `impl Trait`
-fn assoc_in_opaque_type_bounds<U: Trait>() -> impl Generic<U::Assoc> {}
-
-// Check that this doesn't ICE when processing associated const in formal
-// argument and return type of functions defined inside function/method scope.
-pub fn func() {
-    fn _inner1<U: Trait>(_: U::Assoc) {}
-    fn _inner2<U: Trait>() -> U::Assoc { unimplemented!() }
-
-    impl A {
-        fn _inner1<U: Trait>(self, _: U::Assoc) {}
-        fn _inner2<U: Trait>(self) -> U::Assoc { unimplemented!() }
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-64659.rs b/tests/ui/save-analysis/issue-64659.rs
deleted file mode 100644
index a3d88a20377..00000000000
--- a/tests/ui/save-analysis/issue-64659.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-
-trait Trait { type Assoc; }
-
-fn main() {
-    struct Data<T: Trait> {
-        x: T::Assoc,
-    }
-}
diff --git a/tests/ui/save-analysis/issue-65411.rs b/tests/ui/save-analysis/issue-65411.rs
deleted file mode 100644
index 9e58b8da5d2..00000000000
--- a/tests/ui/save-analysis/issue-65411.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-
-trait Trait { type Assoc; }
-trait GenericTrait<T> {}
-struct Wrapper<B> { b: B }
-
-fn func() {
-    // Processing associated path in impl block definition inside a function
-    // body does not ICE
-    impl<B: Trait> GenericTrait<B::Assoc> for Wrapper<B> {}
-}
-
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-65590.rs b/tests/ui/save-analysis/issue-65590.rs
deleted file mode 100644
index 27874f8655e..00000000000
--- a/tests/ui/save-analysis/issue-65590.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// check-pass
-// compile-flags: -Zsave-analysis
-// edition:2018
-
-// Async desugaring for return types in (associated) functions introduces a
-// separate definition internally, which we need to take into account
-// (or else we ICE).
-trait Trait { type Assoc; }
-struct Struct;
-
-async fn foobar<T: Trait>() -> T::Assoc {
-    unimplemented!()
-}
-
-impl Struct {
-    async fn foo<T: Trait>(&self) -> T::Assoc {
-        unimplemented!()
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-68621.rs b/tests/ui/save-analysis/issue-68621.rs
deleted file mode 100644
index 30479580f11..00000000000
--- a/tests/ui/save-analysis/issue-68621.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-#![feature(type_alias_impl_trait)]
-
-trait Trait {}
-
-trait Service {
-    type Future: Trait;
-}
-
-struct Struct;
-
-impl Service for Struct {
-    type Future = impl Trait; //~ ERROR: unconstrained opaque type
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-68621.stderr b/tests/ui/save-analysis/issue-68621.stderr
deleted file mode 100644
index 4452ee7915b..00000000000
--- a/tests/ui/save-analysis/issue-68621.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained opaque type
-  --> $DIR/issue-68621.rs:14:19
-   |
-LL |     type Future = impl Trait;
-   |                   ^^^^^^^^^^
-   |
-   = note: `Future` must be used in combination with a concrete type within the same impl
-
-error: aborting due to previous error
-
diff --git a/tests/ui/save-analysis/issue-72267.rs b/tests/ui/save-analysis/issue-72267.rs
deleted file mode 100644
index eea0a7fea0c..00000000000
--- a/tests/ui/save-analysis/issue-72267.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// compile-flags: -Z save-analysis
-
-fn main() {
-    let _: Box<(dyn ?Sized)>;
-    //~^ ERROR `?Trait` is not permitted in trait object types
-    //~| ERROR at least one trait is required for an object type
-}
diff --git a/tests/ui/save-analysis/issue-72267.stderr b/tests/ui/save-analysis/issue-72267.stderr
deleted file mode 100644
index 76fc6c57cbc..00000000000
--- a/tests/ui/save-analysis/issue-72267.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error: `?Trait` is not permitted in trait object types
-  --> $DIR/issue-72267.rs:4:21
-   |
-LL |     let _: Box<(dyn ?Sized)>;
-   |                     ^^^^^^
-
-error[E0224]: at least one trait is required for an object type
-  --> $DIR/issue-72267.rs:4:17
-   |
-LL |     let _: Box<(dyn ?Sized)>;
-   |                 ^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0224`.
diff --git a/tests/ui/save-analysis/issue-73020.rs b/tests/ui/save-analysis/issue-73020.rs
deleted file mode 100644
index 87ce0933681..00000000000
--- a/tests/ui/save-analysis/issue-73020.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// compile-flags: -Zsave-analysis
-use {self}; //~ ERROR E0431
-
-fn main () {
-}
diff --git a/tests/ui/save-analysis/issue-73020.stderr b/tests/ui/save-analysis/issue-73020.stderr
deleted file mode 100644
index 5bb3aae9997..00000000000
--- a/tests/ui/save-analysis/issue-73020.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0431]: `self` import can only appear in an import list with a non-empty prefix
-  --> $DIR/issue-73020.rs:2:6
-   |
-LL | use {self};
-   |      ^^^^ can only appear in an import list with a non-empty prefix
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0431`.
diff --git a/tests/ui/save-analysis/issue-73022.rs b/tests/ui/save-analysis/issue-73022.rs
deleted file mode 100644
index 9ad89a319ba..00000000000
--- a/tests/ui/save-analysis/issue-73022.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// build-pass
-// compile-flags: -Zsave-analysis
-enum Enum2 {
-    Variant8 { _field: bool },
-}
-
-impl Enum2 {
-    fn new_variant8() -> Enum2 {
-        Self::Variant8 { _field: true }
-    }
-}
-
-fn main() {}
diff --git a/tests/ui/save-analysis/issue-89066.rs b/tests/ui/save-analysis/issue-89066.rs
deleted file mode 100644
index c65e2d73fad..00000000000
--- a/tests/ui/save-analysis/issue-89066.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// compile-flags: -Zsave-analysis
-
-// Check that this does not ICE.
-// Stolen from tests/ui/const-generics/generic_arg_infer/infer-arg-test.rs
-
-#![feature(generic_arg_infer)]
-
-struct All<'a, T, const N: usize> {
-  v: &'a T,
-}
-
-struct BadInfer<_>;
-//~^ ERROR expected identifier
-//~| ERROR parameter `_` is never used
-
-fn all_fn<'a, T, const N: usize>() {}
-
-fn bad_infer_fn<_>() {}
-//~^ ERROR expected identifier
-
-
-fn main() {
-  let a: All<_, _, _>;
-  //~^ ERROR this struct takes 2 generic arguments but 3 generic arguments were supplied
-  all_fn();
-  let v: [u8; _];
-  let v: [u8; 10] = [0; _];
-}
diff --git a/tests/ui/save-analysis/issue-89066.stderr b/tests/ui/save-analysis/issue-89066.stderr
deleted file mode 100644
index 5ef04936ea2..00000000000
--- a/tests/ui/save-analysis/issue-89066.stderr
+++ /dev/null
@@ -1,39 +0,0 @@
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/issue-89066.rs:12:17
-   |
-LL | struct BadInfer<_>;
-   |                 ^ expected identifier, found reserved identifier
-
-error: expected identifier, found reserved identifier `_`
-  --> $DIR/issue-89066.rs:18:17
-   |
-LL | fn bad_infer_fn<_>() {}
-   |                 ^ expected identifier, found reserved identifier
-
-error[E0392]: parameter `_` is never used
-  --> $DIR/issue-89066.rs:12:17
-   |
-LL | struct BadInfer<_>;
-   |                 ^ unused parameter
-   |
-   = help: consider removing `_`, referring to it in a field, or using a marker such as `PhantomData`
-   = help: if you intended `_` to be a const parameter, use `const _: usize` instead
-
-error[E0107]: this struct takes 2 generic arguments but 3 generic arguments were supplied
-  --> $DIR/issue-89066.rs:23:10
-   |
-LL |   let a: All<_, _, _>;
-   |          ^^^       - help: remove this generic argument
-   |          |
-   |          expected 2 generic arguments
-   |
-note: struct defined here, with 2 generic parameters: `T`, `N`
-  --> $DIR/issue-89066.rs:8:8
-   |
-LL | struct All<'a, T, const N: usize> {
-   |        ^^^     -  --------------
-
-error: aborting due to 4 previous errors
-
-Some errors have detailed explanations: E0107, E0392.
-For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/traits/alias/self-in-generics.rs b/tests/ui/traits/alias/self-in-generics.rs
index 0bb6335f91e..dcb33b7a90a 100644
--- a/tests/ui/traits/alias/self-in-generics.rs
+++ b/tests/ui/traits/alias/self-in-generics.rs
@@ -1,9 +1,5 @@
 // astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
 // This `FreshTy(0)` can leak into substs, causing ICEs in several places.
-// Using `save-analysis` triggers type-checking `f` that would be normally skipped
-// as `type_of` emitted an error.
-//
-// compile-flags: -Zsave-analysis
 
 #![feature(trait_alias)]
 
diff --git a/tests/ui/traits/alias/self-in-generics.stderr b/tests/ui/traits/alias/self-in-generics.stderr
index 110d60e6e91..80af4e5aae3 100644
--- a/tests/ui/traits/alias/self-in-generics.stderr
+++ b/tests/ui/traits/alias/self-in-generics.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait alias `SelfInput` cannot be made into an object
-  --> $DIR/self-in-generics.rs:12:19
+  --> $DIR/self-in-generics.rs:8:19
    |
 LL | pub fn f(_f: &dyn SelfInput) {}
    |                   ^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/issue-63279.rs b/tests/ui/type-alias-impl-trait/issue-63279.rs
index 97332e16d84..0e46745c65c 100644
--- a/tests/ui/type-alias-impl-trait/issue-63279.rs
+++ b/tests/ui/type-alias-impl-trait/issue-63279.rs
@@ -1,5 +1,3 @@
-// compile-flags: -Zsave-analysis
-
 #![feature(type_alias_impl_trait)]
 
 type Closure = impl FnOnce();
diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr
index 110b8d1eea4..a4f6359b904 100644
--- a/tests/ui/type-alias-impl-trait/issue-63279.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr
@@ -1,5 +1,5 @@
 error[E0277]: expected a `FnOnce<()>` closure, found `()`
-  --> $DIR/issue-63279.rs:7:11
+  --> $DIR/issue-63279.rs:5:11
    |
 LL | fn c() -> Closure {
    |           ^^^^^^^ expected an `FnOnce<()>` closure, found `()`
@@ -8,7 +8,7 @@ LL | fn c() -> Closure {
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
 
 error[E0277]: expected a `FnOnce<()>` closure, found `()`
-  --> $DIR/issue-63279.rs:9:11
+  --> $DIR/issue-63279.rs:7:11
    |
 LL |     || -> Closure { || () }
    |           ^^^^^^^ expected an `FnOnce<()>` closure, found `()`
@@ -17,26 +17,26 @@ LL |     || -> Closure { || () }
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-63279.rs:9:21
+  --> $DIR/issue-63279.rs:7:21
    |
 LL |     || -> Closure { || () }
    |                     ^^^^^ expected `()`, found closure
    |
    = note: expected unit type `()`
-                found closure `[closure@$DIR/issue-63279.rs:9:21: 9:23]`
+                found closure `[closure@$DIR/issue-63279.rs:7:21: 7:23]`
 help: use parentheses to call this closure
    |
 LL |     || -> Closure { (|| ())() }
    |                     +     +++
 
 error[E0308]: mismatched types
-  --> $DIR/issue-63279.rs:9:5
+  --> $DIR/issue-63279.rs:7:5
    |
 LL |     || -> Closure { || () }
    |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure
    |
    = note: expected unit type `()`
-                found closure `[closure@$DIR/issue-63279.rs:9:5: 9:18]`
+                found closure `[closure@$DIR/issue-63279.rs:7:5: 7:18]`
 help: use parentheses to call this closure
    |
 LL |     (|| -> Closure { || () })()
diff --git a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
index 72c22827f62..b91cbce3727 100644
--- a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
+++ b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
@@ -1,4 +1,3 @@
-// compile-flags: -Zsave-analysis
 // check-pass
 
 #![feature(type_alias_impl_trait, rustc_attrs)]