diff --git a/Cargo.lock b/Cargo.lock
index 375e567222965..7e0448a152f4d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -48,6 +48,12 @@ dependencies = [
  "ansi_term",
 ]
 
+[[package]]
+name = "annotate-snippets"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5"
+
 [[package]]
 name = "ansi_term"
 version = "0.11.0"
@@ -3277,7 +3283,7 @@ version = "654.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "908e1ea187c6bb368af4ba6db980001e920515e67371ddc4086e749baabe6080"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.6.1",
  "atty",
  "log",
  "rustc-ap-rustc_data_structures",
@@ -3761,7 +3767,7 @@ version = "0.0.0"
 name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.8.0",
  "atty",
  "log",
  "rustc_data_structures",
@@ -4408,7 +4414,7 @@ dependencies = [
 name = "rustfmt-nightly"
 version = "1.4.14"
 dependencies = [
- "annotate-snippets",
+ "annotate-snippets 0.6.1",
  "bytecount",
  "cargo_metadata 0.8.0",
  "derive-new",
diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml
index b8340b1a1df6a..5882a6855b673 100644
--- a/src/librustc_errors/Cargo.toml
+++ b/src/librustc_errors/Cargo.toml
@@ -17,7 +17,7 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 unicode-width = "0.1.4"
 atty = "0.2"
 termcolor = "1.0"
-annotate-snippets = "0.6.1"
+annotate-snippets = "0.8.0"
 termize = "0.1.1"
 
 [target.'cfg(windows)'.dependencies]
diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs
index d83175694f407..5b47364e714e9 100644
--- a/src/librustc_errors/annotate_snippet_emitter_writer.rs
+++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs
@@ -8,12 +8,11 @@
 use crate::emitter::FileWithAnnotatedLines;
 use crate::snippet::Line;
 use crate::{CodeSuggestion, Diagnostic, DiagnosticId, Emitter, Level, SubDiagnostic};
-use annotate_snippets::display_list::DisplayList;
-use annotate_snippets::formatter::DisplayListFormatter;
+use annotate_snippets::display_list::{DisplayList, FormatOptions};
 use annotate_snippets::snippet::*;
 use rustc_data_structures::sync::Lrc;
 use rustc_span::source_map::SourceMap;
-use rustc_span::{Loc, MultiSpan, SourceFile};
+use rustc_span::{MultiSpan, SourceFile};
 
 /// Generates diagnostics using annotate-snippet
 pub struct AnnotateSnippetEmitterWriter {
@@ -59,112 +58,20 @@ impl Emitter for AnnotateSnippetEmitterWriter {
     }
 }
 
-/// Collects all the data needed to generate the data structures needed for the
-/// `annotate-snippets` library.
-struct DiagnosticConverter<'a> {
-    source_map: Option<Lrc<SourceMap>>,
-    level: Level,
-    message: String,
-    code: Option<DiagnosticId>,
-    msp: MultiSpan,
-    #[allow(dead_code)]
-    children: &'a [SubDiagnostic],
-    #[allow(dead_code)]
-    suggestions: &'a [CodeSuggestion],
+/// Provides the source string for the given `line` of `file`
+fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
+    file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or_default()
 }
 
-impl<'a> DiagnosticConverter<'a> {
-    /// Turns rustc Diagnostic information into a `annotate_snippets::snippet::Snippet`.
-    fn to_annotation_snippet(&self) -> Option<Snippet> {
-        if let Some(source_map) = &self.source_map {
-            // Make sure our primary file comes first
-            let primary_lo = if let Some(ref primary_span) = self.msp.primary_span().as_ref() {
-                source_map.lookup_char_pos(primary_span.lo())
-            } else {
-                // FIXME(#59346): Not sure when this is the case and what
-                // should be done if it happens
-                return None;
-            };
-            let annotated_files =
-                FileWithAnnotatedLines::collect_annotations(&self.msp, &self.source_map);
-            let slices = self.slices_for_files(annotated_files, primary_lo);
-
-            Some(Snippet {
-                title: Some(Annotation {
-                    label: Some(self.message.to_string()),
-                    id: self.code.clone().map(|c| match c {
-                        DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val,
-                    }),
-                    annotation_type: Self::annotation_type_for_level(self.level),
-                }),
-                footer: vec![],
-                slices,
-            })
-        } else {
-            // FIXME(#59346): Is it ok to return None if there's no source_map?
-            None
-        }
-    }
-
-    fn slices_for_files(
-        &self,
-        annotated_files: Vec<FileWithAnnotatedLines>,
-        primary_lo: Loc,
-    ) -> Vec<Slice> {
-        // FIXME(#64205): Provide a test case where `annotated_files` is > 1
-        annotated_files
-            .iter()
-            .flat_map(|annotated_file| {
-                annotated_file
-                    .lines
-                    .iter()
-                    .map(|line| {
-                        let line_source = Self::source_string(annotated_file.file.clone(), &line);
-                        Slice {
-                            source: line_source,
-                            line_start: line.line_index,
-                            origin: Some(primary_lo.file.name.to_string()),
-                            // FIXME(#59346): Not really sure when `fold` should be true or false
-                            fold: false,
-                            annotations: line
-                                .annotations
-                                .iter()
-                                .map(|a| self.annotation_to_source_annotation(a.clone()))
-                                .collect(),
-                        }
-                    })
-                    .collect::<Vec<Slice>>()
-            })
-            .collect::<Vec<Slice>>()
-    }
-
-    /// Turns a `crate::snippet::Annotation` into a `SourceAnnotation`
-    fn annotation_to_source_annotation(
-        &self,
-        annotation: crate::snippet::Annotation,
-    ) -> SourceAnnotation {
-        SourceAnnotation {
-            range: (annotation.start_col, annotation.end_col),
-            label: annotation.label.unwrap_or("".to_string()),
-            annotation_type: Self::annotation_type_for_level(self.level),
-        }
-    }
-
-    /// Provides the source string for the given `line` of `file`
-    fn source_string(file: Lrc<SourceFile>, line: &Line) -> String {
-        file.get_line(line.line_index - 1).map(|a| a.to_string()).unwrap_or(String::new())
-    }
-
-    /// Maps `Diagnostic::Level` to `snippet::AnnotationType`
-    fn annotation_type_for_level(level: Level) -> AnnotationType {
-        match level {
-            Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
-            Level::Warning => AnnotationType::Warning,
-            Level::Note => AnnotationType::Note,
-            Level::Help => AnnotationType::Help,
-            // FIXME(#59346): Not sure how to map these two levels
-            Level::Cancelled | Level::FailureNote => AnnotationType::Error,
-        }
+/// Maps `Diagnostic::Level` to `snippet::AnnotationType`
+fn annotation_type_for_level(level: Level) -> AnnotationType {
+    match level {
+        Level::Bug | Level::Fatal | Level::Error => AnnotationType::Error,
+        Level::Warning => AnnotationType::Warning,
+        Level::Note => AnnotationType::Note,
+        Level::Help => AnnotationType::Help,
+        // FIXME(#59346): Not sure how to map these two levels
+        Level::Cancelled | Level::FailureNote => AnnotationType::Error,
     }
 }
 
@@ -191,25 +98,87 @@ impl AnnotateSnippetEmitterWriter {
         message: String,
         code: &Option<DiagnosticId>,
         msp: &MultiSpan,
-        children: &[SubDiagnostic],
-        suggestions: &[CodeSuggestion],
+        _children: &[SubDiagnostic],
+        _suggestions: &[CodeSuggestion],
     ) {
-        let converter = DiagnosticConverter {
-            source_map: self.source_map.clone(),
-            level: *level,
-            message,
-            code: code.clone(),
-            msp: msp.clone(),
-            children,
-            suggestions,
-        };
-        if let Some(snippet) = converter.to_annotation_snippet() {
-            let dl = DisplayList::from(snippet);
-            let dlf = DisplayListFormatter::new(true, self.ui_testing);
+        if let Some(source_map) = &self.source_map {
+            // Make sure our primary file comes first
+            let primary_lo = if let Some(ref primary_span) = msp.primary_span().as_ref() {
+                if primary_span.is_dummy() {
+                    // FIXME(#59346): Not sure when this is the case and what
+                    // should be done if it happens
+                    return;
+                } else {
+                    source_map.lookup_char_pos(primary_span.lo())
+                }
+            } else {
+                // FIXME(#59346): Not sure when this is the case and what
+                // should be done if it happens
+                return;
+            };
+            let mut annotated_files =
+                FileWithAnnotatedLines::collect_annotations(msp, &self.source_map);
+            if let Ok(pos) =
+                annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name))
+            {
+                annotated_files.swap(0, pos);
+            }
+            // owned: line source, line index, annotations
+            type Owned = (String, usize, Vec<crate::snippet::Annotation>);
+            let origin = primary_lo.file.name.to_string();
+            let annotated_files: Vec<Owned> = annotated_files
+                .into_iter()
+                .flat_map(|annotated_file| {
+                    let file = annotated_file.file;
+                    annotated_file
+                        .lines
+                        .into_iter()
+                        .map(|line| {
+                            (source_string(file.clone(), &line), line.line_index, line.annotations)
+                        })
+                        .collect::<Vec<Owned>>()
+                })
+                .collect();
+            let snippet = Snippet {
+                title: Some(Annotation {
+                    label: Some(&message),
+                    id: code.as_ref().map(|c| match c {
+                        DiagnosticId::Error(val) | DiagnosticId::Lint(val) => val.as_str(),
+                    }),
+                    annotation_type: annotation_type_for_level(*level),
+                }),
+                footer: vec![],
+                opt: FormatOptions { color: true, anonymized_line_numbers: self.ui_testing },
+                slices: annotated_files
+                    .iter()
+                    .map(|(source, line_index, annotations)| {
+                        Slice {
+                            source,
+                            line_start: *line_index,
+                            origin: Some(&origin),
+                            // FIXME(#59346): Not really sure when `fold` should be true or false
+                            fold: false,
+                            annotations: annotations
+                                .into_iter()
+                                .map(|annotation| SourceAnnotation {
+                                    range: (annotation.start_col, annotation.end_col),
+                                    label: annotation
+                                        .label
+                                        .as_ref()
+                                        .map(|s| s.as_str())
+                                        .unwrap_or_default(),
+                                    annotation_type: annotation_type_for_level(*level),
+                                })
+                                .collect(),
+                        }
+                    })
+                    .collect(),
+            };
             // FIXME(#59346): Figure out if we can _always_ print to stderr or not.
             // `emitter.rs` has the `Destination` enum that lists various possible output
             // destinations.
-            eprintln!("{}", dlf.format(&dl));
-        };
+            eprintln!("{}", DisplayList::from(snippet))
+        }
+        // FIXME(#59346): Is it ok to return None if there's no source_map?
     }
 }
