about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2024-01-05 10:57:21 -0500
committerGitHub <noreply@github.com>2024-01-05 10:57:21 -0500
commite74a0cdfeda0738097e5f261048b4293c36f41e3 (patch)
tree163307f8e0f60235884d54c2ed4fdfbc6343cfc3 /compiler
parentf361b591efb7c05b9f498f2b4eb6381d522094ce (diff)
parentaf3205421ff989c143e09b6e96413eadaa1dbc4d (diff)
downloadrust-e74a0cdfeda0738097e5f261048b4293c36f41e3.tar.gz
rust-e74a0cdfeda0738097e5f261048b4293c36f41e3.zip
Rollup merge of #119566 - Zalathar:remove-spanview, r=Swatinem,Nilstrieb
Remove `-Zdump-mir-spanview`

The `-Zdump-mir-spanview` flag was added back in #76074, as a development/debugging aid for the initial work on what would eventually become `-Cinstrument-coverage`. It causes the compiler to emit an HTML file containing a function's source code, with various spans highlighted based on the contents of MIR.

When the suggestion was made to [triage and remove unnecessary `-Z` flags (Zulip)](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/.60-Z.60.20option.20triage), I noted that this flag could potentially be worth removing, but I wanted to keep it around to see whether I found it useful for my own coverage work.

But when I actually tried to use it, I ran into various issues (e.g. it crashes on `tests/coverage/closure.rs`). If I can't trust it to work properly without a full overhaul, then instead of diving down a rabbit hole of trying to fix arcane span-handling bugs, it seems better to just remove this obscure old code entirely.

---

````@rustbot```` label +A-code-coverage
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_interface/src/tests.rs5
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs11
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs642
-rw-r--r--compiler/rustc_session/src/config.rs15
-rw-r--r--compiler/rustc_session/src/options.rs29
6 files changed, 2 insertions, 701 deletions
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 75410db1e36..f61dac28478 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -6,8 +6,8 @@ use rustc_session::config::{
     build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
     DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
     FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay,
-    LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, NextSolverConfig,
-    OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius,
+    LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, NextSolverConfig, OomStrategy,
+    Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius,
     ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
 };
 use rustc_session::lint::Level;
@@ -666,7 +666,6 @@ fn test_unstable_options_tracking_hash() {
     untracked!(dump_mir_dir, String::from("abc"));
     untracked!(dump_mir_exclude_pass_number, true);
     untracked!(dump_mir_graphviz, true);
-    untracked!(dump_mir_spanview, Some(MirSpanview::Statement));
     untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into())));
     untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json);
     untracked!(dylib_lto, true);
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 0a1a72b442a..c863c68123d 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -55,7 +55,6 @@ pub mod mono;
 pub mod patch;
 pub mod pretty;
 mod query;
-pub mod spanview;
 mod statement;
 mod syntax;
 pub mod tcx;
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 0b487eae36d..a1e5d73a0fd 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -5,7 +5,6 @@ use std::io::{self, Write as _};
 use std::path::{Path, PathBuf};
 
 use super::graphviz::write_mir_fn_graphviz;
-use super::spanview::write_mir_fn_spanview;
 use rustc_ast::InlineAsmTemplatePiece;
 use rustc_middle::mir::interpret::{
     alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer,
@@ -141,16 +140,6 @@ fn dump_matched_mir_node<'tcx, F>(
             write_mir_fn_graphviz(tcx, body, false, &mut file)?;
         };
     }
-
-    if let Some(spanview) = tcx.sess.opts.unstable_opts.dump_mir_spanview {
-        let _: io::Result<()> = try {
-            let file_basename = dump_file_basename(tcx, pass_num, pass_name, disambiguator, body);
-            let mut file = create_dump_file_with_basename(tcx, &file_basename, "html")?;
-            if body.source.def_id().is_local() {
-                write_mir_fn_spanview(tcx, body, spanview, &file_basename, &mut file)?;
-            }
-        };
-    }
 }
 
 /// Returns the file basename portion (without extension) of a filename path
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
deleted file mode 100644
index cb9fc0d37f2..00000000000
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ /dev/null
@@ -1,642 +0,0 @@
-use rustc_middle::hir;
-use rustc_middle::mir::*;
-use rustc_session::config::MirSpanview;
-use rustc_span::{BytePos, Pos};
-
-use std::cmp;
-use std::io::{self, Write};
-
-pub const TOOLTIP_INDENT: &str = "    ";
-
-const CARET: char = '\u{2038}'; // Unicode `CARET`
-const ANNOTATION_LEFT_BRACKET: char = '\u{298a}'; // Unicode `Z NOTATION RIGHT BINDING BRACKET`
-const ANNOTATION_RIGHT_BRACKET: char = '\u{2989}'; // Unicode `Z NOTATION LEFT BINDING BRACKET`
-const NEW_LINE_SPAN: &str = "</span>\n<span class=\"line\">";
-const HEADER: &str = r#"<!DOCTYPE html>
-<html lang="en">
-<head>
-<meta charset="utf-8">"#;
-const START_BODY: &str = r#"</head>
-<body>"#;
-const FOOTER: &str = r#"</body>
-</html>"#;
-
-const STYLE_SECTION: &str = r#"<style>
-    .line {
-        counter-increment: line;
-    }
-    .line:before {
-        content: counter(line) ": ";
-        font-family: Menlo, Monaco, monospace;
-        font-style: italic;
-        width: 3.8em;
-        display: inline-block;
-        text-align: right;
-        filter: opacity(50%);
-        -webkit-user-select: none;
-    }
-    .code {
-        color: #dddddd;
-        background-color: #222222;
-        font-family: Menlo, Monaco, monospace;
-        line-height: 1.4em;
-        border-bottom: 2px solid #222222;
-        white-space: pre;
-        display: inline-block;
-    }
-    .odd {
-        background-color: #55bbff;
-        color: #223311;
-    }
-    .even {
-        background-color: #ee7756;
-        color: #551133;
-    }
-    .code {
-        --index: calc(var(--layer) - 1);
-        padding-top: calc(var(--index) * 0.15em);
-        filter:
-            hue-rotate(calc(var(--index) * 25deg))
-            saturate(calc(100% - (var(--index) * 2%)))
-            brightness(calc(100% - (var(--index) * 1.5%)));
-    }
-    .annotation {
-        color: #4444ff;
-        font-family: monospace;
-        font-style: italic;
-        display: none;
-        -webkit-user-select: none;
-    }
-    body:active .annotation {
-        /* requires holding mouse down anywhere on the page */
-        display: inline-block;
-    }
-    span:hover .annotation {
-        /* requires hover over a span ONLY on its first line */
-        display: inline-block;
-    }
-</style>"#;
-
-/// Metadata to highlight the span of a MIR BasicBlock, Statement, or Terminator.
-#[derive(Clone, Debug)]
-pub struct SpanViewable {
-    pub bb: BasicBlock,
-    pub span: Span,
-    pub id: String,
-    pub tooltip: String,
-}
-
-/// Write a spanview HTML+CSS file to analyze MIR element spans.
-pub fn write_mir_fn_spanview<'tcx, W>(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    spanview: MirSpanview,
-    title: &str,
-    w: &mut W,
-) -> io::Result<()>
-where
-    W: Write,
-{
-    let def_id = body.source.def_id();
-    let hir_body = hir_body(tcx, def_id);
-    if hir_body.is_none() {
-        return Ok(());
-    }
-    let body_span = hir_body.unwrap().value.span;
-    let mut span_viewables = Vec::new();
-    for (bb, data) in body.basic_blocks.iter_enumerated() {
-        match spanview {
-            MirSpanview::Statement => {
-                for (i, statement) in data.statements.iter().enumerate() {
-                    if let Some(span_viewable) =
-                        statement_span_viewable(tcx, body_span, bb, i, statement)
-                    {
-                        span_viewables.push(span_viewable);
-                    }
-                }
-                if let Some(span_viewable) = terminator_span_viewable(tcx, body_span, bb, data) {
-                    span_viewables.push(span_viewable);
-                }
-            }
-            MirSpanview::Terminator => {
-                if let Some(span_viewable) = terminator_span_viewable(tcx, body_span, bb, data) {
-                    span_viewables.push(span_viewable);
-                }
-            }
-            MirSpanview::Block => {
-                if let Some(span_viewable) = block_span_viewable(tcx, body_span, bb, data) {
-                    span_viewables.push(span_viewable);
-                }
-            }
-        }
-    }
-    write_document(tcx, fn_span(tcx, def_id), span_viewables, title, w)?;
-    Ok(())
-}
-
-/// Generate a spanview HTML+CSS document for the given local function `def_id`, and a pre-generated
-/// list `SpanViewable`s.
-pub fn write_document<'tcx, W>(
-    tcx: TyCtxt<'tcx>,
-    spanview_span: Span,
-    mut span_viewables: Vec<SpanViewable>,
-    title: &str,
-    w: &mut W,
-) -> io::Result<()>
-where
-    W: Write,
-{
-    let mut from_pos = spanview_span.lo();
-    let end_pos = spanview_span.hi();
-    let source_map = tcx.sess.source_map();
-    let start = source_map.lookup_char_pos(from_pos);
-    let indent_to_initial_start_col = " ".repeat(start.col.to_usize());
-    debug!(
-        "spanview_span={:?}; source is:\n{}{}",
-        spanview_span,
-        indent_to_initial_start_col,
-        source_map.span_to_snippet(spanview_span).expect("function should have printable source")
-    );
-    writeln!(w, "{HEADER}")?;
-    writeln!(w, "<title>{title}</title>")?;
-    writeln!(w, "{STYLE_SECTION}")?;
-    writeln!(w, "{START_BODY}")?;
-    write!(
-        w,
-        r#"<div class="code" style="counter-reset: line {}"><span class="line">{}"#,
-        start.line - 1,
-        indent_to_initial_start_col,
-    )?;
-    span_viewables.sort_unstable_by(|a, b| {
-        let a = a.span;
-        let b = b.span;
-        if a.lo() == b.lo() {
-            // Sort hi() in reverse order so shorter spans are attempted after longer spans.
-            // This should give shorter spans a higher "layer", so they are not covered by
-            // the longer spans.
-            b.hi().partial_cmp(&a.hi())
-        } else {
-            a.lo().partial_cmp(&b.lo())
-        }
-        .unwrap()
-    });
-    let mut ordered_viewables = &span_viewables[..];
-    const LOWEST_VIEWABLE_LAYER: usize = 1;
-    let mut alt = false;
-    while ordered_viewables.len() > 0 {
-        debug!(
-            "calling write_next_viewable with from_pos={}, end_pos={}, and viewables len={}",
-            from_pos.to_usize(),
-            end_pos.to_usize(),
-            ordered_viewables.len()
-        );
-        let curr_id = &ordered_viewables[0].id;
-        let (next_from_pos, next_ordered_viewables) = write_next_viewable_with_overlaps(
-            tcx,
-            from_pos,
-            end_pos,
-            ordered_viewables,
-            alt,
-            LOWEST_VIEWABLE_LAYER,
-            w,
-        )?;
-        debug!(
-            "DONE calling write_next_viewable, with new from_pos={}, \
-             and remaining viewables len={}",
-            next_from_pos.to_usize(),
-            next_ordered_viewables.len()
-        );
-        assert!(
-            from_pos != next_from_pos || ordered_viewables.len() != next_ordered_viewables.len(),
-            "write_next_viewable_with_overlaps() must make a state change"
-        );
-        from_pos = next_from_pos;
-        if next_ordered_viewables.len() != ordered_viewables.len() {
-            ordered_viewables = next_ordered_viewables;
-            if let Some(next_ordered_viewable) = ordered_viewables.first() {
-                if &next_ordered_viewable.id != curr_id {
-                    alt = !alt;
-                }
-            }
-        }
-    }
-    if from_pos < end_pos {
-        write_coverage_gap(tcx, from_pos, end_pos, w)?;
-    }
-    writeln!(w, r#"</span></div>"#)?;
-    writeln!(w, "{FOOTER}")?;
-    Ok(())
-}
-
-/// Format a string showing the start line and column, and end line and column within a file.
-pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String {
-    let source_map = tcx.sess.source_map();
-    let start = source_map.lookup_char_pos(span.lo());
-    let end = source_map.lookup_char_pos(span.hi());
-    format!("{}:{}-{}:{}", start.line, start.col.to_usize() + 1, end.line, end.col.to_usize() + 1)
-}
-
-fn statement_span_viewable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body_span: Span,
-    bb: BasicBlock,
-    i: usize,
-    statement: &Statement<'tcx>,
-) -> Option<SpanViewable> {
-    let span = statement.source_info.span;
-    if !body_span.contains(span) {
-        return None;
-    }
-    let id = format!("{}[{}]", bb.index(), i);
-    let tooltip = tooltip(tcx, &id, span, vec![statement.clone()], &None);
-    Some(SpanViewable { bb, span, id, tooltip })
-}
-
-fn terminator_span_viewable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body_span: Span,
-    bb: BasicBlock,
-    data: &BasicBlockData<'tcx>,
-) -> Option<SpanViewable> {
-    let term = data.terminator();
-    let span = term.source_info.span;
-    if !body_span.contains(span) {
-        return None;
-    }
-    let id = format!("{}:{}", bb.index(), term.kind.name());
-    let tooltip = tooltip(tcx, &id, span, vec![], &data.terminator);
-    Some(SpanViewable { bb, span, id, tooltip })
-}
-
-fn block_span_viewable<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body_span: Span,
-    bb: BasicBlock,
-    data: &BasicBlockData<'tcx>,
-) -> Option<SpanViewable> {
-    let span = compute_block_span(data, body_span);
-    if !body_span.contains(span) {
-        return None;
-    }
-    let id = format!("{}", bb.index());
-    let tooltip = tooltip(tcx, &id, span, data.statements.clone(), &data.terminator);
-    Some(SpanViewable { bb, span, id, tooltip })
-}
-
-fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span {
-    let mut span = data.terminator().source_info.span;
-    for statement_span in data.statements.iter().map(|statement| statement.source_info.span) {
-        // Only combine Spans from the root context, and within the function's body_span.
-        if statement_span.ctxt().is_root() && body_span.contains(statement_span) {
-            span = span.to(statement_span);
-        }
-    }
-    span
-}
-
-/// Recursively process each ordered span. Spans that overlap will have progressively varying
-/// styles, such as increased padding for each overlap. Non-overlapping adjacent spans will
-/// have alternating style choices, to help distinguish between them if, visually adjacent.
-/// The `layer` is incremented for each overlap, and the `alt` bool alternates between true
-/// and false, for each adjacent non-overlapping span. Source code between the spans (code
-/// that is not in any coverage region) has neutral styling.
-fn write_next_viewable_with_overlaps<'tcx, 'b, W>(
-    tcx: TyCtxt<'tcx>,
-    mut from_pos: BytePos,
-    mut to_pos: BytePos,
-    ordered_viewables: &'b [SpanViewable],
-    alt: bool,
-    layer: usize,
-    w: &mut W,
-) -> io::Result<(BytePos, &'b [SpanViewable])>
-where
-    W: Write,
-{
-    let debug_indent = "  ".repeat(layer);
-    let (viewable, mut remaining_viewables) =
-        ordered_viewables.split_first().expect("ordered_viewables should have some");
-
-    if from_pos < viewable.span.lo() {
-        debug!(
-            "{}advance from_pos to next SpanViewable (from from_pos={} to viewable.span.lo()={} \
-             of {:?}), with to_pos={}",
-            debug_indent,
-            from_pos.to_usize(),
-            viewable.span.lo().to_usize(),
-            viewable.span,
-            to_pos.to_usize()
-        );
-        let hi = cmp::min(viewable.span.lo(), to_pos);
-        write_coverage_gap(tcx, from_pos, hi, w)?;
-        from_pos = hi;
-        if from_pos < viewable.span.lo() {
-            debug!(
-                "{}EARLY RETURN: stopped before getting to next SpanViewable, at {}",
-                debug_indent,
-                from_pos.to_usize()
-            );
-            return Ok((from_pos, ordered_viewables));
-        }
-    }
-
-    if from_pos < viewable.span.hi() {
-        // Set to_pos to the end of this `viewable` to ensure the recursive calls stop writing
-        // with room to print the tail.
-        to_pos = cmp::min(viewable.span.hi(), to_pos);
-        debug!(
-            "{}update to_pos (if not closer) to viewable.span.hi()={}; to_pos is now {}",
-            debug_indent,
-            viewable.span.hi().to_usize(),
-            to_pos.to_usize()
-        );
-    }
-
-    let mut subalt = false;
-    while remaining_viewables.len() > 0 && remaining_viewables[0].span.overlaps(viewable.span) {
-        let overlapping_viewable = &remaining_viewables[0];
-        debug!("{}overlapping_viewable.span={:?}", debug_indent, overlapping_viewable.span);
-
-        let span =
-            trim_span(viewable.span, from_pos, cmp::min(overlapping_viewable.span.lo(), to_pos));
-        let mut some_html_snippet = if from_pos <= viewable.span.hi() || viewable.span.is_empty() {
-            // `viewable` is not yet fully rendered, so start writing the span, up to either the
-            // `to_pos` or the next `overlapping_viewable`, whichever comes first.
-            debug!(
-                "{}make html_snippet (may not write it if early exit) for partial span {:?} \
-                 of viewable.span {:?}",
-                debug_indent, span, viewable.span
-            );
-            from_pos = span.hi();
-            make_html_snippet(tcx, span, Some(viewable))
-        } else {
-            None
-        };
-
-        // Defer writing the HTML snippet (until after early return checks) ONLY for empty spans.
-        // An empty Span with Some(html_snippet) is probably a tail marker. If there is an early
-        // exit, there should be another opportunity to write the tail marker.
-        if !span.is_empty() {
-            if let Some(ref html_snippet) = some_html_snippet {
-                debug!(
-                    "{}write html_snippet for that partial span of viewable.span {:?}",
-                    debug_indent, viewable.span
-                );
-                write_span(html_snippet, &viewable.tooltip, alt, layer, w)?;
-            }
-            some_html_snippet = None;
-        }
-
-        if from_pos < overlapping_viewable.span.lo() {
-            debug!(
-                "{}EARLY RETURN: from_pos={} has not yet reached the \
-                 overlapping_viewable.span {:?}",
-                debug_indent,
-                from_pos.to_usize(),
-                overlapping_viewable.span
-            );
-            // must have reached `to_pos` before reaching the start of the
-            // `overlapping_viewable.span`
-            return Ok((from_pos, ordered_viewables));
-        }
-
-        if from_pos == to_pos
-            && !(from_pos == overlapping_viewable.span.lo() && overlapping_viewable.span.is_empty())
-        {
-            debug!(
-                "{}EARLY RETURN: from_pos=to_pos={} and overlapping_viewable.span {:?} is not \
-                 empty, or not from_pos",
-                debug_indent,
-                to_pos.to_usize(),
-                overlapping_viewable.span
-            );
-            // `to_pos` must have occurred before the overlapping viewable. Return
-            // `ordered_viewables` so we can continue rendering the `viewable`, from after the
-            // `to_pos`.
-            return Ok((from_pos, ordered_viewables));
-        }
-
-        if let Some(ref html_snippet) = some_html_snippet {
-            debug!(
-                "{}write html_snippet for that partial span of viewable.span {:?}",
-                debug_indent, viewable.span
-            );
-            write_span(html_snippet, &viewable.tooltip, alt, layer, w)?;
-        }
-
-        debug!(
-            "{}recursively calling write_next_viewable with from_pos={}, to_pos={}, \
-             and viewables len={}",
-            debug_indent,
-            from_pos.to_usize(),
-            to_pos.to_usize(),
-            remaining_viewables.len()
-        );
-        // Write the overlaps (and the overlaps' overlaps, if any) up to `to_pos`.
-        let curr_id = &remaining_viewables[0].id;
-        let (next_from_pos, next_remaining_viewables) = write_next_viewable_with_overlaps(
-            tcx,
-            from_pos,
-            to_pos,
-            remaining_viewables,
-            subalt,
-            layer + 1,
-            w,
-        )?;
-        debug!(
-            "{}DONE recursively calling write_next_viewable, with new from_pos={}, and remaining \
-             viewables len={}",
-            debug_indent,
-            next_from_pos.to_usize(),
-            next_remaining_viewables.len()
-        );
-        assert!(
-            from_pos != next_from_pos
-                || remaining_viewables.len() != next_remaining_viewables.len(),
-            "write_next_viewable_with_overlaps() must make a state change"
-        );
-        from_pos = next_from_pos;
-        if next_remaining_viewables.len() != remaining_viewables.len() {
-            remaining_viewables = next_remaining_viewables;
-            if let Some(next_ordered_viewable) = remaining_viewables.first() {
-                if &next_ordered_viewable.id != curr_id {
-                    subalt = !subalt;
-                }
-            }
-        }
-    }
-    if from_pos <= viewable.span.hi() {
-        let span = trim_span(viewable.span, from_pos, to_pos);
-        debug!(
-            "{}After overlaps, writing (end span?) {:?} of viewable.span {:?}",
-            debug_indent, span, viewable.span
-        );
-        if let Some(ref html_snippet) = make_html_snippet(tcx, span, Some(viewable)) {
-            from_pos = span.hi();
-            write_span(html_snippet, &viewable.tooltip, alt, layer, w)?;
-        }
-    }
-    debug!("{}RETURN: No more overlap", debug_indent);
-    Ok((
-        from_pos,
-        if from_pos < viewable.span.hi() { ordered_viewables } else { remaining_viewables },
-    ))
-}
-
-#[inline(always)]
-fn write_coverage_gap<W>(tcx: TyCtxt<'_>, lo: BytePos, hi: BytePos, w: &mut W) -> io::Result<()>
-where
-    W: Write,
-{
-    let span = Span::with_root_ctxt(lo, hi);
-    if let Some(ref html_snippet) = make_html_snippet(tcx, span, None) {
-        write_span(html_snippet, "", false, 0, w)
-    } else {
-        Ok(())
-    }
-}
-
-fn write_span<W>(
-    html_snippet: &str,
-    tooltip: &str,
-    alt: bool,
-    layer: usize,
-    w: &mut W,
-) -> io::Result<()>
-where
-    W: Write,
-{
-    let maybe_alt_class = if layer > 0 { if alt { " odd" } else { " even" } } else { "" };
-    let maybe_title_attr = if !tooltip.is_empty() {
-        format!(" title=\"{}\"", escape_attr(tooltip))
-    } else {
-        "".to_owned()
-    };
-    if layer == 1 {
-        write!(w, "<span>")?;
-    }
-    for (i, line) in html_snippet.lines().enumerate() {
-        if i > 0 {
-            write!(w, "{NEW_LINE_SPAN}")?;
-        }
-        write!(
-            w,
-            r#"<span class="code{maybe_alt_class}" style="--layer: {layer}"{maybe_title_attr}>{line}</span>"#
-        )?;
-    }
-    // Check for and translate trailing newlines, because `str::lines()` ignores them
-    if html_snippet.ends_with('\n') {
-        write!(w, "{NEW_LINE_SPAN}")?;
-    }
-    if layer == 1 {
-        write!(w, "</span>")?;
-    }
-    Ok(())
-}
-
-fn make_html_snippet(
-    tcx: TyCtxt<'_>,
-    span: Span,
-    some_viewable: Option<&SpanViewable>,
-) -> Option<String> {
-    let source_map = tcx.sess.source_map();
-    let snippet = source_map
-        .span_to_snippet(span)
-        .unwrap_or_else(|err| bug!("span_to_snippet error for span {:?}: {:?}", span, err));
-    let html_snippet = if let Some(viewable) = some_viewable {
-        let is_head = span.lo() == viewable.span.lo();
-        let is_tail = span.hi() == viewable.span.hi();
-        let mut labeled_snippet = if is_head {
-            format!(r#"<span class="annotation">{}{}</span>"#, viewable.id, ANNOTATION_LEFT_BRACKET)
-        } else {
-            "".to_owned()
-        };
-        if span.is_empty() {
-            if is_head && is_tail {
-                labeled_snippet.push(CARET);
-            }
-        } else {
-            labeled_snippet.push_str(&escape_html(&snippet));
-        };
-        if is_tail {
-            labeled_snippet.push_str(&format!(
-                r#"<span class="annotation">{}{}</span>"#,
-                ANNOTATION_RIGHT_BRACKET, viewable.id
-            ));
-        }
-        labeled_snippet
-    } else {
-        escape_html(&snippet)
-    };
-    if html_snippet.is_empty() { None } else { Some(html_snippet) }
-}
-
-fn tooltip<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    spanview_id: &str,
-    span: Span,
-    statements: Vec<Statement<'tcx>>,
-    terminator: &Option<Terminator<'tcx>>,
-) -> String {
-    let source_map = tcx.sess.source_map();
-    let mut text = Vec::new();
-    text.push(format!("{}: {}:", spanview_id, &source_map.span_to_embeddable_string(span)));
-    for statement in statements {
-        let source_range = source_range_no_file(tcx, statement.source_info.span);
-        text.push(format!(
-            "\n{}{}: {}: {:?}",
-            TOOLTIP_INDENT,
-            source_range,
-            statement.kind.name(),
-            statement
-        ));
-    }
-    if let Some(term) = terminator {
-        let source_range = source_range_no_file(tcx, term.source_info.span);
-        text.push(format!(
-            "\n{}{}: {}: {:?}",
-            TOOLTIP_INDENT,
-            source_range,
-            term.kind.name(),
-            term.kind
-        ));
-    }
-    text.join("")
-}
-
-fn trim_span(span: Span, from_pos: BytePos, to_pos: BytePos) -> Span {
-    trim_span_hi(trim_span_lo(span, from_pos), to_pos)
-}
-
-fn trim_span_lo(span: Span, from_pos: BytePos) -> Span {
-    if from_pos <= span.lo() { span } else { span.with_lo(cmp::min(span.hi(), from_pos)) }
-}
-
-fn trim_span_hi(span: Span, to_pos: BytePos) -> Span {
-    if to_pos >= span.hi() { span } else { span.with_hi(cmp::max(span.lo(), to_pos)) }
-}
-
-fn fn_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
-    let fn_decl_span = tcx.def_span(def_id);
-    if let Some(body_span) = hir_body(tcx, def_id).map(|hir_body| hir_body.value.span) {
-        if fn_decl_span.eq_ctxt(body_span) { fn_decl_span.to(body_span) } else { body_span }
-    } else {
-        fn_decl_span
-    }
-}
-
-fn hir_body(tcx: TyCtxt<'_>, def_id: DefId) -> Option<&rustc_hir::Body<'_>> {
-    let hir_node = tcx.hir().get_if_local(def_id).expect("expected DefId is local");
-    hir::map::associated_body(hir_node).map(|(_, fn_body_id)| tcx.hir().body(fn_body_id))
-}
-
-fn escape_html(s: &str) -> String {
-    s.replace('&', "&amp;").replace('<', "&lt;").replace('>', "&gt;")
-}
-
-fn escape_attr(s: &str) -> String {
-    s.replace('&', "&amp;")
-        .replace('\"', "&quot;")
-        .replace('\'', "&#39;")
-        .replace('<', "&lt;")
-        .replace('>', "&gt;")
-}
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 89508c77639..770c85cd0fc 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -125,21 +125,6 @@ pub enum LtoCli {
     Unspecified,
 }
 
-/// The different settings that the `-Z dump_mir_spanview` flag can have. `Statement` generates a
-/// document highlighting each span of every statement (including terminators). `Terminator` and
-/// `Block` highlight a single span per `BasicBlock`: the span of the block's `Terminator`, or a
-/// computed span for the block, representing the entire range, covering the block's terminator and
-/// all of its statements.
-#[derive(Clone, Copy, PartialEq, Hash, Debug)]
-pub enum MirSpanview {
-    /// Default `-Z dump_mir_spanview` or `-Z dump_mir_spanview=statement`
-    Statement,
-    /// `-Z dump_mir_spanview=terminator`
-    Terminator,
-    /// `-Z dump_mir_spanview=block`
-    Block,
-}
-
 /// The different settings that the `-C instrument-coverage` flag can have.
 ///
 /// Coverage instrumentation now supports combining `-C instrument-coverage`
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 0b0b67ef890..3584dc6cfb7 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -391,7 +391,6 @@ mod desc {
     pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`";
     pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
     pub const parse_optimization_fuel: &str = "crate=integer";
-    pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`";
     pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
     pub const parse_instrument_coverage: &str =
         "`all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off`";
@@ -866,29 +865,6 @@ mod parse {
         }
     }
 
-    pub(crate) fn parse_mir_spanview(slot: &mut Option<MirSpanview>, v: Option<&str>) -> bool {
-        if v.is_some() {
-            let mut bool_arg = None;
-            if parse_opt_bool(&mut bool_arg, v) {
-                *slot = bool_arg.unwrap().then_some(MirSpanview::Statement);
-                return true;
-            }
-        }
-
-        let Some(v) = v else {
-            *slot = Some(MirSpanview::Statement);
-            return true;
-        };
-
-        *slot = Some(match v.trim_end_matches('s') {
-            "statement" | "stmt" => MirSpanview::Statement,
-            "terminator" | "term" => MirSpanview::Terminator,
-            "block" | "basicblock" => MirSpanview::Block,
-            _ => return false,
-        });
-        true
-    }
-
     pub(crate) fn parse_time_passes_format(slot: &mut TimePassesFormat, v: Option<&str>) -> bool {
         match v {
             None => true,
@@ -1601,11 +1577,6 @@ options! {
         "exclude the pass number when dumping MIR (used in tests) (default: no)"),
     dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
         "in addition to `.mir` files, create graphviz `.dot` files (default: no)"),
-    dump_mir_spanview: Option<MirSpanview> = (None, parse_mir_spanview, [UNTRACKED],
-        "in addition to `.mir` files, create `.html` files to view spans for \
-        all `statement`s (including terminators), only `terminator` spans, or \
-        computed `block` spans (one span encompassing a block's terminator and \
-        all statements)."),
     dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
         parse_switch_with_opt_path, [UNTRACKED],
         "output statistics about monomorphization collection"),