diff --git a/src/test/ui/annotate-snippet/auxiliary/multispan.rs b/src/test/ui/annotate-snippet/auxiliary/multispan.rs
new file mode 100644
index 0000000000000..c05d15643dbb1
--- /dev/null
+++ b/src/test/ui/annotate-snippet/auxiliary/multispan.rs
@@ -0,0 +1,37 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro_diagnostic, proc_macro_span, proc_macro_def_site)]
+
+extern crate proc_macro;
+
+use proc_macro::{TokenStream, TokenTree, Span, Diagnostic};
+
+fn parse(input: TokenStream) -> Result<(), Diagnostic> {
+    let mut hi_spans = vec![];
+    for tree in input {
+        if let TokenTree::Ident(ref ident) = tree {
+            if ident.to_string() == "hi" {
+                hi_spans.push(ident.span());
+            }
+        }
+    }
+
+    if !hi_spans.is_empty() {
+        return Err(Span::def_site()
+                       .error("hello to you, too!")
+                       .span_note(hi_spans, "found these 'hi's"));
+    }
+
+    Ok(())
+}
+
+#[proc_macro]
+pub fn hello(input: TokenStream) -> TokenStream {
+    if let Err(diag) = parse(input) {
+        diag.emit();
+    }
+
+    TokenStream::new()
+}
diff --git a/src/test/ui/annotate-snippet/missing-type.stderr b/src/test/ui/annotate-snippet/missing-type.stderr
index 806acf0bed5d1..c16f022a77fa3 100644
--- a/src/test/ui/annotate-snippet/missing-type.stderr
+++ b/src/test/ui/annotate-snippet/missing-type.stderr
@@ -1,5 +1,5 @@
 error[E0412]: cannot find type `Iter` in this scope
-  --> $DIR/missing-type.rs:4:11
+  --> $DIR/missing-type.rs:4:12
    |
 LL |     let x: Iter;
    |            ^^^^ not found in this scope
diff --git a/src/test/ui/annotate-snippet/multispan.rs b/src/test/ui/annotate-snippet/multispan.rs
new file mode 100644
index 0000000000000..325252d7716f6
--- /dev/null
+++ b/src/test/ui/annotate-snippet/multispan.rs
@@ -0,0 +1,28 @@
+// aux-build:multispan.rs
+// compile-flags: --error-format human-annotate-rs
+
+#![feature(proc_macro_hygiene)]
+
+extern crate multispan;
+
+use multispan::hello;
+
+fn main() {
+    // This one emits no error.
+    hello!();
+
+    // Exactly one 'hi'.
+    hello!(hi); //~ ERROR hello to you, too!
+
+    // Now two, back to back.
+    hello!(hi hi); //~ ERROR hello to you, too!
+
+    // Now three, back to back.
+    hello!(hi hi hi); //~ ERROR hello to you, too!
+
+    // Now several, with spacing.
+    hello!(hi hey hi yo hi beep beep hi hi); //~ ERROR hello to you, too!
+    hello!(hi there, hi how are you? hi... hi.); //~ ERROR hello to you, too!
+    hello!(whoah. hi di hi di ho); //~ ERROR hello to you, too!
+    hello!(hi good hi and good bye); //~ ERROR hello to you, too!
+}
diff --git a/src/test/ui/annotate-snippet/multispan.stderr b/src/test/ui/annotate-snippet/multispan.stderr
new file mode 100644
index 0000000000000..4ac31e32ba7cf
--- /dev/null
+++ b/src/test/ui/annotate-snippet/multispan.stderr
@@ -0,0 +1,42 @@
+error: hello to you, too!
+  --> $DIR/multispan.rs:15:5
+   |
+LL |     hello!(hi);
+   |     ^^^^^^^^^^^
+   |
+error: hello to you, too!
+  --> $DIR/multispan.rs:18:5
+   |
+LL |     hello!(hi hi);
+   |     ^^^^^^^^^^^^^^
+   |
+error: hello to you, too!
+  --> $DIR/multispan.rs:21:5
+   |
+LL |     hello!(hi hi hi);
+   |     ^^^^^^^^^^^^^^^^^
+   |
+error: hello to you, too!
+  --> $DIR/multispan.rs:24:5
+   |
+LL |     hello!(hi hey hi yo hi beep beep hi hi);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+error: hello to you, too!
+  --> $DIR/multispan.rs:25:5
+   |
+LL |     hello!(hi there, hi how are you? hi... hi.);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+error: hello to you, too!
+  --> $DIR/multispan.rs:26:5
+   |
+LL |     hello!(whoah. hi di hi di ho);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+error: hello to you, too!
+  --> $DIR/multispan.rs:27:5
+   |
+LL |     hello!(hi good hi and good bye);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |