diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 894044296cbd6..96ecad629f543 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -94,7 +94,7 @@ use syntax::ast;
 use syntax::parse::token;
 use syntax::ptr::P;
 use syntax_pos::{self, Pos, Span};
-use errors::{DiagnosticBuilder, check_old_skool};
+use errors::{DiagnosticBuilder, check_old_school};
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn note_and_explain_region(self,
@@ -485,7 +485,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                        "{}",
                                        trace.origin);
 
-        if !is_simple_error || check_old_skool() {
+        if !is_simple_error || check_old_school() {
             err.note_expected_found(&"type", &expected, &found);
         }
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 0e516bdc21194..fa9bc7c83680c 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -22,7 +22,8 @@ use mir::transform as mir_pass;
 
 use syntax::ast::{NodeId, Name};
 use errors::{self, DiagnosticBuilder};
-use errors::emitter::{Emitter, BasicEmitter, EmitterWriter};
+use errors::emitter::{Emitter, EmitterWriter};
+use errors::snippet::FormatMode;
 use syntax::json::JsonEmitter;
 use syntax::feature_gate;
 use syntax::parse;
@@ -439,7 +440,7 @@ pub fn build_session_with_codemap(sopts: config::Options,
         config::ErrorOutputType::HumanReadable(color_config) => {
             Box::new(EmitterWriter::stderr(color_config,
                                            Some(registry),
-                                           codemap.clone(),
+                                           Some(codemap.clone()),
                                            errors::snippet::FormatMode::EnvironmentSelected))
         }
         config::ErrorOutputType::Json => {
@@ -575,24 +576,32 @@ unsafe fn configure_llvm(sess: &Session) {
 }
 
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
-    let mut emitter: Box<Emitter> = match output {
+    let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
-            Box::new(BasicEmitter::stderr(color_config))
+            Box::new(EmitterWriter::stderr(color_config,
+                                           None,
+                                           None,
+                                           FormatMode::EnvironmentSelected))
         }
         config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
     };
-    emitter.emit(&MultiSpan::new(), msg, None, errors::Level::Fatal);
+    let handler = errors::Handler::with_emitter(true, false, emitter);
+    handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal);
     panic!(errors::FatalError);
 }
 
 pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
-    let mut emitter: Box<Emitter> = match output {
+    let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
-            Box::new(BasicEmitter::stderr(color_config))
+            Box::new(EmitterWriter::stderr(color_config,
+                                           None,
+                                           None,
+                                           FormatMode::EnvironmentSelected))
         }
         config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
     };
-    emitter.emit(&MultiSpan::new(), msg, None, errors::Level::Warning);
+    let handler = errors::Handler::with_emitter(true, false, emitter);
+    handler.emit(&MultiSpan::new(), msg, errors::Level::Warning);
 }
 
 // Err(0) means compilation was stopped, but no errors were found.
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 84e0403192317..0a8df923b846b 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -100,6 +100,7 @@ use syntax::feature_gate::{GatedCfg, UnstableFeatures};
 use syntax::parse::{self, PResult};
 use syntax_pos::MultiSpan;
 use errors::emitter::Emitter;
+use errors::snippet::FormatMode;
 
 #[cfg(test)]
 pub mod test;
@@ -138,10 +139,15 @@ pub fn run(args: Vec<String>) -> isize {
                 match session {
                     Some(sess) => sess.fatal(&abort_msg(err_count)),
                     None => {
-                        let mut emitter =
-                            errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto);
-                        emitter.emit(&MultiSpan::new(), &abort_msg(err_count), None,
-                            errors::Level::Fatal);
+                        let emitter =
+                            errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
+                                                                   None,
+                                                                   None,
+                                                                   FormatMode::EnvironmentSelected);
+                        let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
+                        handler.emit(&MultiSpan::new(),
+                                     &abort_msg(err_count),
+                                     errors::Level::Fatal);
                         exit_on_err();
                     }
                 }
@@ -373,23 +379,26 @@ fn handle_explain(code: &str,
 
 fn check_cfg(sopts: &config::Options,
              output: ErrorOutputType) {
-    let mut emitter: Box<Emitter> = match output {
+    let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
-            Box::new(errors::emitter::BasicEmitter::stderr(color_config))
+            Box::new(errors::emitter::EmitterWriter::stderr(color_config,
+                                                            None,
+                                                            None,
+                                                            FormatMode::EnvironmentSelected))
         }
         config::ErrorOutputType::Json => Box::new(json::JsonEmitter::basic()),
     };
+    let handler = errors::Handler::with_emitter(true, false, emitter);
 
     let mut saw_invalid_predicate = false;
     for item in sopts.cfg.iter() {
         match item.node {
             ast::MetaItemKind::List(ref pred, _) => {
                 saw_invalid_predicate = true;
-                emitter.emit(&MultiSpan::new(),
+                handler.emit(&MultiSpan::new(),
                              &format!("invalid predicate in --cfg command line argument: `{}`",
                                       pred),
-                             None,
-                             errors::Level::Fatal);
+                                errors::Level::Fatal);
             }
             _ => {},
         }
@@ -1046,26 +1055,34 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
      if let Err(value) = thread.unwrap().join() {
         // Thread panicked without emitting a fatal diagnostic
         if !value.is::<errors::FatalError>() {
-            let mut emitter = errors::emitter::BasicEmitter::stderr(errors::ColorConfig::Auto);
+            let emitter =
+                Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
+                                                       None,
+                                                       None,
+                                                       FormatMode::EnvironmentSelected));
+            let handler = errors::Handler::with_emitter(true, false, emitter);
 
             // a .span_bug or .bug call has already printed what
             // it wants to print.
             if !value.is::<errors::ExplicitBug>() {
-                emitter.emit(&MultiSpan::new(), "unexpected panic", None, errors::Level::Bug);
+                handler.emit(&MultiSpan::new(),
+                             "unexpected panic",
+                             errors::Level::Bug);
             }
 
             let xs = ["the compiler unexpectedly panicked. this is a bug.".to_string(),
                       format!("we would appreciate a bug report: {}", BUG_REPORT_URL)];
             for note in &xs {
-                emitter.emit(&MultiSpan::new(), &note[..], None, errors::Level::Note)
+                handler.emit(&MultiSpan::new(),
+                             &note[..],
+                             errors::Level::Note);
             }
             if match env::var_os("RUST_BACKTRACE") {
                 Some(val) => &val != "0",
                 None => false,
             } {
-                emitter.emit(&MultiSpan::new(),
+                handler.emit(&MultiSpan::new(),
                              "run with `RUST_BACKTRACE=1` for a backtrace",
-                             None,
                              errors::Level::Note);
             }
 
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 911becd3f569b..39763bfa0eb61 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -33,8 +33,8 @@ use syntax::ast;
 use syntax::abi::Abi;
 use syntax::codemap::CodeMap;
 use errors;
-use errors::emitter::{CoreEmitter, Emitter};
-use errors::{Level, RenderSpan};
+use errors::emitter::Emitter;
+use errors::{Level, DiagnosticBuilder};
 use syntax::parse::token;
 use syntax::feature_gate::UnstableFeatures;
 use syntax_pos::DUMMY_SP;
@@ -76,15 +76,12 @@ fn remove_message(e: &mut ExpectErrorEmitter, msg: &str, lvl: Level) {
     }
 }
 
-impl CoreEmitter for ExpectErrorEmitter {
-    fn emit_message(&mut self,
-                    _sp: &RenderSpan,
-                    msg: &str,
-                    _: Option<&str>,
-                    lvl: Level,
-                    _is_header: bool,
-                    _show_snippet: bool) {
-        remove_message(self, msg, lvl);
+impl Emitter for ExpectErrorEmitter {
+    fn emit(&mut self, db: &DiagnosticBuilder) {
+        remove_message(self, &db.message, db.level);
+        for child in &db.children {
+            remove_message(self, &child.message, child.level);
+        }
     }
 }
 
diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs
index a7c68e3a87b31..893f8a6e4ddb0 100644
--- a/src/librustc_errors/emitter.rs
+++ b/src/librustc_errors/emitter.rs
@@ -10,89 +10,40 @@
 
 use self::Destination::*;
 
-use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, Span, MultiSpan, LineInfo};
+use syntax_pos::{COMMAND_LINE_SP, DUMMY_SP, FileMap, Span, MultiSpan, LineInfo, CharPos};
 use registry;
 
-use check_old_skool;
-use {Level, RenderSpan, CodeSuggestion, DiagnosticBuilder, CodeMapper};
+use check_old_school;
+use {Level, CodeSuggestion, DiagnosticBuilder, CodeMapper};
 use RenderSpan::*;
-use Level::*;
-use snippet::{RenderedLineKind, SnippetData, Style, FormatMode};
+use snippet::{StyledString, Style, FormatMode, Annotation, Line};
+use styled_buffer::StyledBuffer;
 
-use std::{cmp, fmt};
+use std::cmp;
 use std::io::prelude::*;
 use std::io;
 use std::rc::Rc;
 use term;
 
-/// Emitter trait for emitting errors. Do not implement this directly:
-/// implement `CoreEmitter` instead.
+/// Emitter trait for emitting errors.
 pub trait Emitter {
-    /// Emit a standalone diagnostic message.
-    fn emit(&mut self, span: &MultiSpan, msg: &str, code: Option<&str>, lvl: Level);
-
     /// Emit a structured diagnostic.
-    fn emit_struct(&mut self, db: &DiagnosticBuilder);
-}
-
-pub trait CoreEmitter {
-    fn emit_message(&mut self,
-                    rsp: &RenderSpan,
-                    msg: &str,
-                    code: Option<&str>,
-                    lvl: Level,
-                    is_header: bool,
-                    show_snippet: bool);
+    fn emit(&mut self, db: &DiagnosticBuilder);
 }
 
-impl<T: CoreEmitter> Emitter for T {
-    fn emit(&mut self,
-            msp: &MultiSpan,
-            msg: &str,
-            code: Option<&str>,
-            lvl: Level) {
-        self.emit_message(&FullSpan(msp.clone()),
-                          msg,
-                          code,
-                          lvl,
-                          true,
-                          true);
-    }
+impl Emitter for EmitterWriter {
+    fn emit(&mut self, db: &DiagnosticBuilder) {
+        // Pick old school mode either from env or let the test dictate the format
+        let old_school = match self.format_mode {
+            FormatMode::NewErrorFormat => false,
+            FormatMode::OriginalErrorFormat => true,
+            FormatMode::EnvironmentSelected => check_old_school()
+        };
 
-    fn emit_struct(&mut self, db: &DiagnosticBuilder) {
-        let old_school = check_old_skool();
-        let db_span = FullSpan(db.span.clone());
-        self.emit_message(&FullSpan(db.span.clone()),
-                          &db.message,
-                          db.code.as_ref().map(|s| &**s),
-                          db.level,
-                          true,
-                          true);
-        for child in &db.children {
-            let render_span = child.render_span
-                                   .clone()
-                                   .unwrap_or_else(
-                                       || FullSpan(child.span.clone()));
-
-            if !old_school {
-                self.emit_message(&render_span,
-                                    &child.message,
-                                    None,
-                                    child.level,
-                                    false,
-                                    true);
-            } else {
-                let (render_span, show_snippet) = match render_span.span().primary_span() {
-                    None => (db_span.clone(), false),
-                    _ => (render_span, true)
-                };
-                self.emit_message(&render_span,
-                                    &child.message,
-                                    None,
-                                    child.level,
-                                    false,
-                                    show_snippet);
-            }
+        if old_school {
+            self.emit_messages_old_school(db);
+        } else {
+            self.emit_messages_default(db);
         }
     }
 }
@@ -117,66 +68,21 @@ impl ColorConfig {
     }
 }
 
-/// A basic emitter for when we don't have access to a codemap or registry. Used
-/// for reporting very early errors, etc.
-pub struct BasicEmitter {
-    dst: Destination,
-}
-
-impl CoreEmitter for BasicEmitter {
-    fn emit_message(&mut self,
-                    _rsp: &RenderSpan,
-                    msg: &str,
-                    code: Option<&str>,
-                    lvl: Level,
-                    _is_header: bool,
-                    _show_snippet: bool) {
-        // we ignore the span as we have no access to a codemap at this point
-        if let Err(e) = print_diagnostic(&mut self.dst, "", lvl, msg, code) {
-            panic!("failed to print diagnostics: {:?}", e);
-        }
-    }
-}
-
-impl BasicEmitter {
-    pub fn stderr(color_config: ColorConfig) -> BasicEmitter {
-        if color_config.use_color() {
-            let dst = Destination::from_stderr();
-            BasicEmitter { dst: dst }
-        } else {
-            BasicEmitter { dst: Raw(Box::new(io::stderr())) }
-        }
-    }
-}
-
 pub struct EmitterWriter {
     dst: Destination,
     registry: Option<registry::Registry>,
-    cm: Rc<CodeMapper>,
-
-    /// Is this the first error emitted thus far? If not, we emit a
-    /// `\n` before the top-level errors.
-    first: bool,
+    cm: Option<Rc<CodeMapper>>,
 
     // For now, allow an old-school mode while we transition
     format_mode: FormatMode
 }
 
-impl CoreEmitter for EmitterWriter {
-    fn emit_message(&mut self,
-                    rsp: &RenderSpan,
-                    msg: &str,
-                    code: Option<&str>,
-                    lvl: Level,
-                    is_header: bool,
-                    show_snippet: bool) {
-        match self.emit_message_(rsp, msg, code, lvl, is_header, show_snippet) {
-            Ok(()) => { }
-            Err(e) => panic!("failed to emit error: {}", e)
-        }
-    }
+struct FileWithAnnotatedLines {
+    file: Rc<FileMap>,
+    lines: Vec<Line>,
 }
 
+
 /// Do not use this for messages that end in `\n` – use `println_maybe_styled` instead. See
 /// `EmitterWriter::print_maybe_styled` for details.
 macro_rules! print_maybe_styled {
@@ -194,7 +100,7 @@ macro_rules! println_maybe_styled {
 impl EmitterWriter {
     pub fn stderr(color_config: ColorConfig,
                   registry: Option<registry::Registry>,
-                  code_map: Rc<CodeMapper>,
+                  code_map: Option<Rc<CodeMapper>>,
                   format_mode: FormatMode)
                   -> EmitterWriter {
         if color_config.use_color() {
@@ -202,248 +108,854 @@ impl EmitterWriter {
             EmitterWriter { dst: dst,
                             registry: registry,
                             cm: code_map,
-                            first: true,
                             format_mode: format_mode.clone() }
         } else {
             EmitterWriter { dst: Raw(Box::new(io::stderr())),
                             registry: registry,
                             cm: code_map,
-                            first: true,
                             format_mode: format_mode.clone() }
         }
     }
 
     pub fn new(dst: Box<Write + Send>,
                registry: Option<registry::Registry>,
-               code_map: Rc<CodeMapper>,
+               code_map: Option<Rc<CodeMapper>>,
                format_mode: FormatMode)
                -> EmitterWriter {
         EmitterWriter { dst: Raw(dst),
                         registry: registry,
                         cm: code_map,
-                        first: true,
                         format_mode: format_mode.clone() }
     }
 
-    fn emit_message_(&mut self,
-                     rsp: &RenderSpan,
-                     msg: &str,
-                     code: Option<&str>,
-                     lvl: Level,
-                     is_header: bool,
-                     show_snippet: bool)
-                     -> io::Result<()> {
-        let old_school = match self.format_mode {
-            FormatMode::NewErrorFormat => false,
-            FormatMode::OriginalErrorFormat => true,
-            FormatMode::EnvironmentSelected => check_old_skool()
-        };
+    fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {
+        fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
+                                    file: Rc<FileMap>,
+                                    line_index: usize,
+                                    ann: Annotation) {
+
+            for slot in file_vec.iter_mut() {
+                // Look through each of our files for the one we're adding to
+                if slot.file.name == file.name {
+                    // See if we already have a line for it
+                    for line_slot in &mut slot.lines {
+                        if line_slot.line_index == line_index {
+                            line_slot.annotations.push(ann);
+                            return;
+                        }
+                    }
+                    // We don't have a line yet, create one
+                    slot.lines.push(Line {
+                        line_index: line_index,
+                        annotations: vec![ann],
+                    });
+                    slot.lines.sort();
+                    return;
+                }
+            }
+            // This is the first time we're seeing the file
+            file_vec.push(FileWithAnnotatedLines {
+                file: file,
+                lines: vec![Line {
+                                line_index: line_index,
+                                annotations: vec![ann],
+                            }],
+            });
+        }
+
+        let mut output = vec![];
+
+        if let Some(ref cm) = self.cm {
+            for span_label in msp.span_labels() {
+                if span_label.span == DUMMY_SP || span_label.span == COMMAND_LINE_SP {
+                    continue;
+                }
+                let lo = cm.lookup_char_pos(span_label.span.lo);
+                let mut hi = cm.lookup_char_pos(span_label.span.hi);
+                let mut is_minimized = false;
+
+                // If the span is multi-line, simplify down to the span of one character
+                if lo.line != hi.line {
+                    hi.line = lo.line;
+                    hi.col = CharPos(lo.col.0 + 1);
+                    is_minimized = true;
+                }
 
-        if is_header {
-            if self.first {
-                self.first = false;
+                // Watch out for "empty spans". If we get a span like 6..6, we
+                // want to just display a `^` at 6, so convert that to
+                // 6..7. This is degenerate input, but it's best to degrade
+                // gracefully -- and the parser likes to supply a span like
+                // that for EOF, in particular.
+                if lo.col == hi.col {
+                    hi.col = CharPos(lo.col.0 + 1);
+                }
+
+                add_annotation_to_file(&mut output,
+                                        lo.file,
+                                        lo.line,
+                                        Annotation {
+                                            start_col: lo.col.0,
+                                            end_col: hi.col.0,
+                                            is_primary: span_label.is_primary,
+                                            is_minimized: is_minimized,
+                                            label: span_label.label.clone(),
+                                        });
+            }
+        }
+        output
+    }
+
+    fn render_source_line(&self,
+                          buffer: &mut StyledBuffer,
+                          file: Rc<FileMap>,
+                          line: &Line,
+                          width_offset: usize) {
+        let source_string = file.get_line(line.line_index - 1)
+            .unwrap_or("");
+
+        let line_offset = buffer.num_lines();
+
+        // First create the source line we will highlight.
+        buffer.puts(line_offset, width_offset, &source_string, Style::Quotation);
+        buffer.puts(line_offset,
+                    0,
+                    &(line.line_index.to_string()),
+                    Style::LineNumber);
+
+        draw_col_separator(buffer, line_offset, width_offset - 2);
+
+        if line.annotations.is_empty() {
+            return;
+        }
+
+        // We want to display like this:
+        //
+        //      vec.push(vec.pop().unwrap());
+        //      ---      ^^^               _ previous borrow ends here
+        //      |        |
+        //      |        error occurs here
+        //      previous borrow of `vec` occurs here
+        //
+        // But there are some weird edge cases to be aware of:
+        //
+        //      vec.push(vec.pop().unwrap());
+        //      --------                    - previous borrow ends here
+        //      ||
+        //      |this makes no sense
+        //      previous borrow of `vec` occurs here
+        //
+        // For this reason, we group the lines into "highlight lines"
+        // and "annotations lines", where the highlight lines have the `~`.
+
+        // Sort the annotations by (start, end col)
+        let mut annotations = line.annotations.clone();
+        annotations.sort();
+
+        // Next, create the highlight line.
+        for annotation in &annotations {
+            for p in annotation.start_col..annotation.end_col {
+                if annotation.is_primary {
+                    buffer.putc(line_offset + 1,
+                                width_offset + p,
+                                '^',
+                                Style::UnderlinePrimary);
+                    if !annotation.is_minimized {
+                        buffer.set_style(line_offset,
+                                            width_offset + p,
+                                            Style::UnderlinePrimary);
+                    }
+                } else {
+                    buffer.putc(line_offset + 1,
+                                width_offset + p,
+                                '-',
+                                Style::UnderlineSecondary);
+                    if !annotation.is_minimized {
+                        buffer.set_style(line_offset,
+                                            width_offset + p,
+                                            Style::UnderlineSecondary);
+                    }
+                }
+            }
+        }
+        draw_col_separator(buffer, line_offset + 1, width_offset - 2);
+
+        // Now we are going to write labels in. To start, we'll exclude
+        // the annotations with no labels.
+        let (labeled_annotations, unlabeled_annotations): (Vec<_>, _) = annotations.into_iter()
+            .partition(|a| a.label.is_some());
+
+        // If there are no annotations that need text, we're done.
+        if labeled_annotations.is_empty() {
+            return;
+        }
+        // Now add the text labels. We try, when possible, to stick the rightmost
+        // annotation at the end of the highlight line:
+        //
+        //      vec.push(vec.pop().unwrap());
+        //      ---      ---               - previous borrow ends here
+        //
+        // But sometimes that's not possible because one of the other
+        // annotations overlaps it. For example, from the test
+        // `span_overlap_label`, we have the following annotations
+        // (written on distinct lines for clarity):
+        //
+        //      fn foo(x: u32) {
+        //      --------------
+        //             -
+        //
+        // In this case, we can't stick the rightmost-most label on
+        // the highlight line, or we would get:
+        //
+        //      fn foo(x: u32) {
+        //      -------- x_span
+        //      |
+        //      fn_span
+        //
+        // which is totally weird. Instead we want:
+        //
+        //      fn foo(x: u32) {
+        //      --------------
+        //      |      |
+        //      |      x_span
+        //      fn_span
+        //
+        // which is...less weird, at least. In fact, in general, if
+        // the rightmost span overlaps with any other span, we should
+        // use the "hang below" version, so we can at least make it
+        // clear where the span *starts*.
+        let mut labeled_annotations = &labeled_annotations[..];
+        match labeled_annotations.split_last().unwrap() {
+            (last, previous) => {
+                if previous.iter()
+                    .chain(&unlabeled_annotations)
+                    .all(|a| !overlaps(a, last)) {
+                    // append the label afterwards; we keep it in a separate
+                    // string
+                    let highlight_label: String = format!(" {}", last.label.as_ref().unwrap());
+                    if last.is_primary {
+                        buffer.append(line_offset + 1, &highlight_label, Style::LabelPrimary);
+                    } else {
+                        buffer.append(line_offset + 1, &highlight_label, Style::LabelSecondary);
+                    }
+                    labeled_annotations = previous;
+                }
+            }
+        }
+
+        // If that's the last annotation, we're done
+        if labeled_annotations.is_empty() {
+            return;
+        }
+
+        for (index, annotation) in labeled_annotations.iter().enumerate() {
+            // Leave:
+            // - 1 extra line
+            // - One line for each thing that comes after
+            let comes_after = labeled_annotations.len() - index - 1;
+            let blank_lines = 3 + comes_after;
+
+            // For each blank line, draw a `|` at our column. The
+            // text ought to be long enough for this.
+            for index in 2..blank_lines {
+                if annotation.is_primary {
+                    buffer.putc(line_offset + index,
+                                width_offset + annotation.start_col,
+                                '|',
+                                Style::UnderlinePrimary);
+                } else {
+                    buffer.putc(line_offset + index,
+                                width_offset + annotation.start_col,
+                                '|',
+                                Style::UnderlineSecondary);
+                }
+                draw_col_separator(buffer, line_offset + index, width_offset - 2);
+            }
+
+            if annotation.is_primary {
+                buffer.puts(line_offset + blank_lines,
+                            width_offset + annotation.start_col,
+                            annotation.label.as_ref().unwrap(),
+                            Style::LabelPrimary);
             } else {
-                if !old_school {
-                    write!(self.dst, "\n")?;
+                buffer.puts(line_offset + blank_lines,
+                            width_offset + annotation.start_col,
+                            annotation.label.as_ref().unwrap(),
+                            Style::LabelSecondary);
+            }
+            draw_col_separator(buffer, line_offset + blank_lines, width_offset - 2);
+        }
+    }
+
+    fn get_multispan_max_line_num(&mut self, msp: &MultiSpan) -> usize {
+        let mut max = 0;
+        if let Some(ref cm) = self.cm {
+            for primary_span in msp.primary_spans() {
+                if primary_span != &DUMMY_SP && primary_span != &COMMAND_LINE_SP {
+                    let hi = cm.lookup_char_pos(primary_span.hi);
+                    if hi.line > max {
+                        max = hi.line;
+                    }
+                }
+            }
+            for span_label in msp.span_labels() {
+                if span_label.span != DUMMY_SP && span_label.span != COMMAND_LINE_SP {
+                    let hi = cm.lookup_char_pos(span_label.span.hi);
+                    if hi.line > max {
+                        max = hi.line;
+                    }
+                }
+            }
+        }
+        max
+    }
+
+    fn get_max_line_num(&mut self, db: &DiagnosticBuilder) -> usize {
+        let mut max = 0;
+
+        let primary = self.get_multispan_max_line_num(&db.span);
+        max = if primary > max { primary } else { max };
+
+        for sub in &db.children {
+            let sub_result = self.get_multispan_max_line_num(&sub.span);
+            max = if sub_result > max { primary } else { max };
+        }
+        max
+    }
+
+    fn emit_message_default(&mut self,
+                            msp: &MultiSpan,
+                            msg: &str,
+                            code: &Option<String>,
+                            level: &Level,
+                            max_line_num_len: usize,
+                            is_secondary: bool)
+                            -> io::Result<()> {
+        let mut buffer = StyledBuffer::new();
+
+        if msp.primary_spans().is_empty() && msp.span_labels().is_empty() && is_secondary {
+            // This is a secondary message with no span info
+            for _ in 0..max_line_num_len {
+                buffer.prepend(0, " ", Style::NoStyle);
+            }
+            draw_note_separator(&mut buffer, 0, max_line_num_len + 1);
+            buffer.append(0, &level.to_string(), Style::HeaderMsg);
+            buffer.append(0, ": ", Style::NoStyle);
+            buffer.append(0, msg, Style::NoStyle);
+        }
+        else {
+            buffer.append(0, &level.to_string(), Style::Level(level.clone()));
+            match code {
+                &Some(ref code) => {
+                    buffer.append(0, "[", Style::Level(level.clone()));
+                    buffer.append(0, &code, Style::Level(level.clone()));
+                    buffer.append(0, "]", Style::Level(level.clone()));
                 }
+                _ => {}
             }
+            buffer.append(0, ": ", Style::HeaderMsg);
+            buffer.append(0, msg, Style::HeaderMsg);
         }
 
-        match code {
-            Some(code) if self.registry.as_ref()
-                                       .and_then(|registry| registry.find_description(code))
-                                       .is_some() => {
-                let code_with_explain = String::from("--explain ") + code;
-                if old_school {
-                    let loc = match rsp.span().primary_span() {
-                        Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(),
-                        Some(ps) => self.cm.span_to_string(ps),
-                        None => "".to_string()
-                    };
-                    print_diagnostic(&mut self.dst, &loc, lvl, msg, Some(code))?
+        // Preprocess all the annotations so that they are grouped by file and by line number
+        // This helps us quickly iterate over the whole message (including secondary file spans)
+        let mut annotated_files = self.preprocess_annotations(msp);
+
+        // Make sure our primary file comes first
+        let primary_lo =
+            if let (Some(ref cm), Some(ref primary_span)) = (self.cm.as_ref(),
+                                                             msp.primary_span().as_ref()) {
+                if primary_span != &&DUMMY_SP && primary_span != &&COMMAND_LINE_SP {
+                    cm.lookup_char_pos(primary_span.lo)
                 }
                 else {
-                    print_diagnostic(&mut self.dst, "", lvl, msg, Some(&code_with_explain))?
+                    emit_to_destination(&buffer.render(), level, &mut self.dst)?;
+                    return Ok(());
+                }
+            } else {
+                // If we don't have span information, emit and exit
+                emit_to_destination(&buffer.render(), level, &mut self.dst)?;
+                return Ok(());
+            };
+        if let Ok(pos) =
+                annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name)) {
+            annotated_files.swap(0, pos);
+        }
+
+        // Print out the annotate source lines that correspond with the error
+        for annotated_file in annotated_files {
+            // print out the span location and spacer before we print the annotated source
+            // to do this, we need to know if this span will be primary
+            let is_primary = primary_lo.file.name == annotated_file.file.name;
+            if is_primary {
+                // remember where we are in the output buffer for easy reference
+                let buffer_msg_line_offset = buffer.num_lines();
+
+                buffer.prepend(buffer_msg_line_offset, "--> ", Style::LineNumber);
+                let loc = primary_lo.clone();
+                buffer.append(buffer_msg_line_offset,
+                                &format!("{}:{}:{}", loc.file.name, loc.line, loc.col.0 + 1),
+                                Style::LineAndColumn);
+                for _ in 0..max_line_num_len {
+                    buffer.prepend(buffer_msg_line_offset, " ", Style::NoStyle);
+                }
+            } else {
+                // remember where we are in the output buffer for easy reference
+                let buffer_msg_line_offset = buffer.num_lines();
+
+                // Add spacing line
+                draw_col_separator(&mut buffer, buffer_msg_line_offset, max_line_num_len + 1);
+
+                // Then, the secondary file indicator
+                buffer.prepend(buffer_msg_line_offset + 1, "::: ", Style::LineNumber);
+                buffer.append(buffer_msg_line_offset + 1,
+                                &annotated_file.file.name,
+                                Style::LineAndColumn);
+                for _ in 0..max_line_num_len {
+                    buffer.prepend(buffer_msg_line_offset + 1, " ", Style::NoStyle);
                 }
             }
-            _ => {
-                if old_school {
-                    let loc = match rsp.span().primary_span() {
-                        Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(),
-                        Some(ps) => self.cm.span_to_string(ps),
-                        None => "".to_string()
-                    };
-                    print_diagnostic(&mut self.dst, &loc, lvl, msg, code)?
+
+            // Put in the spacer between the location and annotated source
+            let buffer_msg_line_offset = buffer.num_lines();
+            draw_col_separator_no_space(&mut buffer, buffer_msg_line_offset, max_line_num_len + 1);
+
+            // Next, output the annotate source for this file
+            for line_idx in 0..annotated_file.lines.len() {
+                self.render_source_line(&mut buffer,
+                                        annotated_file.file.clone(),
+                                        &annotated_file.lines[line_idx],
+                                        3 + max_line_num_len);
+
+                // check to see if we need to print out or elide lines that come between
+                // this annotated line and the next one
+                if line_idx < (annotated_file.lines.len() - 1) {
+                    let line_idx_delta = annotated_file.lines[line_idx + 1].line_index -
+                                            annotated_file.lines[line_idx].line_index;
+                    if line_idx_delta > 2 {
+                        let last_buffer_line_num = buffer.num_lines();
+                        buffer.puts(last_buffer_line_num, 0, "...", Style::LineNumber);
+                    } else if line_idx_delta == 2 {
+                        let unannotated_line = annotated_file.file
+                            .get_line(annotated_file.lines[line_idx].line_index)
+                            .unwrap_or("");
+
+                        let last_buffer_line_num = buffer.num_lines();
+
+                        buffer.puts(last_buffer_line_num,
+                                    0,
+                                    &(annotated_file.lines[line_idx + 1].line_index - 1)
+                                        .to_string(),
+                                    Style::LineNumber);
+                        draw_col_separator(&mut buffer, last_buffer_line_num, 1 + max_line_num_len);
+                        buffer.puts(last_buffer_line_num,
+                                    3 + max_line_num_len,
+                                    &unannotated_line,
+                                    Style::Quotation);
+                    }
                 }
-                else {
-                    print_diagnostic(&mut self.dst, "", lvl, msg, code)?
+            }
+        }
+
+        if let Some(ref primary_span) = msp.primary_span().as_ref() {
+            self.render_macro_backtrace_old_school(primary_span, &mut buffer)?;
+        }
+
+        // final step: take our styled buffer, render it, then output it
+        emit_to_destination(&buffer.render(), level, &mut self.dst)?;
+
+        Ok(())
+    }
+    fn emit_suggestion_default(&mut self,
+                               suggestion: &CodeSuggestion,
+                               level: &Level,
+                               msg: &str,
+                               max_line_num_len: usize)
+                               -> io::Result<()> {
+        use std::borrow::Borrow;
+
+        let primary_span = suggestion.msp.primary_span().unwrap();
+        if let Some(ref cm) = self.cm {
+            let mut buffer = StyledBuffer::new();
+
+            buffer.append(0, &level.to_string(), Style::Level(level.clone()));
+            buffer.append(0, ": ", Style::HeaderMsg);
+            buffer.append(0, msg, Style::HeaderMsg);
+
+            let lines = cm.span_to_lines(primary_span).unwrap();
+
+            assert!(!lines.lines.is_empty());
+
+            let complete = suggestion.splice_lines(cm.borrow());
+
+            // print the suggestion without any line numbers, but leave
+            // space for them. This helps with lining up with previous
+            // snippets from the actual error being reported.
+            let mut lines = complete.lines();
+            let mut row_num = 1;
+            for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
+                draw_col_separator(&mut buffer, row_num, max_line_num_len + 1);
+                buffer.append(row_num, line, Style::NoStyle);
+                row_num += 1;
+            }
+
+            // if we elided some lines, add an ellipsis
+            if let Some(_) = lines.next() {
+                buffer.append(row_num, "...", Style::NoStyle);
+            }
+            emit_to_destination(&buffer.render(), level, &mut self.dst)?;
+        }
+        Ok(())
+    }
+    fn emit_messages_default(&mut self, db: &DiagnosticBuilder) {
+        let max_line_num = self.get_max_line_num(db);
+        let max_line_num_len = max_line_num.to_string().len();
+
+        match self.emit_message_default(&db.span,
+                                        &db.message,
+                                        &db.code,
+                                        &db.level,
+                                        max_line_num_len,
+                                        false) {
+            Ok(()) => {
+                if !db.children.is_empty() {
+                    let mut buffer = StyledBuffer::new();
+                    draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1);
+                    match emit_to_destination(&buffer.render(), &db.level, &mut self.dst) {
+                        Ok(()) => (),
+                        Err(e) => panic!("failed to emit error: {}", e)
+                    }
+                }
+                for child in &db.children {
+                    match child.render_span {
+                        Some(FullSpan(ref msp)) => {
+                            match self.emit_message_default(msp,
+                                                            &child.message,
+                                                            &None,
+                                                            &child.level,
+                                                            max_line_num_len,
+                                                            true) {
+                                Err(e) => panic!("failed to emit error: {}", e),
+                                _ => ()
+                            }
+                        },
+                        Some(Suggestion(ref cs)) => {
+                            match self.emit_suggestion_default(cs,
+                                                               &child.level,
+                                                               &child.message,
+                                                               max_line_num_len) {
+                                Err(e) => panic!("failed to emit error: {}", e),
+                                _ => ()
+                            }
+                        },
+                        None => {
+                            match self.emit_message_default(&child.span,
+                                                            &child.message,
+                                                            &None,
+                                                            &child.level,
+                                                            max_line_num_len,
+                                                            true) {
+                                Err(e) => panic!("failed to emit error: {}", e),
+                                _ => ()
+                            }
+                        }
+                    }
                 }
             }
+            Err(e) => panic!("failed to emit error: {}", e)
+        }
+        match write!(&mut self.dst, "\n") {
+            Err(e) => panic!("failed to emit error: {}", e),
+            _ => ()
+        }
+    }
+    fn emit_message_old_school(&mut self,
+                               msp: &MultiSpan,
+                               msg: &str,
+                               code: &Option<String>,
+                               level: &Level,
+                               show_snippet: bool)
+                               -> io::Result<()> {
+        let mut buffer = StyledBuffer::new();
+
+        let loc = match msp.primary_span() {
+            Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(),
+            Some(ps) => if let Some(ref cm) = self.cm {
+                cm.span_to_string(ps)
+            } else {
+                "".to_string()
+            },
+            None => {
+                "".to_string()
+            }
+        };
+        if loc != "" {
+            buffer.append(0, &loc, Style::NoStyle);
+            buffer.append(0, " ", Style::NoStyle);
+        }
+        buffer.append(0, &level.to_string(), Style::Level(level.clone()));
+        buffer.append(0, ": ", Style::HeaderMsg);
+        buffer.append(0, msg, Style::HeaderMsg);
+        buffer.append(0, " ", Style::NoStyle);
+        match code {
+            &Some(ref code) => {
+                buffer.append(0, "[", Style::ErrorCode);
+                buffer.append(0, &code, Style::ErrorCode);
+                buffer.append(0, "]", Style::ErrorCode);
+            }
+            _ => {}
         }
 
         if !show_snippet {
+            emit_to_destination(&buffer.render(), level, &mut self.dst)?;
             return Ok(());
         }
 
         // Watch out for various nasty special spans; don't try to
         // print any filename or anything for those.
-        match rsp.span().primary_span() {
+        match msp.primary_span() {
             Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => {
+                emit_to_destination(&buffer.render(), level, &mut self.dst)?;
                 return Ok(());
             }
             _ => { }
         }
 
-        // Otherwise, print out the snippet etc as needed.
-        match *rsp {
-            FullSpan(ref msp) => {
-                self.highlight_lines(msp, lvl)?;
-                if let Some(primary_span) = msp.primary_span() {
-                    self.print_macro_backtrace(primary_span)?;
-                }
-            }
-            Suggestion(ref suggestion) => {
-                self.highlight_suggestion(suggestion)?;
-                if let Some(primary_span) = rsp.span().primary_span() {
-                    self.print_macro_backtrace(primary_span)?;
+        let annotated_files = self.preprocess_annotations(msp);
+
+        if let (Some(ref cm), Some(ann_file), Some(ref primary_span)) =
+            (self.cm.as_ref(), annotated_files.first(), msp.primary_span().as_ref()) {
+
+            // Next, print the source line and its squiggle
+            // for old school mode, we will render them to the buffer, then insert the file loc
+            // (or space the same amount) in front of the line and the squiggle
+            let source_string = ann_file.file.get_line(ann_file.lines[0].line_index - 1)
+                .unwrap_or("");
+
+            let line_offset = buffer.num_lines();
+
+            let lo = cm.lookup_char_pos(primary_span.lo);
+            //Before each secondary line in old skool-mode, print the label
+            //as an old-style note
+            let file_pos = format!("{}:{} ", lo.file.name.clone(), lo.line);
+            let file_pos_len = file_pos.len();
+
+            // First create the source line we will highlight.
+            buffer.puts(line_offset, 0, &file_pos, Style::FileNameStyle);
+            buffer.puts(line_offset, file_pos_len, &source_string, Style::Quotation);
+            // Sort the annotations by (start, end col)
+            let annotations = ann_file.lines[0].annotations.clone();
+
+            // Next, create the highlight line.
+            for annotation in &annotations {
+                for p in annotation.start_col..annotation.end_col {
+                    if p == annotation.start_col {
+                        buffer.putc(line_offset + 1,
+                                    file_pos_len + p,
+                                    '^',
+                                    if annotation.is_primary {
+                                        Style::UnderlinePrimary
+                                    } else {
+                                        Style::OldSchoolNote
+                                    });
+                    } else {
+                        buffer.putc(line_offset + 1,
+                                    file_pos_len + p,
+                                    '~',
+                                    if annotation.is_primary {
+                                        Style::UnderlinePrimary
+                                    } else {
+                                        Style::OldSchoolNote
+                                    });
+                    }
                 }
             }
         }
-        if old_school {
-            match code {
-                Some(code) if self.registry.as_ref()
-                                        .and_then(|registry| registry.find_description(code))
-                                        .is_some() => {
-                    let loc = match rsp.span().primary_span() {
-                        Some(COMMAND_LINE_SP) | Some(DUMMY_SP) => "".to_string(),
-                        Some(ps) => self.cm.span_to_string(ps),
-                        None => "".to_string()
-                    };
-                    let msg = "run `rustc --explain ".to_string() + &code.to_string() +
-                        "` to see a detailed explanation";
-                    print_diagnostic(&mut self.dst, &loc, Level::Help, &msg,
-                        None)?
-                }
-                _ => ()
+        if let Some(ref primary_span) = msp.primary_span().as_ref() {
+            self.render_macro_backtrace_old_school(primary_span, &mut buffer)?;
+        }
+
+        match code {
+            &Some(ref code) if self.registry.as_ref()
+                                           .and_then(|registry| registry.find_description(code))
+                                           .is_some() => {
+                let msg = "run `rustc --explain ".to_string() + &code.to_string() +
+                    "` to see a detailed explanation";
+
+                let line_offset = buffer.num_lines();
+                buffer.append(line_offset, &loc, Style::NoStyle);
+                buffer.append(line_offset, " ", Style::NoStyle);
+                buffer.append(line_offset, &Level::Help.to_string(), Style::Level(Level::Help));
+                buffer.append(line_offset, ": ", Style::HeaderMsg);
+                buffer.append(line_offset, &msg, Style::HeaderMsg);
             }
+            _ => ()
         }
+
+        // final step: take our styled buffer, render it, then output it
+        emit_to_destination(&buffer.render(), level, &mut self.dst)?;
         Ok(())
     }
-
-    fn highlight_suggestion(&mut self, suggestion: &CodeSuggestion) -> io::Result<()>
-    {
+    fn emit_suggestion_old_school(&mut self,
+                                  suggestion: &CodeSuggestion,
+                                  level: &Level,
+                                  msg: &str)
+                                  -> io::Result<()> {
         use std::borrow::Borrow;
 
         let primary_span = suggestion.msp.primary_span().unwrap();
-        let lines = self.cm.span_to_lines(primary_span).unwrap();
-        assert!(!lines.lines.is_empty());
+        if let Some(ref cm) = self.cm {
+            let mut buffer = StyledBuffer::new();
 
-        let complete = suggestion.splice_lines(self.cm.borrow());
-        let line_count = cmp::min(lines.lines.len(), MAX_HIGHLIGHT_LINES);
-        let display_lines = &lines.lines[..line_count];
+            let loc = cm.span_to_string(primary_span);
 
-        let fm = &*lines.file;
-        // Calculate the widest number to format evenly
-        let max_digits = line_num_max_digits(display_lines.last().unwrap());
+            if loc != "" {
+                buffer.append(0, &loc, Style::NoStyle);
+                buffer.append(0, " ", Style::NoStyle);
+            }
 
-        // print the suggestion without any line numbers, but leave
-        // space for them. This helps with lining up with previous
-        // snippets from the actual error being reported.
-        let mut lines = complete.lines();
-        for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
-            write!(&mut self.dst, "{0}:{1:2$} {3}\n",
-                   fm.name, "", max_digits, line)?;
-        }
+            buffer.append(0, &level.to_string(), Style::Level(level.clone()));
+            buffer.append(0, ": ", Style::HeaderMsg);
+            buffer.append(0, msg, Style::HeaderMsg);
 
-        // if we elided some lines, add an ellipsis
-        if let Some(_) = lines.next() {
-            write!(&mut self.dst, "{0:1$} {0:2$} ...\n",
-                   "", fm.name.len(), max_digits)?;
-        }
+            let lines = cm.span_to_lines(primary_span).unwrap();
 
-        Ok(())
-    }
+            assert!(!lines.lines.is_empty());
 
-    pub fn highlight_lines(&mut self,
-                       msp: &MultiSpan,
-                       lvl: Level)
-                       -> io::Result<()>
-    {
-        let old_school = match self.format_mode {
-            FormatMode::NewErrorFormat => false,
-            FormatMode::OriginalErrorFormat => true,
-            FormatMode::EnvironmentSelected => check_old_skool()
-        };
+            let complete = suggestion.splice_lines(cm.borrow());
+            let line_count = cmp::min(lines.lines.len(), MAX_HIGHLIGHT_LINES);
+            let display_lines = &lines.lines[..line_count];
 
-        let mut snippet_data = SnippetData::new(self.cm.clone(),
-                                                msp.primary_span(),
-                                                self.format_mode.clone());
-        if old_school {
-            let mut output_vec = vec![];
+            let fm = &*lines.file;
+            // Calculate the widest number to format evenly
+            let max_digits = line_num_max_digits(display_lines.last().unwrap());
 
-            for span_label in msp.span_labels() {
-                let mut snippet_data = SnippetData::new(self.cm.clone(),
-                                                        Some(span_label.span),
-                                                        self.format_mode.clone());
-
-                snippet_data.push(span_label.span,
-                                  span_label.is_primary,
-                                  span_label.label);
-                if span_label.is_primary {
-                    output_vec.insert(0, snippet_data);
-                }
-                else {
-                    output_vec.push(snippet_data);
+            // print the suggestion without any line numbers, but leave
+            // space for them. This helps with lining up with previous
+            // snippets from the actual error being reported.
+            let mut lines = complete.lines();
+            let mut row_num = 1;
+            for line in lines.by_ref().take(MAX_HIGHLIGHT_LINES) {
+                buffer.append(row_num, &fm.name, Style::FileNameStyle);
+                for _ in 0..max_digits+2 {
+                    buffer.append(row_num, &" ", Style::NoStyle);
                 }
+                buffer.append(row_num, line, Style::NoStyle);
+                row_num += 1;
+            }
+
+            // if we elided some lines, add an ellipsis
+            if let Some(_) = lines.next() {
+                buffer.append(row_num, "...", Style::NoStyle);
             }
+            emit_to_destination(&buffer.render(), level, &mut self.dst)?;
+        }
+        Ok(())
+    }
 
-            for snippet_data in output_vec.iter() {
-                let rendered_lines = snippet_data.render_lines();
-                for rendered_line in &rendered_lines {
-                    for styled_string in &rendered_line.text {
-                        self.dst.apply_style(lvl, &rendered_line.kind, styled_string.style)?;
-                        write!(&mut self.dst, "{}", styled_string.text)?;
-                        self.dst.reset_attrs()?;
+    fn emit_messages_old_school(&mut self, db: &DiagnosticBuilder) {
+        match self.emit_message_old_school(&db.span,
+                                           &db.message,
+                                           &db.code,
+                                           &db.level,
+                                           true) {
+            Ok(()) => {
+                for child in &db.children {
+                    let (span, show_snippet) = if child.span.primary_spans().is_empty() {
+                        (db.span.clone(), false)
+                    } else {
+                        (child.span.clone(), true)
+                    };
+
+                    match child.render_span {
+                        Some(FullSpan(_)) => {
+                            match self.emit_message_old_school(&span,
+                                                               &child.message,
+                                                               &None,
+                                                               &child.level,
+                                                               show_snippet) {
+                                Err(e) => panic!("failed to emit error: {}", e),
+                                _ => ()
+                            }
+                        },
+                        Some(Suggestion(ref cs)) => {
+                            match self.emit_suggestion_old_school(cs,
+                                                                  &child.level,
+                                                                  &child.message) {
+                                Err(e) => panic!("failed to emit error: {}", e),
+                                _ => ()
+                            }
+                        },
+                        None => {
+                            match self.emit_message_old_school(&span,
+                                                               &child.message,
+                                                               &None,
+                                                               &child.level,
+                                                               show_snippet) {
+                                Err(e) => panic!("failed to emit error: {}", e),
+                                _ => ()
+                            }
+                        }
                     }
-                    write!(&mut self.dst, "\n")?;
                 }
             }
+            Err(e) => panic!("failed to emit error: {}", e)
         }
-        else {
-            for span_label in msp.span_labels() {
-                snippet_data.push(span_label.span,
-                                  span_label.is_primary,
-                                  span_label.label);
-            }
-            let rendered_lines = snippet_data.render_lines();
-            for rendered_line in &rendered_lines {
-                for styled_string in &rendered_line.text {
-                    self.dst.apply_style(lvl, &rendered_line.kind, styled_string.style)?;
-                    write!(&mut self.dst, "{}", styled_string.text)?;
-                    self.dst.reset_attrs()?;
+    }
+
+    fn render_macro_backtrace_old_school(&mut self,
+                                         sp: &Span,
+                                         buffer: &mut StyledBuffer) -> io::Result<()> {
+        if let Some(ref cm) = self.cm {
+            for trace in cm.macro_backtrace(sp.clone()) {
+                let line_offset = buffer.num_lines();
+
+                let mut diag_string =
+                    format!("in this expansion of {}", trace.macro_decl_name);
+                if let Some(def_site_span) = trace.def_site_span {
+                    diag_string.push_str(
+                        &format!(" (defined in {})",
+                            cm.span_to_filename(def_site_span)));
                 }
-                write!(&mut self.dst, "\n")?;
+                let snippet = cm.span_to_string(trace.call_site);
+                buffer.append(line_offset, &format!("{} ", snippet), Style::NoStyle);
+                buffer.append(line_offset, "note", Style::Level(Level::Note));
+                buffer.append(line_offset, ": ", Style::NoStyle);
+                buffer.append(line_offset, &diag_string, Style::OldSchoolNoteText);
             }
         }
         Ok(())
     }
+}
 
-    fn print_macro_backtrace(&mut self,
-                             sp: Span)
-                             -> io::Result<()> {
-        for trace in self.cm.macro_backtrace(sp) {
-            let mut diag_string =
-                format!("in this expansion of {}", trace.macro_decl_name);
-            if let Some(def_site_span) = trace.def_site_span {
-                diag_string.push_str(
-                    &format!(" (defined in {})",
-                        self.cm.span_to_filename(def_site_span)));
-            }
-            let snippet = self.cm.span_to_string(trace.call_site);
-            print_diagnostic(&mut self.dst, &snippet, Note, &diag_string, None)?;
+fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
+    buffer.puts(line, col, "| ", Style::LineNumber);
+}
+
+fn draw_col_separator_no_space(buffer: &mut StyledBuffer, line: usize, col: usize) {
+    buffer.puts(line, col, "|", Style::LineNumber);
+}
+
+fn draw_note_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
+    buffer.puts(line, col, "= ", Style::LineNumber);
+}
+
+fn overlaps(a1: &Annotation, a2: &Annotation) -> bool {
+    (a2.start_col..a2.end_col).contains(a1.start_col) ||
+    (a1.start_col..a1.end_col).contains(a2.start_col)
+}
+
+fn emit_to_destination(rendered_buffer: &Vec<Vec<StyledString>>,
+        lvl: &Level,
+        dst: &mut Destination) -> io::Result<()> {
+    for line in rendered_buffer {
+        for part in line {
+            dst.apply_style(lvl.clone(), part.style)?;
+            write!(dst, "{}", part.text)?;
+            dst.reset_attrs()?;
         }
-        Ok(())
+        write!(dst, "\n")?;
     }
+    Ok(())
 }
 
 fn line_num_max_digits(line: &LineInfo) -> usize {
@@ -456,40 +968,6 @@ fn line_num_max_digits(line: &LineInfo) -> usize {
     digits
 }
 
-fn print_diagnostic(dst: &mut Destination,
-                    topic: &str,
-                    lvl: Level,
-                    msg: &str,
-                    code: Option<&str>)
-                    -> io::Result<()> {
-    if !topic.is_empty() {
-        let old_school = check_old_skool();
-        if !old_school {
-            write!(dst, "{}: ", topic)?;
-        }
-        else {
-            write!(dst, "{} ", topic)?;
-        }
-        dst.reset_attrs()?;
-    }
-    dst.start_attr(term::Attr::Bold)?;
-    dst.start_attr(term::Attr::ForegroundColor(lvl.color()))?;
-    write!(dst, "{}", lvl.to_string())?;
-    dst.reset_attrs()?;
-    write!(dst, ": ")?;
-    dst.start_attr(term::Attr::Bold)?;
-    write!(dst, "{}", msg)?;
-
-    if let Some(code) = code {
-        let style = term::Attr::ForegroundColor(term::color::BRIGHT_MAGENTA);
-        print_maybe_styled!(dst, style, " [{}]", code.clone())?;
-    }
-
-    dst.reset_attrs()?;
-    write!(dst, "\n")?;
-    Ok(())
-}
-
 #[cfg(unix)]
 fn stderr_isatty() -> bool {
     use libc;
@@ -513,7 +991,7 @@ fn stderr_isatty() -> bool {
     }
 }
 
-enum Destination {
+pub enum Destination {
     Terminal(Box<term::StderrTerminal>),
     Raw(Box<Write + Send>),
 }
@@ -528,35 +1006,39 @@ impl Destination {
 
     fn apply_style(&mut self,
                    lvl: Level,
-                   _kind: &RenderedLineKind,
                    style: Style)
                    -> io::Result<()> {
         match style {
-            Style::FileNameStyle |
-            Style::LineAndColumn => {
-            }
+            Style::FileNameStyle | Style::LineAndColumn => {}
             Style::LineNumber => {
-                self.start_attr(term::Attr::Bold)?;
-                self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_BLUE))?;
+                try!(self.start_attr(term::Attr::Bold));
+                try!(self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_BLUE)));
             }
-            Style::Quotation => {
+            Style::ErrorCode => {
+                try!(self.start_attr(term::Attr::Bold));
+                try!(self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_MAGENTA)));
             }
-            Style::OldSkoolNote => {
-                self.start_attr(term::Attr::Bold)?;
-                self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_GREEN))?;
+            Style::Quotation => {}
+            Style::OldSchoolNote => {
+                try!(self.start_attr(term::Attr::Bold));
+                try!(self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_GREEN)));
             }
-            Style::OldSkoolNoteText => {
-                self.start_attr(term::Attr::Bold)?;
+            Style::OldSchoolNoteText | Style::HeaderMsg => {
+                try!(self.start_attr(term::Attr::Bold));
             }
             Style::UnderlinePrimary | Style::LabelPrimary => {
-                self.start_attr(term::Attr::Bold)?;
-                self.start_attr(term::Attr::ForegroundColor(lvl.color()))?;
+                try!(self.start_attr(term::Attr::Bold));
+                try!(self.start_attr(term::Attr::ForegroundColor(lvl.color())));
             }
-            Style::UnderlineSecondary | Style::LabelSecondary => {
-                self.start_attr(term::Attr::Bold)?;
-                self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_BLUE))?;
+            Style::UnderlineSecondary |
+            Style::LabelSecondary => {
+                try!(self.start_attr(term::Attr::Bold));
+                try!(self.start_attr(term::Attr::ForegroundColor(term::color::BRIGHT_BLUE)));
             }
-            Style::NoStyle => {
+            Style::NoStyle => {}
+            Style::Level(l) => {
+                try!(self.start_attr(term::Attr::Bold));
+                try!(self.start_attr(term::Attr::ForegroundColor(l.color())));
             }
         }
         Ok(())
@@ -577,46 +1059,6 @@ impl Destination {
         }
         Ok(())
     }
-
-    fn print_maybe_styled(&mut self,
-                          args: fmt::Arguments,
-                          color: term::Attr,
-                          print_newline_at_end: bool)
-                          -> io::Result<()> {
-        match *self {
-            Terminal(ref mut t) => {
-                t.attr(color)?;
-                // If `msg` ends in a newline, we need to reset the color before
-                // the newline. We're making the assumption that we end up writing
-                // to a `LineBufferedWriter`, which means that emitting the reset
-                // after the newline ends up buffering the reset until we print
-                // another line or exit. Buffering the reset is a problem if we're
-                // sharing the terminal with any other programs (e.g. other rustc
-                // instances via `make -jN`).
-                //
-                // Note that if `msg` contains any internal newlines, this will
-                // result in the `LineBufferedWriter` flushing twice instead of
-                // once, which still leaves the opportunity for interleaved output
-                // to be miscolored. We assume this is rare enough that we don't
-                // have to worry about it.
-                t.write_fmt(args)?;
-                t.reset()?;
-                if print_newline_at_end {
-                    t.write_all(b"\n")
-                } else {
-                    Ok(())
-                }
-            }
-            Raw(ref mut w) => {
-                w.write_fmt(args)?;
-                if print_newline_at_end {
-                    w.write_all(b"\n")
-                } else {
-                    Ok(())
-                }
-            }
-        }
-    }
 }
 
 impl Write for Destination {
@@ -632,4 +1074,4 @@ impl Write for Destination {
             Raw(ref mut w) => w.flush(),
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 18fc826f9aa4b..6a48f65714cc5 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -49,6 +49,7 @@ use std::thread::panicking;
 pub mod emitter;
 pub mod snippet;
 pub mod registry;
+pub mod styled_buffer;
 
 use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION };
 use syntax_pos::{MacroBacktrace};
@@ -81,16 +82,6 @@ pub trait CodeMapper {
     fn macro_backtrace(&self, span: Span) -> Vec<MacroBacktrace>;
 }
 
-impl RenderSpan {
-    fn span(&self) -> &MultiSpan {
-        match *self {
-            FullSpan(ref msp) |
-            Suggestion(CodeSuggestion { ref msp, .. }) =>
-                msp
-        }
-    }
-}
-
 impl CodeSuggestion {
     /// Returns the assembled code suggestion.
     pub fn splice_lines(&self, cm: &CodeMapper) -> String {
@@ -238,7 +229,7 @@ impl<'a> DiagnosticBuilder<'a> {
             return;
         }
 
-        self.handler.emit.borrow_mut().emit_struct(&self);
+        self.handler.emitter.borrow_mut().emit(&self);
         self.cancel();
         self.handler.panic_if_treat_err_as_bug();
 
@@ -359,11 +350,20 @@ impl<'a> DiagnosticBuilder<'a> {
     fn new(handler: &'a Handler,
            level: Level,
            message: &str) -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder::new_with_code(handler, level, None, message)
+    }
+
+    /// Convenience function for internal use, clients should use one of the
+    /// struct_* methods on Handler.
+    fn new_with_code(handler: &'a Handler,
+           level: Level,
+           code: Option<String>,
+           message: &str) -> DiagnosticBuilder<'a> {
         DiagnosticBuilder {
             handler: handler,
             level: level,
             message: message.to_owned(),
-            code: None,
+            code: code,
             span: MultiSpan::new(),
             children: vec![],
         }
@@ -397,10 +397,10 @@ impl<'a> fmt::Debug for DiagnosticBuilder<'a> {
 impl<'a> Drop for DiagnosticBuilder<'a> {
     fn drop(&mut self) {
         if !panicking() && !self.cancelled() {
-            self.handler.emit.borrow_mut().emit(&MultiSpan::new(),
-                                                "Error constructed but not emitted",
-                                                None,
-                                                Bug);
+            let mut db = DiagnosticBuilder::new(self.handler,
+                                                Bug,
+                                                "Error constructed but not emitted");
+            db.emit();
             panic!();
         }
     }
@@ -411,7 +411,7 @@ impl<'a> Drop for DiagnosticBuilder<'a> {
 /// others log errors for later reporting.
 pub struct Handler {
     err_count: Cell<usize>,
-    emit: RefCell<Box<Emitter>>,
+    emitter: RefCell<Box<Emitter>>,
     pub can_emit_warnings: bool,
     treat_err_as_bug: bool,
     continue_after_error: Cell<bool>,
@@ -423,7 +423,7 @@ impl Handler {
                             registry: Option<registry::Registry>,
                             can_emit_warnings: bool,
                             treat_err_as_bug: bool,
-                            cm: Rc<CodeMapper>)
+                            cm: Option<Rc<CodeMapper>>)
                             -> Handler {
         let emitter = Box::new(EmitterWriter::stderr(color_config, registry, cm,
                                snippet::FormatMode::EnvironmentSelected));
@@ -435,7 +435,7 @@ impl Handler {
                         e: Box<Emitter>) -> Handler {
         Handler {
             err_count: Cell::new(0),
-            emit: RefCell::new(e),
+            emitter: RefCell::new(e),
             can_emit_warnings: can_emit_warnings,
             treat_err_as_bug: treat_err_as_bug,
             continue_after_error: Cell::new(true),
@@ -588,7 +588,7 @@ impl Handler {
         self.bump_err_count();
     }
     pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
-        self.emit.borrow_mut().emit(&sp.into(), msg, None, Note);
+        self.emit(&sp.into(), msg, Note);
     }
     pub fn span_unimpl<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
         self.span_bug(sp, &format!("unimplemented {}", msg));
@@ -597,7 +597,10 @@ impl Handler {
         if self.treat_err_as_bug {
             self.bug(msg);
         }
-        self.emit.borrow_mut().emit(&MultiSpan::new(), msg, None, Fatal);
+        let mut db = DiagnosticBuilder::new(self,
+                                            Fatal,
+                                            msg);
+        db.emit();
         self.bump_err_count();
         FatalError
     }
@@ -605,17 +608,29 @@ impl Handler {
         if self.treat_err_as_bug {
             self.bug(msg);
         }
-        self.emit.borrow_mut().emit(&MultiSpan::new(), msg, None, Error);
+        let mut db = DiagnosticBuilder::new(self,
+                                            Error,
+                                            msg);
+        db.emit();
         self.bump_err_count();
     }
     pub fn warn(&self, msg: &str) {
-        self.emit.borrow_mut().emit(&MultiSpan::new(), msg, None, Warning);
+        let mut db = DiagnosticBuilder::new(self,
+                                            Warning,
+                                            msg);
+        db.emit();
     }
     pub fn note_without_error(&self, msg: &str) {
-        self.emit.borrow_mut().emit(&MultiSpan::new(), msg, None, Note);
+        let mut db = DiagnosticBuilder::new(self,
+                                            Note,
+                                            msg);
+        db.emit();
     }
     pub fn bug(&self, msg: &str) -> ! {
-        self.emit.borrow_mut().emit(&MultiSpan::new(), msg, None, Bug);
+        let mut db = DiagnosticBuilder::new(self,
+                                            Bug,
+                                            msg);
+        db.emit();
         panic!(ExplicitBug);
     }
     pub fn unimpl(&self, msg: &str) -> ! {
@@ -661,7 +676,9 @@ impl Handler {
                 msg: &str,
                 lvl: Level) {
         if lvl == Warning && !self.can_emit_warnings { return }
-        self.emit.borrow_mut().emit(&msp, msg, None, lvl);
+        let mut db = DiagnosticBuilder::new(self, lvl, msg);
+        db.set_span(msp.clone());
+        db.emit();
         if !self.continue_after_error.get() { self.abort_if_errors(); }
     }
     pub fn emit_with_code(&self,
@@ -670,7 +687,12 @@ impl Handler {
                           code: &str,
                           lvl: Level) {
         if lvl == Warning && !self.can_emit_warnings { return }
-        self.emit.borrow_mut().emit(&msp, msg, Some(code), lvl);
+        let mut db = DiagnosticBuilder::new_with_code(self,
+                                                      lvl,
+                                                      Some(code.to_owned()),
+                                                      msg);
+        db.set_span(msp.clone());
+        db.emit();
         if !self.continue_after_error.get() { self.abort_if_errors(); }
     }
 }
@@ -734,13 +756,13 @@ pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T where
 ///
 /// FIXME(#33240)
 #[cfg(not(test))]
-pub fn check_old_skool() -> bool {
+pub fn check_old_school() -> bool {
     use std::env;
     env::var("RUST_NEW_ERROR_FORMAT").is_err()
 }
 
 /// For unit tests, use the new format.
 #[cfg(test)]
-pub fn check_old_skool() -> bool {
+pub fn check_old_school() -> bool {
     false
 }
diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs
index 33f40ffc71a9f..2f94a7f6832fe 100644
--- a/src/librustc_errors/snippet.rs
+++ b/src/librustc_errors/snippet.rs
@@ -10,12 +10,10 @@
 
 // Code for annotating snippets.
 
-use syntax_pos::{Span, FileMap, CharPos, LineInfo};
-use check_old_skool;
+use syntax_pos::{Span, FileMap};
 use CodeMapper;
-use std::cmp;
 use std::rc::Rc;
-use std::mem;
+use {Level};
 
 #[derive(Clone)]
 pub enum FormatMode {
@@ -49,37 +47,31 @@ pub struct FileInfo {
     format_mode: FormatMode,
 }
 
-#[derive(Clone, Debug)]
-struct Line {
-    line_index: usize,
-    annotations: Vec<Annotation>,
+#[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
+pub struct Line {
+    pub line_index: usize,
+    pub annotations: Vec<Annotation>,
 }
 
 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
-struct Annotation {
+pub struct Annotation {
     /// Start column, 0-based indexing -- counting *characters*, not
     /// utf-8 bytes. Note that it is important that this field goes
     /// first, so that when we sort, we sort orderings by start
     /// column.
-    start_col: usize,
+    pub start_col: usize,
 
     /// End column within the line (exclusive)
-    end_col: usize,
+    pub end_col: usize,
 
     /// Is this annotation derived from primary span
-    is_primary: bool,
+    pub is_primary: bool,
 
     /// Is this a large span minimized down to a smaller span
-    is_minimized: bool,
+    pub is_minimized: bool,
 
     /// Optional label to display adjacent to the annotation.
-    label: Option<String>,
-}
-
-#[derive(Debug)]
-pub struct RenderedLine {
-    pub text: Vec<StyledString>,
-    pub kind: RenderedLineKind,
+    pub label: Option<String>,
 }
 
 #[derive(Debug)]
@@ -88,14 +80,9 @@ pub struct StyledString {
     pub style: Style,
 }
 
-#[derive(Debug)]
-pub struct StyledBuffer {
-    text: Vec<Vec<char>>,
-    styles: Vec<Vec<Style>>
-}
-
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum Style {
+    HeaderMsg,
     FileNameStyle,
     LineAndColumn,
     LineNumber,
@@ -104,813 +91,9 @@ pub enum Style {
     UnderlineSecondary,
     LabelPrimary,
     LabelSecondary,
-    OldSkoolNoteText,
-    OldSkoolNote,
+    OldSchoolNoteText,
+    OldSchoolNote,
     NoStyle,
-}
-
-#[derive(Debug, Clone)]
-pub enum RenderedLineKind {
-    PrimaryFileName,
-    OtherFileName,
-    SourceText {
-        file: Rc<FileMap>,
-        line_index: usize,
-    },
-    Annotations,
-    Elision,
-}
-
-impl SnippetData {
-    pub fn new(codemap: Rc<CodeMapper>,
-               primary_span: Option<Span>,
-               format_mode: FormatMode) // (*)
-               -> Self {
-        // (*) The primary span indicates the file that must appear
-        // first, and which will have a line number etc in its
-        // name. Outside of tests, this is always `Some`, but for many
-        // tests it's not relevant to test this portion of the logic,
-        // and it's tedious to pick a primary span (read: tedious to
-        // port older tests that predate the existence of a primary
-        // span).
-
-        debug!("SnippetData::new(primary_span={:?})", primary_span);
-
-        let mut data = SnippetData {
-            codemap: codemap.clone(),
-            files: vec![],
-            format_mode: format_mode.clone()
-        };
-        if let Some(primary_span) = primary_span {
-            let lo = codemap.lookup_char_pos(primary_span.lo);
-            data.files.push(
-                FileInfo {
-                    file: lo.file,
-                    primary_span: Some(primary_span),
-                    lines: vec![],
-                    format_mode: format_mode.clone(),
-                });
-        }
-        data
-    }
-
-    pub fn push(&mut self, span: Span, is_primary: bool, label: Option<String>) {
-        debug!("SnippetData::push(span={:?}, is_primary={}, label={:?})",
-               span, is_primary, label);
-
-        let file_lines = match self.codemap.span_to_lines(span) {
-            Ok(file_lines) => file_lines,
-            Err(_) => {
-                // ignore unprintable spans completely.
-                return;
-            }
-        };
-
-        self.file(&file_lines.file)
-            .push_lines(&file_lines.lines, is_primary, label);
-    }
-
-    fn file(&mut self, file_map: &Rc<FileMap>) -> &mut FileInfo {
-        let index = self.files.iter().position(|f| f.file.name == file_map.name);
-        if let Some(index) = index {
-            return &mut self.files[index];
-        }
-
-        self.files.push(
-            FileInfo {
-                file: file_map.clone(),
-                lines: vec![],
-                primary_span: None,
-                format_mode: self.format_mode.clone()
-            });
-        self.files.last_mut().unwrap()
-    }
-
-    pub fn render_lines(&self) -> Vec<RenderedLine> {
-        debug!("SnippetData::render_lines()");
-
-        let mut rendered_lines: Vec<_> =
-            self.files.iter()
-                      .flat_map(|f| f.render_file_lines(&self.codemap))
-                      .collect();
-        prepend_prefixes(&mut rendered_lines, &self.format_mode);
-        trim_lines(&mut rendered_lines);
-        rendered_lines
-    }
-}
-
-pub trait StringSource {
-    fn make_string(self) -> String;
-}
-
-impl StringSource for String {
-    fn make_string(self) -> String {
-        self
-    }
-}
-
-impl StringSource for Vec<char> {
-    fn make_string(self) -> String {
-        self.into_iter().collect()
-    }
-}
-
-impl<S> From<(S, Style, RenderedLineKind)> for RenderedLine
-    where S: StringSource
-{
-    fn from((text, style, kind): (S, Style, RenderedLineKind)) -> Self {
-        RenderedLine {
-            text: vec![StyledString {
-                text: text.make_string(),
-                style: style,
-            }],
-            kind: kind,
-        }
-    }
-}
-
-impl<S1,S2> From<(S1, Style, S2, Style, RenderedLineKind)> for RenderedLine
-    where S1: StringSource, S2: StringSource
-{
-    fn from(tuple: (S1, Style, S2, Style, RenderedLineKind)) -> Self {
-        let (text1, style1, text2, style2, kind) = tuple;
-        RenderedLine {
-            text: vec![
-                StyledString {
-                    text: text1.make_string(),
-                    style: style1,
-                },
-                StyledString {
-                    text: text2.make_string(),
-                    style: style2,
-                }
-            ],
-            kind: kind,
-        }
-    }
-}
-
-impl RenderedLine {
-    fn trim_last(&mut self) {
-        if let Some(last_text) = self.text.last_mut() {
-            let len = last_text.text.trim_right().len();
-            last_text.text.truncate(len);
-        }
-    }
-}
-
-impl RenderedLineKind {
-    fn prefix(&self) -> StyledString {
-        match *self {
-            RenderedLineKind::SourceText { file: _, line_index } =>
-                StyledString {
-                    text: format!("{}", line_index + 1),
-                    style: Style::LineNumber,
-                },
-            RenderedLineKind::Elision =>
-                StyledString {
-                    text: String::from("..."),
-                    style: Style::LineNumber,
-                },
-            RenderedLineKind::PrimaryFileName |
-            RenderedLineKind::OtherFileName |
-            RenderedLineKind::Annotations =>
-                StyledString {
-                    text: String::from(""),
-                    style: Style::LineNumber,
-                },
-        }
-    }
-}
-
-impl StyledBuffer {
-    fn new() -> StyledBuffer {
-        StyledBuffer { text: vec![], styles: vec![] }
-    }
-
-    fn render(&self, source_kind: RenderedLineKind) -> Vec<RenderedLine> {
-        let mut output: Vec<RenderedLine> = vec![];
-        let mut styled_vec: Vec<StyledString> = vec![];
-
-        for (row, row_style) in self.text.iter().zip(&self.styles) {
-            let mut current_style = Style::NoStyle;
-            let mut current_text = String::new();
-
-            for (&c, &s) in row.iter().zip(row_style) {
-                if s != current_style {
-                    if !current_text.is_empty() {
-                        styled_vec.push(StyledString { text: current_text, style: current_style });
-                    }
-                    current_style = s;
-                    current_text = String::new();
-                }
-                current_text.push(c);
-            }
-            if !current_text.is_empty() {
-                styled_vec.push(StyledString { text: current_text, style: current_style });
-            }
-
-            if output.is_empty() {
-                //We know our first output line is source and the rest are highlights and labels
-                output.push(RenderedLine { text: styled_vec, kind: source_kind.clone() });
-            } else {
-                output.push(RenderedLine { text: styled_vec, kind: RenderedLineKind::Annotations });
-            }
-            styled_vec = vec![];
-        }
-
-        output
-    }
-
-    fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
-        while line >= self.text.len() {
-            self.text.push(vec![]);
-            self.styles.push(vec![]);
-        }
-
-        if col < self.text[line].len() {
-            self.text[line][col] = chr;
-            self.styles[line][col] = style;
-        } else {
-            let mut i = self.text[line].len();
-            while i < col {
-                let s = match self.text[0].get(i) {
-                    Some(&'\t') => '\t',
-                    _ => ' '
-                };
-                self.text[line].push(s);
-                self.styles[line].push(Style::NoStyle);
-                i += 1;
-            }
-            self.text[line].push(chr);
-            self.styles[line].push(style);
-        }
-    }
-
-    fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
-        let mut n = col;
-        for c in string.chars() {
-            self.putc(line, n, c, style);
-            n += 1;
-        }
-    }
-
-    fn set_style(&mut self, line: usize, col: usize, style: Style) {
-        if self.styles.len() > line && self.styles[line].len() > col {
-            self.styles[line][col] = style;
-        }
-    }
-
-    fn append(&mut self, line: usize, string: &str, style: Style) {
-        if line >= self.text.len() {
-            self.puts(line, 0, string, style);
-        } else {
-            let col = self.text[line].len();
-            self.puts(line, col, string, style);
-        }
-    }
-}
-
-impl FileInfo {
-    fn push_lines(&mut self,
-                  lines: &[LineInfo],
-                  is_primary: bool,
-                  label: Option<String>) {
-        assert!(lines.len() > 0);
-
-        // If a span covers multiple lines, we reduce it to a single
-        // point at the start of the span. This means that instead
-        // of producing output like this:
-        //
-        // ```
-        // --> foo.rs:2:1
-        // 2   |> fn conflicting_items<'grammar>(state: &LR0State<'grammar>)
-        //     |> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-        // 3   |>                               -> Set<LR0Item<'grammar>>
-        //     |> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-        // (and so on)
-        // ```
-        //
-        // we produce:
-        //
-        // ```
-        // --> foo.rs:2:1
-        // 2   |> fn conflicting_items<'grammar>(state: &LR0State<'grammar>)
-        //        ^
-        // ```
-        //
-        // Basically, although this loses information, multi-line spans just
-        // never look good.
-
-        let (line, start_col, mut end_col, is_minimized) = if lines.len() == 1 {
-            (lines[0].line_index, lines[0].start_col, lines[0].end_col, false)
-        } else {
-            (lines[0].line_index, lines[0].start_col, CharPos(lines[0].start_col.0 + 1), true)
-        };
-
-        // Watch out for "empty spans". If we get a span like 6..6, we
-        // want to just display a `^` at 6, so convert that to
-        // 6..7. This is degenerate input, but it's best to degrade
-        // gracefully -- and the parser likes to suply a span like
-        // that for EOF, in particular.
-        if start_col == end_col {
-            end_col.0 += 1;
-        }
-
-        let index = self.ensure_source_line(line);
-        self.lines[index].push_annotation(start_col,
-                                          end_col,
-                                          is_primary,
-                                          is_minimized,
-                                          label);
-    }
-
-    /// Ensure that we have a `Line` struct corresponding to
-    /// `line_index` in the file. If we already have some other lines,
-    /// then this will add the intervening lines to ensure that we
-    /// have a complete snippet. (Note that when we finally display,
-    /// some of those lines may be elided.)
-    fn ensure_source_line(&mut self, line_index: usize) -> usize {
-        if self.lines.is_empty() {
-            self.lines.push(Line::new(line_index));
-            return 0;
-        }
-
-        // Find the range of lines we have thus far.
-        let first_line_index = self.lines.first().unwrap().line_index;
-        let last_line_index = self.lines.last().unwrap().line_index;
-        assert!(first_line_index <= last_line_index);
-
-        // If the new line is lower than all the lines we have thus
-        // far, then insert the new line and any intervening lines at
-        // the front. In a silly attempt at micro-optimization, we
-        // don't just call `insert` repeatedly, but instead make a new
-        // (empty) vector, pushing the new lines onto it, and then
-        // appending the old vector.
-        if line_index < first_line_index {
-            let lines = mem::replace(&mut self.lines, vec![]);
-            self.lines.extend(
-                (line_index .. first_line_index)
-                    .map(|line| Line::new(line))
-                    .chain(lines));
-            return 0;
-        }
-
-        // If the new line comes after the ones we have so far, insert
-        // lines for it.
-        if line_index > last_line_index {
-            self.lines.extend(
-                (last_line_index+1 .. line_index+1)
-                    .map(|line| Line::new(line)));
-            return self.lines.len() - 1;
-        }
-
-        // Otherwise it should already exist.
-        return line_index - first_line_index;
-    }
-
-    fn render_file_lines(&self, codemap: &Rc<CodeMapper>) -> Vec<RenderedLine> {
-        let old_school = match self.format_mode {
-            FormatMode::OriginalErrorFormat => true,
-            FormatMode::NewErrorFormat => false,
-            FormatMode::EnvironmentSelected => check_old_skool()
-        };
-
-        // As a first step, we elide any instance of more than one
-        // continuous unannotated line.
-
-        let mut lines_iter = self.lines.iter();
-        let mut output = vec![];
-
-        // First insert the name of the file.
-        if !old_school {
-            match self.primary_span {
-                Some(span) => {
-                    let lo = codemap.lookup_char_pos(span.lo);
-                    output.push(RenderedLine {
-                        text: vec![StyledString {
-                            text: lo.file.name.clone(),
-                            style: Style::FileNameStyle,
-                        }, StyledString {
-                            text: format!(":{}:{}", lo.line, lo.col.0 + 1),
-                            style: Style::LineAndColumn,
-                        }],
-                        kind: RenderedLineKind::PrimaryFileName,
-                    });
-                    output.push(RenderedLine {
-                        text: vec![StyledString {
-                            text: "".to_string(),
-                            style: Style::FileNameStyle,
-                        }],
-                        kind: RenderedLineKind::Annotations,
-                    });
-                }
-                None => {
-                    output.push(RenderedLine {
-                        text: vec![StyledString {
-                            text: self.file.name.clone(),
-                            style: Style::FileNameStyle,
-                        }],
-                        kind: RenderedLineKind::OtherFileName,
-                    });
-                    output.push(RenderedLine {
-                        text: vec![StyledString {
-                            text: "".to_string(),
-                            style: Style::FileNameStyle,
-                        }],
-                        kind: RenderedLineKind::Annotations,
-                    });
-                }
-            }
-        }
-
-        let mut next_line = lines_iter.next();
-        while next_line.is_some() {
-            // Consume lines with annotations.
-            while let Some(line) = next_line {
-                if line.annotations.is_empty() { break; }
-
-                let mut rendered_lines = self.render_line(line);
-                assert!(!rendered_lines.is_empty());
-                if old_school {
-                    match self.primary_span {
-                        Some(span) => {
-                            let lo = codemap.lookup_char_pos(span.lo);
-                            let hi = codemap.lookup_char_pos(span.hi);
-                            //Before each secondary line in old skool-mode, print the label
-                            //as an old-style note
-                            if !line.annotations[0].is_primary {
-                                if let Some(ann) = line.annotations[0].label.clone() {
-                                    output.push(RenderedLine {
-                                        text: vec![StyledString {
-                                            text: lo.file.name.clone(),
-                                            style: Style::FileNameStyle,
-                                        }, StyledString {
-                                            text: format!(":{}:{}: {}:{} ", lo.line, lo.col.0 + 1,
-                                                hi.line, hi.col.0+1),
-                                            style: Style::LineAndColumn,
-                                        }, StyledString {
-                                            text: format!("note: "),
-                                            style: Style::OldSkoolNote,
-                                        }, StyledString {
-                                            text: format!("{}", ann),
-                                            style: Style::OldSkoolNoteText,
-                                        }],
-                                        kind: RenderedLineKind::Annotations,
-                                    });
-                                }
-                            }
-                            rendered_lines[0].text.insert(0, StyledString {
-                                text: format!(":{} ", lo.line),
-                                style: Style::LineAndColumn,
-                            });
-                            rendered_lines[0].text.insert(0, StyledString {
-                                text: lo.file.name.clone(),
-                                style: Style::FileNameStyle,
-                            });
-                            let gap_amount =
-                                rendered_lines[0].text[0].text.len() +
-                                rendered_lines[0].text[1].text.len();
-                            assert!(rendered_lines.len() >= 2,
-                                    "no annotations resulted from: {:?}",
-                                    line);
-                            for i in 1..rendered_lines.len() {
-                                rendered_lines[i].text.insert(0, StyledString {
-                                    text: vec![" "; gap_amount].join(""),
-                                    style: Style::NoStyle
-                                });
-                            }
-                        }
-                        _ =>()
-                    }
-                }
-                output.append(&mut rendered_lines);
-                next_line = lines_iter.next();
-            }
-
-            // Emit lines without annotations, but only if they are
-            // followed by a line with an annotation.
-            let unannotated_line = next_line;
-            let mut unannotated_lines = 0;
-            while let Some(line) = next_line {
-                if !line.annotations.is_empty() { break; }
-                unannotated_lines += 1;
-                next_line = lines_iter.next();
-            }
-            if unannotated_lines > 1 {
-                output.push(RenderedLine::from((String::new(),
-                                                Style::NoStyle,
-                                                RenderedLineKind::Elision)));
-            } else if let Some(line) = unannotated_line {
-                output.append(&mut self.render_line(line));
-            }
-        }
-
-        output
-    }
-
-    fn render_line(&self, line: &Line) -> Vec<RenderedLine> {
-        let old_school = match self.format_mode {
-            FormatMode::OriginalErrorFormat => true,
-            FormatMode::NewErrorFormat => false,
-            FormatMode::EnvironmentSelected => check_old_skool()
-        };
-
-        let source_string = self.file.get_line(line.line_index)
-                                     .unwrap_or("");
-        let source_kind = RenderedLineKind::SourceText {
-            file: self.file.clone(),
-            line_index: line.line_index,
-        };
-
-        let mut styled_buffer = StyledBuffer::new();
-
-        // First create the source line we will highlight.
-        styled_buffer.append(0, &source_string, Style::Quotation);
-
-        if line.annotations.is_empty() {
-            return styled_buffer.render(source_kind);
-        }
-
-        // We want to display like this:
-        //
-        //      vec.push(vec.pop().unwrap());
-        //      ---      ^^^               _ previous borrow ends here
-        //      |        |
-        //      |        error occurs here
-        //      previous borrow of `vec` occurs here
-        //
-        // But there are some weird edge cases to be aware of:
-        //
-        //      vec.push(vec.pop().unwrap());
-        //      --------                    - previous borrow ends here
-        //      ||
-        //      |this makes no sense
-        //      previous borrow of `vec` occurs here
-        //
-        // For this reason, we group the lines into "highlight lines"
-        // and "annotations lines", where the highlight lines have the `~`.
-
-        //let mut highlight_line = Self::whitespace(&source_string);
-
-        // Sort the annotations by (start, end col)
-        let mut annotations = line.annotations.clone();
-        annotations.sort();
-
-        // Next, create the highlight line.
-        for annotation in &annotations {
-            if old_school {
-                for p in annotation.start_col .. annotation.end_col {
-                    if p == annotation.start_col {
-                        styled_buffer.putc(1, p, '^',
-                            if annotation.is_primary {
-                                Style::UnderlinePrimary
-                            } else {
-                                Style::OldSkoolNote
-                            });
-                    }
-                    else {
-                        styled_buffer.putc(1, p, '~',
-                            if annotation.is_primary {
-                                Style::UnderlinePrimary
-                            } else {
-                                Style::OldSkoolNote
-                            });
-                    }
-                }
-            }
-            else {
-                for p in annotation.start_col .. annotation.end_col {
-                    if annotation.is_primary {
-                        styled_buffer.putc(1, p, '^', Style::UnderlinePrimary);
-                        if !annotation.is_minimized {
-                            styled_buffer.set_style(0, p, Style::UnderlinePrimary);
-                        }
-                    } else {
-                        styled_buffer.putc(1, p, '-', Style::UnderlineSecondary);
-                        if !annotation.is_minimized {
-                            styled_buffer.set_style(0, p, Style::UnderlineSecondary);
-                        }
-                    }
-                }
-            }
-        }
-
-        // Now we are going to write labels in. To start, we'll exclude
-        // the annotations with no labels.
-        let (labeled_annotations, unlabeled_annotations): (Vec<_>, _) =
-            annotations.into_iter()
-                       .partition(|a| a.label.is_some());
-
-        // If there are no annotations that need text, we're done.
-        if labeled_annotations.is_empty() {
-            return styled_buffer.render(source_kind);
-        }
-        if old_school {
-            return styled_buffer.render(source_kind);
-        }
-
-        // Now add the text labels. We try, when possible, to stick the rightmost
-        // annotation at the end of the highlight line:
-        //
-        //      vec.push(vec.pop().unwrap());
-        //      ---      ---               - previous borrow ends here
-        //
-        // But sometimes that's not possible because one of the other
-        // annotations overlaps it. For example, from the test
-        // `span_overlap_label`, we have the following annotations
-        // (written on distinct lines for clarity):
-        //
-        //      fn foo(x: u32) {
-        //      --------------
-        //             -
-        //
-        // In this case, we can't stick the rightmost-most label on
-        // the highlight line, or we would get:
-        //
-        //      fn foo(x: u32) {
-        //      -------- x_span
-        //      |
-        //      fn_span
-        //
-        // which is totally weird. Instead we want:
-        //
-        //      fn foo(x: u32) {
-        //      --------------
-        //      |      |
-        //      |      x_span
-        //      fn_span
-        //
-        // which is...less weird, at least. In fact, in general, if
-        // the rightmost span overlaps with any other span, we should
-        // use the "hang below" version, so we can at least make it
-        // clear where the span *starts*.
-        let mut labeled_annotations = &labeled_annotations[..];
-        match labeled_annotations.split_last().unwrap() {
-            (last, previous) => {
-                if previous.iter()
-                           .chain(&unlabeled_annotations)
-                           .all(|a| !overlaps(a, last))
-                {
-                    // append the label afterwards; we keep it in a separate
-                    // string
-                    let highlight_label: String = format!(" {}", last.label.as_ref().unwrap());
-                    if last.is_primary {
-                        styled_buffer.append(1, &highlight_label, Style::LabelPrimary);
-                    } else {
-                        styled_buffer.append(1, &highlight_label, Style::LabelSecondary);
-                    }
-                    labeled_annotations = previous;
-                }
-            }
-        }
-
-        // If that's the last annotation, we're done
-        if labeled_annotations.is_empty() {
-            return styled_buffer.render(source_kind);
-        }
-
-        for (index, annotation) in labeled_annotations.iter().enumerate() {
-            // Leave:
-            // - 1 extra line
-            // - One line for each thing that comes after
-            let comes_after = labeled_annotations.len() - index - 1;
-            let blank_lines = 3 + comes_after;
-
-            // For each blank line, draw a `|` at our column. The
-            // text ought to be long enough for this.
-            for index in 2..blank_lines {
-                if annotation.is_primary {
-                    styled_buffer.putc(index, annotation.start_col, '|', Style::UnderlinePrimary);
-                } else {
-                    styled_buffer.putc(index, annotation.start_col, '|', Style::UnderlineSecondary);
-                }
-            }
-
-            if annotation.is_primary {
-                styled_buffer.puts(blank_lines, annotation.start_col,
-                    annotation.label.as_ref().unwrap(), Style::LabelPrimary);
-            } else {
-                styled_buffer.puts(blank_lines, annotation.start_col,
-                    annotation.label.as_ref().unwrap(), Style::LabelSecondary);
-            }
-        }
-
-        styled_buffer.render(source_kind)
-    }
-}
-
-fn prepend_prefixes(rendered_lines: &mut [RenderedLine], format_mode: &FormatMode) {
-    let old_school = match *format_mode {
-        FormatMode::OriginalErrorFormat => true,
-        FormatMode::NewErrorFormat => false,
-        FormatMode::EnvironmentSelected => check_old_skool()
-    };
-    if old_school {
-        return;
-    }
-
-    let prefixes: Vec<_> =
-        rendered_lines.iter()
-                      .map(|rl| rl.kind.prefix())
-                      .collect();
-
-    // find the max amount of spacing we need; add 1 to
-    // p.text.len() to leave space between the prefix and the
-    // source text
-    let padding_len =
-        prefixes.iter()
-                .map(|p| if p.text.len() == 0 { 0 } else { p.text.len() + 1 })
-                .max()
-                .unwrap_or(0);
-
-    // Ensure we insert at least one character of padding, so that the
-    // `-->` arrows can fit etc.
-    let padding_len = cmp::max(padding_len, 1);
-
-    for (mut prefix, line) in prefixes.into_iter().zip(rendered_lines) {
-        let extra_spaces = (prefix.text.len() .. padding_len).map(|_| ' ');
-        prefix.text.extend(extra_spaces);
-        match line.kind {
-            RenderedLineKind::Elision => {
-                line.text.insert(0, prefix);
-            }
-            RenderedLineKind::PrimaryFileName => {
-                //   --> filename
-                // 22 |>
-                //   ^
-                //   padding_len
-                let dashes = (0..padding_len - 1).map(|_| ' ')
-                                                 .chain(Some('-'))
-                                                 .chain(Some('-'))
-                                                 .chain(Some('>'))
-                                                 .chain(Some(' '));
-                line.text.insert(0, StyledString {text: dashes.collect(),
-                                                  style: Style::LineNumber})
-            }
-            RenderedLineKind::OtherFileName => {
-                //   ::: filename
-                // 22 |>
-                //   ^
-                //   padding_len
-                let dashes = (0..padding_len - 1).map(|_| ' ')
-                                                 .chain(Some(':'))
-                                                 .chain(Some(':'))
-                                                 .chain(Some(':'))
-                                                 .chain(Some(' '));
-                line.text.insert(0, StyledString {text: dashes.collect(),
-                                                  style: Style::LineNumber})
-            }
-            _ => {
-                line.text.insert(0, prefix);
-                line.text.insert(1, StyledString {text: String::from("|> "),
-                                                  style: Style::LineNumber})
-            }
-        }
-    }
-}
-
-fn trim_lines(rendered_lines: &mut [RenderedLine]) {
-    for line in rendered_lines {
-        while !line.text.is_empty() {
-            line.trim_last();
-            if line.text.last().unwrap().text.is_empty() {
-                line.text.pop();
-            } else {
-                break;
-            }
-        }
-    }
-}
-
-impl Line {
-    fn new(line_index: usize) -> Line {
-        Line {
-            line_index: line_index,
-            annotations: vec![]
-        }
-    }
-
-    fn push_annotation(&mut self,
-                       start: CharPos,
-                       end: CharPos,
-                       is_primary: bool,
-                       is_minimized: bool,
-                       label: Option<String>) {
-        self.annotations.push(Annotation {
-            start_col: start.0,
-            end_col: end.0,
-            is_primary: is_primary,
-            is_minimized: is_minimized,
-            label: label,
-        });
-    }
-}
-
-fn overlaps(a1: &Annotation,
-            a2: &Annotation)
-            -> bool
-{
-    (a2.start_col .. a2.end_col).contains(a1.start_col) ||
-        (a1.start_col .. a1.end_col).contains(a2.start_col)
-}
+    ErrorCode,
+    Level(Level),
+}
\ No newline at end of file
diff --git a/src/librustc_errors/styled_buffer.rs b/src/librustc_errors/styled_buffer.rs
new file mode 100644
index 0000000000000..9768b68619e79
--- /dev/null
+++ b/src/librustc_errors/styled_buffer.rs
@@ -0,0 +1,146 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Code for creating styled buffers
+
+use snippet::{Style, StyledString};
+
+#[derive(Debug)]
+pub struct StyledBuffer {
+    text: Vec<Vec<char>>,
+    styles: Vec<Vec<Style>>,
+}
+
+impl StyledBuffer {
+    pub fn new() -> StyledBuffer {
+        StyledBuffer {
+            text: vec![],
+            styles: vec![],
+        }
+    }
+
+    pub fn copy_tabs(&mut self, row: usize) {
+        if row < self.text.len() {
+            for i in row+1..self.text.len() {
+                for j in 0..self.text[i].len() {
+                    if self.text[row].len() > j &&
+                       self.text[row][j] == '\t' &&
+                       self.text[i][j] == ' ' {
+                        self.text[i][j] = '\t';
+                    }
+                }
+            }
+        }
+    }
+
+    pub fn render(&mut self) -> Vec<Vec<StyledString>> {
+        let mut output: Vec<Vec<StyledString>> = vec![];
+        let mut styled_vec: Vec<StyledString> = vec![];
+
+        //before we render, do a little patch-up work to support tabs
+        self.copy_tabs(3);
+
+        for (row, row_style) in self.text.iter().zip(&self.styles) {
+            let mut current_style = Style::NoStyle;
+            let mut current_text = String::new();
+
+            for (&c, &s) in row.iter().zip(row_style) {
+                if s != current_style {
+                    if !current_text.is_empty() {
+                        styled_vec.push(StyledString {
+                            text: current_text,
+                            style: current_style,
+                        });
+                    }
+                    current_style = s;
+                    current_text = String::new();
+                }
+                current_text.push(c);
+            }
+            if !current_text.is_empty() {
+                styled_vec.push(StyledString {
+                    text: current_text,
+                    style: current_style,
+                });
+            }
+
+            // We're done with the row, push and keep going
+            output.push(styled_vec);
+
+            styled_vec = vec![];
+        }
+
+        output
+    }
+
+    fn ensure_lines(&mut self, line: usize) {
+        while line >= self.text.len() {
+            self.text.push(vec![]);
+            self.styles.push(vec![]);
+        }
+    }
+
+    pub fn putc(&mut self, line: usize, col: usize, chr: char, style: Style) {
+        self.ensure_lines(line);
+        if col < self.text[line].len() {
+            self.text[line][col] = chr;
+            self.styles[line][col] = style;
+        } else {
+            let mut i = self.text[line].len();
+            while i < col {
+                self.text[line].push(' ');
+                self.styles[line].push(Style::NoStyle);
+                i += 1;
+            }
+            self.text[line].push(chr);
+            self.styles[line].push(style);
+        }
+    }
+
+    pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) {
+        let mut n = col;
+        for c in string.chars() {
+            self.putc(line, n, c, style);
+            n += 1;
+        }
+    }
+
+    pub fn set_style(&mut self, line: usize, col: usize, style: Style) {
+        if self.styles.len() > line && self.styles[line].len() > col {
+            self.styles[line][col] = style;
+        }
+    }
+
+    pub fn prepend(&mut self, line: usize, string: &str, style: Style) {
+        self.ensure_lines(line);
+        let string_len = string.len();
+
+        // Push the old content over to make room for new content
+        for _ in 0..string_len {
+            self.styles[line].insert(0, Style::NoStyle);
+            self.text[line].insert(0, ' ');
+        }
+
+        self.puts(line, 0, string, style);
+    }
+
+    pub fn append(&mut self, line: usize, string: &str, style: Style) {
+        if line >= self.text.len() {
+            self.puts(line, 0, string, style);
+        } else {
+            let col = self.text[line].len();
+            self.puts(line, col, string, style);
+        }
+    }
+
+    pub fn num_lines(&self) -> usize {
+        self.text.len()
+    }
+}
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 071960f1944cf..33cffa8a48013 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -19,8 +19,8 @@ use llvm::SMDiagnosticRef;
 use {CrateTranslation, ModuleTranslation};
 use util::common::time;
 use util::common::path2cstr;
-use errors::{self, Handler, Level, RenderSpan};
-use errors::emitter::CoreEmitter;
+use errors::{self, Handler, Level, DiagnosticBuilder};
+use errors::emitter::Emitter;
 use syntax_pos::MultiSpan;
 
 use std::collections::HashMap;
@@ -100,23 +100,23 @@ impl SharedEmitter {
     }
 }
 
-impl CoreEmitter for SharedEmitter {
-    fn emit_message(&mut self,
-                    _rsp: &RenderSpan,
-                    msg: &str,
-                    code: Option<&str>,
-                    lvl: Level,
-                    _is_header: bool,
-                    _show_snippet: bool) {
+impl Emitter for SharedEmitter {
+    fn emit(&mut self, db: &DiagnosticBuilder) {
         self.buffer.lock().unwrap().push(Diagnostic {
-            msg: msg.to_string(),
-            code: code.map(|s| s.to_string()),
-            lvl: lvl,
+            msg: db.message.to_string(),
+            code: db.code.clone(),
+            lvl: db.level,
         });
+        for child in &db.children {
+            self.buffer.lock().unwrap().push(Diagnostic {
+                msg: child.message.to_string(),
+                code: None,
+                lvl: child.level,
+            });
+        }
     }
 }
 
-
 // On android, we by default compile for armv7 processors. This enables
 // things like double word CAS instructions (rather than emulating them)
 // which are *far* more efficient. This is obviously undesirable in some
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 49a3991ecbe0b..fc9ae73f5ce7e 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -131,7 +131,7 @@ pub fn run_core(search_paths: SearchPaths,
                                                                None,
                                                                true,
                                                                false,
-                                                               codemap.clone());
+                                                               Some(codemap.clone()));
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index bb69ba6e568d5..f9d0df9981a1d 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -77,7 +77,7 @@ pub fn run(input: &str,
                                                                None,
                                                                true,
                                                                false,
-                                                               codemap.clone());
+                                                               Some(codemap.clone()));
 
     let dep_graph = DepGraph::new(false);
     let _ignore = dep_graph.in_ignore();
@@ -229,7 +229,7 @@ fn runtest(test: &str, cratename: &str, cfgs: Vec<String>, libs: SearchPaths,
     let codemap = Rc::new(CodeMap::new());
     let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
                                                 None,
-                                                codemap.clone(),
+                                                Some(codemap.clone()),
                                                 errors::snippet::FormatMode::EnvironmentSelected);
     let old = io::set_panic(box Sink(data.clone()));
     let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 743f96d737e2d..a8aca90e6238d 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -827,12 +827,6 @@ impl CodeMapper for CodeMap {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use errors::{Level, CodeSuggestion};
-    use errors::emitter::EmitterWriter;
-    use errors::snippet::{SnippetData, RenderedLine, FormatMode};
-    use std::sync::{Arc, Mutex};
-    use std::io::{self, Write};
-    use std::str::from_utf8;
     use std::rc::Rc;
 
     #[test]
@@ -1122,24 +1116,6 @@ mod tests {
         }
     }
 
-    fn splice(start: Span, end: Span) -> Span {
-        Span {
-            lo: start.lo,
-            hi: end.hi,
-            expn_id: NO_EXPANSION,
-        }
-    }
-
-    fn make_string(lines: &[RenderedLine]) -> String {
-        lines.iter()
-            .flat_map(|rl| {
-                rl.text.iter()
-                        .map(|s| &s.text[..])
-                        .chain(Some("\n"))
-            })
-            .collect()
-    }
-
     fn init_expansion_chain(cm: &CodeMap) -> Span {
         // Creates an expansion chain containing two recursive calls
         // root -> expA -> expA -> expB -> expB -> end
@@ -1219,761 +1195,4 @@ r"blork2.rs:2:1: 2:12
 ";
         assert_eq!(sstr, res_str);
     }
-
-    struct Sink(Arc<Mutex<Vec<u8>>>);
-    impl Write for Sink {
-        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
-            Write::write(&mut *self.0.lock().unwrap(), data)
-        }
-        fn flush(&mut self) -> io::Result<()> { Ok(()) }
-    }
-
-    // Diagnostic doesn't align properly in span where line number increases by one digit
-    #[test]
-    fn test_hilight_suggestion_issue_11715() {
-        let data = Arc::new(Mutex::new(Vec::new()));
-        let cm = Rc::new(CodeMap::new());
-        let mut ew = EmitterWriter::new(Box::new(Sink(data.clone())),
-                                        None,
-                                        cm.clone(),
-                                        FormatMode::NewErrorFormat);
-        let content = "abcdefg
-        koksi
-        line3
-        line4
-        cinq
-        line6
-        line7
-        line8
-        line9
-        line10
-        e-lä-vän
-        tolv
-        dreizehn
-        ";
-        let file = cm.new_filemap_and_lines("dummy.txt", None, content);
-        let start = file.lines.borrow()[10];
-        let end = file.lines.borrow()[11];
-        let sp = mk_sp(start, end);
-        let lvl = Level::Error;
-        println!("highlight_lines");
-        ew.highlight_lines(&sp.into(), lvl).unwrap();
-        println!("done");
-        let vec = data.lock().unwrap().clone();
-        let vec: &[u8] = &vec;
-        let str = from_utf8(vec).unwrap();
-        println!("r#\"\n{}\"#", str);
-        assert_eq!(str, &r#"
-  --> dummy.txt:11:1
-   |>
-11 |>         e-lä-vän
-   |> ^
-"#[1..]);
-    }
-
-    #[test]
-    fn test_single_span_splice() {
-        // Test that a `MultiSpan` containing a single span splices a substition correctly
-        let cm = CodeMap::new();
-        let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
-        let selection = "     \n    ~~\n~~~\n~~~~~     \n   \n";
-        cm.new_filemap_and_lines("blork.rs", None, inputtext);
-        let sp = span_from_selection(inputtext, selection);
-        let msp: MultiSpan = sp.into();
-
-        // check that we are extracting the text we thought we were extracting
-        assert_eq!(&cm.span_to_snippet(sp).unwrap(), "BB\nCCC\nDDDDD");
-
-        let substitute = "ZZZZZZ".to_owned();
-        let expected = "bbbbZZZZZZddddd";
-        let suggest = CodeSuggestion {
-            msp: msp,
-            substitutes: vec![substitute],
-        };
-        assert_eq!(suggest.splice_lines(&cm), expected);
-    }
-
-    #[test]
-    fn test_multi_span_splice() {
-        // Test that a `MultiSpan` containing multiple spans splices a substition correctly
-        let cm = CodeMap::new();
-        let inputtext  = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
-        let selection1 = "     \n      \n   \n          \n ~ \n"; // intentionally out of order
-        let selection2 = "     \n    ~~\n~~~\n~~~~~     \n   \n";
-        cm.new_filemap_and_lines("blork.rs", None, inputtext);
-        let sp1 = span_from_selection(inputtext, selection1);
-        let sp2 = span_from_selection(inputtext, selection2);
-        let msp: MultiSpan = MultiSpan::from_spans(vec![sp1, sp2]);
-
-        let expected = "bbbbZZZZZZddddd\neXYZe";
-        let suggest = CodeSuggestion {
-            msp: msp,
-            substitutes: vec!["ZZZZZZ".to_owned(),
-                              "XYZ".to_owned()]
-        };
-
-        assert_eq!(suggest.splice_lines(&cm), expected);
-    }
-
-    #[test]
-    fn test_multispan_highlight() {
-        let data = Arc::new(Mutex::new(Vec::new()));
-        let cm = Rc::new(CodeMap::new());
-        let mut diag = EmitterWriter::new(Box::new(Sink(data.clone())),
-                                          None,
-                                          cm.clone(),
-                                          FormatMode::NewErrorFormat);
-
-        let inp =       "_____aaaaaa____bbbbbb__cccccdd_";
-        let sp1 =       "     ~~~~~~                    ";
-        let sp2 =       "               ~~~~~~          ";
-        let sp3 =       "                       ~~~~~   ";
-        let sp4 =       "                          ~~~~ ";
-        let sp34 =      "                       ~~~~~~~ ";
-
-        let expect_start = &r#"
- --> dummy.txt:1:6
-  |>
-1 |> _____aaaaaa____bbbbbb__cccccdd_
-  |>      ^^^^^^    ^^^^^^  ^^^^^^^
-"#[1..];
-
-        let span = |sp, expected| {
-            let sp = span_from_selection(inp, sp);
-            assert_eq!(&cm.span_to_snippet(sp).unwrap(), expected);
-            sp
-        };
-        cm.new_filemap_and_lines("dummy.txt", None, inp);
-        let sp1 = span(sp1, "aaaaaa");
-        let sp2 = span(sp2, "bbbbbb");
-        let sp3 = span(sp3, "ccccc");
-        let sp4 = span(sp4, "ccdd");
-        let sp34 = span(sp34, "cccccdd");
-
-        let spans = vec![sp1, sp2, sp3, sp4];
-
-        let test = |expected, highlight: &mut FnMut()| {
-            data.lock().unwrap().clear();
-            highlight();
-            let vec = data.lock().unwrap().clone();
-            let actual = from_utf8(&vec[..]).unwrap();
-            println!("actual=\n{}", actual);
-            assert_eq!(actual, expected);
-        };
-
-        let msp = MultiSpan::from_spans(vec![sp1, sp2, sp34]);
-        test(expect_start, &mut || {
-            diag.highlight_lines(&msp, Level::Error).unwrap();
-        });
-        test(expect_start, &mut || {
-            let msp = MultiSpan::from_spans(spans.clone());
-            diag.highlight_lines(&msp, Level::Error).unwrap();
-        });
-    }
-
-    #[test]
-    fn test_huge_multispan_highlight() {
-        let data = Arc::new(Mutex::new(Vec::new()));
-        let cm = Rc::new(CodeMap::new());
-        let mut diag = EmitterWriter::new(Box::new(Sink(data.clone())),
-                                          None,
-                                          cm.clone(),
-                                          FormatMode::NewErrorFormat);
-
-        let inp = "aaaaa\n\
-                   aaaaa\n\
-                   aaaaa\n\
-                   bbbbb\n\
-                   ccccc\n\
-                   xxxxx\n\
-                   yyyyy\n\
-                   _____\n\
-                   ddd__eee_\n\
-                   elided\n\
-                   __f_gg";
-        let file = cm.new_filemap_and_lines("dummy.txt", None, inp);
-
-        let span = |lo, hi, (off_lo, off_hi)| {
-            let lines = file.lines.borrow();
-            let (mut lo, mut hi): (BytePos, BytePos) = (lines[lo], lines[hi]);
-            lo.0 += off_lo;
-            hi.0 += off_hi;
-            mk_sp(lo, hi)
-        };
-        let sp0 = span(4, 6, (0, 5));
-        let sp1 = span(0, 6, (0, 5));
-        let sp2 = span(8, 8, (0, 3));
-        let sp3 = span(8, 8, (5, 8));
-        let sp4 = span(10, 10, (2, 3));
-        let sp5 = span(10, 10, (4, 6));
-
-        let expect0 = &r#"
-   --> dummy.txt:5:1
-    |>
-5   |> ccccc
-    |> ^
-...
-9   |> ddd__eee_
-    |> ^^^  ^^^
-10  |> elided
-11  |> __f_gg
-    |>   ^ ^^
-"#[1..];
-
-        let expect = &r#"
-   --> dummy.txt:1:1
-    |>
-1   |> aaaaa
-    |> ^
-...
-9   |> ddd__eee_
-    |> ^^^  ^^^
-10  |> elided
-11  |> __f_gg
-    |>   ^ ^^
-"#[1..];
-
-        macro_rules! test {
-            ($expected: expr, $highlight: expr) => ({
-                data.lock().unwrap().clear();
-                $highlight();
-                let vec = data.lock().unwrap().clone();
-                let actual = from_utf8(&vec[..]).unwrap();
-                println!("actual:");
-                println!("{}", actual);
-                println!("expected:");
-                println!("{}", $expected);
-                assert_eq!(&actual[..], &$expected[..]);
-            });
-        }
-
-        let msp0 = MultiSpan::from_spans(vec![sp0, sp2, sp3, sp4, sp5]);
-        let msp = MultiSpan::from_spans(vec![sp1, sp2, sp3, sp4, sp5]);
-
-        test!(expect0, || {
-            diag.highlight_lines(&msp0, Level::Error).unwrap();
-        });
-        test!(expect, || {
-            diag.highlight_lines(&msp, Level::Error).unwrap();
-        });
-    }
-
-    #[test]
-    fn tab() {
-        let file_text = "
-fn foo() {
-\tbar;
-}
-";
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-        let span_bar = cm.span_substr(&foo, file_text, "bar", 0);
-
-        let mut snippet = SnippetData::new(cm, Some(span_bar), FormatMode::NewErrorFormat);
-        snippet.push(span_bar, true, None);
-
-        let lines = snippet.render_lines();
-        let text = make_string(&lines);
-        assert_eq!(&text[..], &"
- --> foo.rs:3:2
-  |>
-3 |> \tbar;
-  |> \t^^^
-"[1..]);
-    }
-
-    #[test]
-    fn one_line() {
-        let file_text = r#"
-fn foo() {
-    vec.push(vec.pop().unwrap());
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-        let span_vec0 = cm.span_substr(&foo, file_text, "vec", 0);
-        let span_vec1 = cm.span_substr(&foo, file_text, "vec", 1);
-        let span_semi = cm.span_substr(&foo, file_text, ";", 0);
-
-        let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
-        snippet.push(span_vec0, false, Some(format!("previous borrow of `vec` occurs here")));
-        snippet.push(span_vec1, false, Some(format!("error occurs here")));
-        snippet.push(span_semi, false, Some(format!("previous borrow ends here")));
-
-        let lines = snippet.render_lines();
-        println!("{:#?}", lines);
-
-        let text: String = make_string(&lines);
-
-        println!("text=\n{}", text);
-        assert_eq!(&text[..], &r#"
- ::: foo.rs
-  |>
-3 |>     vec.push(vec.pop().unwrap());
-  |>     ---      ---                - previous borrow ends here
-  |>     |        |
-  |>     |        error occurs here
-  |>     previous borrow of `vec` occurs here
-"#[1..]);
-    }
-
-    #[test]
-    fn two_files() {
-        let file_text_foo = r#"
-fn foo() {
-    vec.push(vec.pop().unwrap());
-}
-"#;
-
-        let file_text_bar = r#"
-fn bar() {
-    // these blank links here
-    // serve to ensure that the line numbers
-    // from bar.rs
-    // require more digits
-
-
-
-
-
-
-
-
-
-
-    vec.push();
-
-    // this line will get elided
-
-    vec.pop().unwrap());
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo_map = cm.new_filemap_and_lines("foo.rs", None, file_text_foo);
-        let span_foo_vec0 = cm.span_substr(&foo_map, file_text_foo, "vec", 0);
-        let span_foo_vec1 = cm.span_substr(&foo_map, file_text_foo, "vec", 1);
-        let span_foo_semi = cm.span_substr(&foo_map, file_text_foo, ";", 0);
-
-        let bar_map = cm.new_filemap_and_lines("bar.rs", None, file_text_bar);
-        let span_bar_vec0 = cm.span_substr(&bar_map, file_text_bar, "vec", 0);
-        let span_bar_vec1 = cm.span_substr(&bar_map, file_text_bar, "vec", 1);
-        let span_bar_semi = cm.span_substr(&bar_map, file_text_bar, ";", 0);
-
-        let mut snippet = SnippetData::new(cm, Some(span_foo_vec1), FormatMode::NewErrorFormat);
-        snippet.push(span_foo_vec0, false, Some(format!("a")));
-        snippet.push(span_foo_vec1, true, Some(format!("b")));
-        snippet.push(span_foo_semi, false, Some(format!("c")));
-        snippet.push(span_bar_vec0, false, Some(format!("d")));
-        snippet.push(span_bar_vec1, false, Some(format!("e")));
-        snippet.push(span_bar_semi, false, Some(format!("f")));
-
-        let lines = snippet.render_lines();
-        println!("{:#?}", lines);
-
-        let text: String = make_string(&lines);
-
-        println!("text=\n{}", text);
-
-        // Note that the `|>` remain aligned across both files:
-        assert_eq!(&text[..], &r#"
-   --> foo.rs:3:14
-    |>
-3   |>     vec.push(vec.pop().unwrap());
-    |>     ---      ^^^                - c
-    |>     |        |
-    |>     |        b
-    |>     a
-   ::: bar.rs
-    |>
-17  |>     vec.push();
-    |>     ---       - f
-    |>     |
-    |>     d
-...
-21  |>     vec.pop().unwrap());
-    |>     --- e
-"#[1..]);
-    }
-
-    #[test]
-    fn multi_line() {
-        let file_text = r#"
-fn foo() {
-    let name = find_id(&data, 22).unwrap();
-
-    // Add one more item we forgot to the vector. Silly us.
-    data.push(Data { name: format!("Hera"), id: 66 });
-
-    // Print everything out.
-    println!("Name: {:?}", name);
-    println!("Data: {:?}", data);
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-        let span_data0 = cm.span_substr(&foo, file_text, "data", 0);
-        let span_data1 = cm.span_substr(&foo, file_text, "data", 1);
-        let span_rbrace = cm.span_substr(&foo, file_text, "}", 3);
-
-        let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
-        snippet.push(span_data0, false, Some(format!("immutable borrow begins here")));
-        snippet.push(span_data1, false, Some(format!("mutable borrow occurs here")));
-        snippet.push(span_rbrace, false, Some(format!("immutable borrow ends here")));
-
-        let lines = snippet.render_lines();
-        println!("{:#?}", lines);
-
-        let text: String = make_string(&lines);
-
-        println!("text=\n{}", text);
-        assert_eq!(&text[..], &r#"
-   ::: foo.rs
-    |>
-3   |>     let name = find_id(&data, 22).unwrap();
-    |>                         ---- immutable borrow begins here
-...
-6   |>     data.push(Data { name: format!("Hera"), id: 66 });
-    |>     ---- mutable borrow occurs here
-...
-11  |> }
-    |> - immutable borrow ends here
-"#[1..]);
-    }
-
-    #[test]
-    fn overlapping() {
-        let file_text = r#"
-fn foo() {
-    vec.push(vec.pop().unwrap());
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-        let span0 = cm.span_substr(&foo, file_text, "vec.push", 0);
-        let span1 = cm.span_substr(&foo, file_text, "vec", 0);
-        let span2 = cm.span_substr(&foo, file_text, "ec.push", 0);
-        let span3 = cm.span_substr(&foo, file_text, "unwrap", 0);
-
-        let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
-        snippet.push(span0, false, Some(format!("A")));
-        snippet.push(span1, false, Some(format!("B")));
-        snippet.push(span2, false, Some(format!("C")));
-        snippet.push(span3, false, Some(format!("D")));
-
-        let lines = snippet.render_lines();
-        println!("{:#?}", lines);
-        let text: String = make_string(&lines);
-
-        println!("text=r#\"\n{}\".trim_left()", text);
-        assert_eq!(&text[..], &r#"
- ::: foo.rs
-  |>
-3 |>     vec.push(vec.pop().unwrap());
-  |>     --------           ------ D
-  |>     ||
-  |>     |C
-  |>     A
-  |>     B
-"#[1..]);
-    }
-
-    #[test]
-    fn one_line_out_of_order() {
-        let file_text = r#"
-fn foo() {
-    vec.push(vec.pop().unwrap());
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-        let span_vec0 = cm.span_substr(&foo, file_text, "vec", 0);
-        let span_vec1 = cm.span_substr(&foo, file_text, "vec", 1);
-        let span_semi = cm.span_substr(&foo, file_text, ";", 0);
-
-        // intentionally don't push the snippets left to right
-        let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
-        snippet.push(span_vec1, false, Some(format!("error occurs here")));
-        snippet.push(span_vec0, false, Some(format!("previous borrow of `vec` occurs here")));
-        snippet.push(span_semi, false, Some(format!("previous borrow ends here")));
-
-        let lines = snippet.render_lines();
-        println!("{:#?}", lines);
-        let text: String = make_string(&lines);
-
-        println!("text=r#\"\n{}\".trim_left()", text);
-        assert_eq!(&text[..], &r#"
- ::: foo.rs
-  |>
-3 |>     vec.push(vec.pop().unwrap());
-  |>     ---      ---                - previous borrow ends here
-  |>     |        |
-  |>     |        error occurs here
-  |>     previous borrow of `vec` occurs here
-"#[1..]);
-    }
-
-    #[test]
-    fn elide_unnecessary_lines() {
-        let file_text = r#"
-fn foo() {
-    let mut vec = vec![0, 1, 2];
-    let mut vec2 = vec;
-    vec2.push(3);
-    vec2.push(4);
-    vec2.push(5);
-    vec2.push(6);
-    vec.push(7);
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-        let span_vec0 = cm.span_substr(&foo, file_text, "vec", 3);
-        let span_vec1 = cm.span_substr(&foo, file_text, "vec", 8);
-
-        let mut snippet = SnippetData::new(cm, None, FormatMode::NewErrorFormat);
-        snippet.push(span_vec0, false, Some(format!("`vec` moved here because it \
-            has type `collections::vec::Vec<i32>`")));
-        snippet.push(span_vec1, false, Some(format!("use of moved value: `vec`")));
-
-        let lines = snippet.render_lines();
-        println!("{:#?}", lines);
-        let text: String = make_string(&lines);
-        println!("text=r#\"\n{}\".trim_left()", text);
-        assert_eq!(&text[..], &r#"
-   ::: foo.rs
-    |>
-4   |>     let mut vec2 = vec;
-    |>                    --- `vec` moved here because it has type `collections::vec::Vec<i32>`
-...
-9   |>     vec.push(7);
-    |>     --- use of moved value: `vec`
-"#[1..]);
-    }
-
-    #[test]
-    fn spans_without_labels() {
-        let file_text = r#"
-fn foo() {
-    let mut vec = vec![0, 1, 2];
-    let mut vec2 = vec;
-    vec2.push(3);
-    vec2.push(4);
-    vec2.push(5);
-    vec2.push(6);
-    vec.push(7);
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-
-        let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
-        for i in 0..4 {
-            let span_veci = cm.span_substr(&foo, file_text, "vec", i);
-            snippet.push(span_veci, false, None);
-        }
-
-        let lines = snippet.render_lines();
-        let text: String = make_string(&lines);
-        println!("text=&r#\"\n{}\n\"#[1..]", text);
-        assert_eq!(text, &r#"
- ::: foo.rs
-  |>
-3 |>     let mut vec = vec![0, 1, 2];
-  |>             ---   ---
-4 |>     let mut vec2 = vec;
-  |>             ---    ---
-"#[1..]);
-    }
-
-    #[test]
-    fn span_long_selection() {
-        let file_text = r#"
-impl SomeTrait for () {
-    fn foo(x: u32) {
-        // impl 1
-        // impl 2
-        // impl 3
-    }
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-
-        let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
-        let fn_span = cm.span_substr(&foo, file_text, "fn", 0);
-        let rbrace_span = cm.span_substr(&foo, file_text, "}", 0);
-        snippet.push(splice(fn_span, rbrace_span), false, None);
-        let lines = snippet.render_lines();
-        let text: String = make_string(&lines);
-        println!("r#\"\n{}\"", text);
-        assert_eq!(text, &r#"
- ::: foo.rs
-  |>
-3 |>     fn foo(x: u32) {
-  |>     -
-"#[1..]);
-    }
-
-    #[test]
-    fn span_overlap_label() {
-        // Test that we don't put `x_span` to the right of its highlight,
-        // since there is another highlight that overlaps it.
-
-        let file_text = r#"
-    fn foo(x: u32) {
-    }
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-
-        let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
-        let fn_span = cm.span_substr(&foo, file_text, "fn foo(x: u32)", 0);
-        let x_span = cm.span_substr(&foo, file_text, "x", 0);
-        snippet.push(fn_span, false, Some(format!("fn_span")));
-        snippet.push(x_span, false, Some(format!("x_span")));
-        let lines = snippet.render_lines();
-        let text: String = make_string(&lines);
-        println!("r#\"\n{}\"", text);
-        assert_eq!(text, &r#"
- ::: foo.rs
-  |>
-2 |>     fn foo(x: u32) {
-  |>     --------------
-  |>     |      |
-  |>     |      x_span
-  |>     fn_span
-"#[1..]);
-    }
-
-    #[test]
-    fn span_overlap_label2() {
-        // Test that we don't put `x_span` to the right of its highlight,
-        // since there is another highlight that overlaps it. In this
-        // case, the overlap is only at the beginning, but it's still
-        // better to show the beginning more clearly.
-
-        let file_text = r#"
-    fn foo(x: u32) {
-    }
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-
-        let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
-        let fn_span = cm.span_substr(&foo, file_text, "fn foo(x", 0);
-        let x_span = cm.span_substr(&foo, file_text, "x: u32)", 0);
-        snippet.push(fn_span, false, Some(format!("fn_span")));
-        snippet.push(x_span, false, Some(format!("x_span")));
-        let lines = snippet.render_lines();
-        let text: String = make_string(&lines);
-        println!("r#\"\n{}\"", text);
-        assert_eq!(text, &r#"
- ::: foo.rs
-  |>
-2 |>     fn foo(x: u32) {
-  |>     --------------
-  |>     |      |
-  |>     |      x_span
-  |>     fn_span
-"#[1..]);
-    }
-
-    #[test]
-    fn span_overlap_label3() {
-        // Test that we don't put `x_span` to the right of its highlight,
-        // since there is another highlight that overlaps it. In this
-        // case, the overlap is only at the beginning, but it's still
-        // better to show the beginning more clearly.
-
-        let file_text = r#"
-    fn foo() {
-       let closure = || {
-           inner
-       };
-    }
-}
-"#;
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-
-        let mut snippet = SnippetData::new(cm.clone(), None, FormatMode::NewErrorFormat);
-
-        let closure_span = {
-            let closure_start_span = cm.span_substr(&foo, file_text, "||", 0);
-            let closure_end_span = cm.span_substr(&foo, file_text, "}", 0);
-            splice(closure_start_span, closure_end_span)
-        };
-
-        let inner_span = cm.span_substr(&foo, file_text, "inner", 0);
-
-        snippet.push(closure_span, false, Some(format!("foo")));
-        snippet.push(inner_span, false, Some(format!("bar")));
-
-        let lines = snippet.render_lines();
-        let text: String = make_string(&lines);
-        println!("r#\"\n{}\"", text);
-        assert_eq!(text, &r#"
- ::: foo.rs
-  |>
-3 |>        let closure = || {
-  |>                      - foo
-4 |>            inner
-  |>            ----- bar
-"#[1..]);
-    }
-
-    #[test]
-    fn span_empty() {
-        // In one of the unit tests, we found that the parser sometimes
-        // gives empty spans, and in particular it supplied an EOF span
-        // like this one, which points at the very end. We want to
-        // fallback gracefully in this case.
-
-        let file_text = r#"
-fn main() {
-    struct Foo;
-
-    impl !Sync for Foo {}
-
-    unsafe impl Send for &'static Foo {
-    // error: cross-crate traits with a default impl, like `core::marker::Send`,
-    //        can only be implemented for a struct/enum type, not
-    //        `&'static Foo`
-}"#;
-
-
-        let cm = Rc::new(CodeMap::new());
-        let foo = cm.new_filemap_and_lines("foo.rs", None, file_text);
-
-        let mut rbrace_span = cm.span_substr(&foo, file_text, "}", 1);
-        rbrace_span.lo = rbrace_span.hi;
-
-        let mut snippet = SnippetData::new(cm.clone(),
-                                           Some(rbrace_span),
-                                           FormatMode::NewErrorFormat);
-        snippet.push(rbrace_span, false, None);
-        let lines = snippet.render_lines();
-        let text: String = make_string(&lines);
-        println!("r#\"\n{}\"", text);
-        assert_eq!(text, &r#"
-  --> foo.rs:11:2
-   |>
-11 |> }
-   |>  -
-"#[1..]);
-    }
 }
diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs
index dc9a5ee46645f..a40c30b3e3397 100644
--- a/src/libsyntax/json.rs
+++ b/src/libsyntax/json.rs
@@ -22,7 +22,7 @@
 use codemap::CodeMap;
 use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan};
 use errors::registry::Registry;
-use errors::{Level, DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
+use errors::{DiagnosticBuilder, SubDiagnostic, RenderSpan, CodeSuggestion, CodeMapper};
 use errors::emitter::Emitter;
 
 use std::rc::Rc;
@@ -53,14 +53,7 @@ impl JsonEmitter {
 }
 
 impl Emitter for JsonEmitter {
-    fn emit(&mut self, span: &MultiSpan, msg: &str, code: Option<&str>, level: Level) {
-        let data = Diagnostic::new(span, msg, code, level, self);
-        if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
-            panic!("failed to print diagnostics: {:?}", e);
-        }
-    }
-
-    fn emit_struct(&mut self, db: &DiagnosticBuilder) {
+    fn emit(&mut self, db: &DiagnosticBuilder) {
         let data = Diagnostic::from_diagnostic_builder(db, self);
         if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
             panic!("failed to print diagnostics: {:?}", e);
@@ -146,22 +139,6 @@ struct DiagnosticCode {
 }
 
 impl<'a> Diagnostic<'a> {
-    fn new(msp: &MultiSpan,
-           msg: &'a str,
-           code: Option<&str>,
-           level: Level,
-           je: &JsonEmitter)
-           -> Diagnostic<'a> {
-        Diagnostic {
-            message: msg,
-            code: DiagnosticCode::map_opt_string(code.map(|c| c.to_owned()), je),
-            level: level.to_str(),
-            spans: DiagnosticSpan::from_multispan(msp, je),
-            children: vec![],
-            rendered: None,
-        }
-    }
-
     fn from_diagnostic_builder<'c>(db: &'c DiagnosticBuilder,
                                    je: &JsonEmitter)
                                    -> Diagnostic<'c> {
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 77b5c10899a3d..5ea1d6be9fec9 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1686,7 +1686,7 @@ mod tests {
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
         let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
                                                 None,
-                                                cm,
+                                                Some(cm),
                                                 errors::snippet::FormatMode::EnvironmentSelected);
         errors::Handler::with_emitter(true, false, Box::new(emitter))
     }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 9502bc48a3e11..6af4d95e888ac 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -50,7 +50,11 @@ pub struct ParseSess {
 impl ParseSess {
     pub fn new() -> ParseSess {
         let cm = Rc::new(CodeMap::new());
-        let handler = Handler::with_tty_emitter(ColorConfig::Auto, None, true, false, cm.clone());
+        let handler = Handler::with_tty_emitter(ColorConfig::Auto,
+                                                None,
+                                                true,
+                                                false,
+                                                Some(cm.clone()));
         ParseSess::with_span_handler(handler, cm)
     }
 
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 0a60b7fd430c4..570c0a09bc417 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -26,7 +26,7 @@ use std::rc::Rc;
 
 use codemap::{self, CodeMap, ExpnInfo, NameAndSpan, MacroAttribute};
 use errors;
-use errors::snippet::{RenderedLine, SnippetData};
+use errors::snippet::{SnippetData};
 use config;
 use entry::{self, EntryPointType};
 use ext::base::{ExtCtxt, DummyMacroLoader};
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 39bb5956312bc..7dfe19452a2a9 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -568,7 +568,7 @@ impl Sub for CharPos {
 //
 
 /// A source code location used for error reporting
-#[derive(Debug)]
+#[derive(Debug, Clone)]
 pub struct Loc {
     /// Information about the original source
     pub file: Rc<FileMap>,
diff --git a/src/test/ui/codemap_tests/empty_span.rs b/src/test/ui/codemap_tests/empty_span.rs
new file mode 100644
index 0000000000000..c78a586763429
--- /dev/null
+++ b/src/test/ui/codemap_tests/empty_span.rs
@@ -0,0 +1,19 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+#![feature(optin_builtin_traits)]
+fn main() {
+    struct Foo;
+
+    impl !Sync for Foo {}
+
+    unsafe impl Send for &'static Foo { }
+}
diff --git a/src/test/ui/codemap_tests/empty_span.stderr b/src/test/ui/codemap_tests/empty_span.stderr
new file mode 100644
index 0000000000000..f3e04ef02409b
--- /dev/null
+++ b/src/test/ui/codemap_tests/empty_span.stderr
@@ -0,0 +1,8 @@
+error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`, can only be implemented for a struct/enum type, not `&'static main::Foo`
+  --> $DIR/empty_span.rs:18:5
+   |
+18 |     unsafe impl Send for &'static Foo { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.rs b/src/test/ui/codemap_tests/huge_multispan_highlight.rs
new file mode 100644
index 0000000000000..b06832c7628ed
--- /dev/null
+++ b/src/test/ui/codemap_tests/huge_multispan_highlight.rs
@@ -0,0 +1,104 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+
+fn main() {
+    let x = "foo";
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    let y = &mut x;
+}
+
+
+
diff --git a/src/test/ui/codemap_tests/huge_multispan_highlight.stderr b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr
new file mode 100644
index 0000000000000..6a898a434778e
--- /dev/null
+++ b/src/test/ui/codemap_tests/huge_multispan_highlight.stderr
@@ -0,0 +1,11 @@
+error: cannot borrow immutable local variable `x` as mutable
+   --> $DIR/huge_multispan_highlight.rs:100:18
+    |
+14  |     let x = "foo";
+    |         - use `mut x` here to make mutable
+...
+100 |     let y = &mut x;
+    |                  ^ cannot borrow mutably
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/issue-11715.rs b/src/test/ui/codemap_tests/issue-11715.rs
new file mode 100644
index 0000000000000..7ea497a25c832
--- /dev/null
+++ b/src/test/ui/codemap_tests/issue-11715.rs
@@ -0,0 +1,104 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+fn main() {
+    let mut x = "foo";
+    let y = &mut x;
+    let z = &mut x;
+}
+
+
+
diff --git a/src/test/ui/codemap_tests/issue-11715.stderr b/src/test/ui/codemap_tests/issue-11715.stderr
new file mode 100644
index 0000000000000..4947cbedd200e
--- /dev/null
+++ b/src/test/ui/codemap_tests/issue-11715.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+   --> $DIR/issue-11715.rs:100:18
+    |
+99  |     let y = &mut x;
+    |                  - first mutable borrow occurs here
+100 |     let z = &mut x;
+    |                  ^ second mutable borrow occurs here
+101 | }
+    | - first borrow ends here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/one_line.rs b/src/test/ui/codemap_tests/one_line.rs
new file mode 100644
index 0000000000000..2a5ee6f8711ef
--- /dev/null
+++ b/src/test/ui/codemap_tests/one_line.rs
@@ -0,0 +1,16 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+
+fn main() {
+    let mut v = vec![Some("foo"), Some("bar")];
+    v.push(v.pop().unwrap());
+}
diff --git a/src/test/ui/codemap_tests/one_line.stderr b/src/test/ui/codemap_tests/one_line.stderr
new file mode 100644
index 0000000000000..8f80489ea1aeb
--- /dev/null
+++ b/src/test/ui/codemap_tests/one_line.stderr
@@ -0,0 +1,11 @@
+error[E0499]: cannot borrow `v` as mutable more than once at a time
+  --> $DIR/one_line.rs:15:12
+   |
+15 |     v.push(v.pop().unwrap());
+   |     -      ^               - first borrow ends here
+   |     |      |
+   |     |      second mutable borrow occurs here
+   |     first mutable borrow occurs here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/overlapping_spans.rs b/src/test/ui/codemap_tests/overlapping_spans.rs
new file mode 100644
index 0000000000000..5a90852392c08
--- /dev/null
+++ b/src/test/ui/codemap_tests/overlapping_spans.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+#[derive(Debug)]
+struct Foo { }
+
+struct S {f:String}
+impl Drop for S {
+    fn drop(&mut self) { println!("{}", self.f); }
+}
+
+fn main() {
+    match (S {f:"foo".to_string()}) {
+        S {f:_s} => {}
+    }
+}
diff --git a/src/test/ui/codemap_tests/overlapping_spans.stderr b/src/test/ui/codemap_tests/overlapping_spans.stderr
new file mode 100644
index 0000000000000..cbcf154eaba50
--- /dev/null
+++ b/src/test/ui/codemap_tests/overlapping_spans.stderr
@@ -0,0 +1,11 @@
+error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
+  --> $DIR/overlapping_spans.rs:22:9
+   |
+22 |         S {f:_s} => {}
+   |         ^^^^^--^
+   |         |    |
+   |         |    hint: to prevent move, use `ref _s` or `ref mut _s`
+   |         cannot move out of here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/tab.rs b/src/test/ui/codemap_tests/tab.rs
new file mode 100644
index 0000000000000..aaaee8c5577fe
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab.rs
@@ -0,0 +1,16 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+// ignore-tidy-tab
+fn main() {
+	bar;
+}
+
diff --git a/src/test/ui/codemap_tests/tab.stderr b/src/test/ui/codemap_tests/tab.stderr
new file mode 100644
index 0000000000000..543c02fb701f3
--- /dev/null
+++ b/src/test/ui/codemap_tests/tab.stderr
@@ -0,0 +1,8 @@
+error[E0425]: unresolved name `bar`
+  --> $DIR/tab.rs:14:2
+   |
+14 | \tbar;
+   | \t^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/two_files.rs b/src/test/ui/codemap_tests/two_files.rs
new file mode 100644
index 0000000000000..53e240e8c4738
--- /dev/null
+++ b/src/test/ui/codemap_tests/two_files.rs
@@ -0,0 +1,18 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+include!("two_files_data.rs");
+
+struct Baz { }
+
+impl Bar for Baz { }
+
+fn main() { }
diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr
new file mode 100644
index 0000000000000..6c388cd69395b
--- /dev/null
+++ b/src/test/ui/codemap_tests/two_files.stderr
@@ -0,0 +1,13 @@
+error[E0404]: `Bar` is not a trait
+  --> $DIR/two_files.rs:16:6
+   |
+16 | impl Bar for Baz { }
+   |      ^^^ `Bar` is not a trait
+   | 
+  ::: $DIR/two_files_data.rs
+   |
+15 | type Bar = Foo;
+   | --------------- type aliases cannot be used for traits
+
+error: cannot continue compilation due to previous error
+
diff --git a/src/test/ui/codemap_tests/two_files_data.rs b/src/test/ui/codemap_tests/two_files_data.rs
new file mode 100644
index 0000000000000..412c40f8e811b
--- /dev/null
+++ b/src/test/ui/codemap_tests/two_files_data.rs
@@ -0,0 +1,16 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+// ignore-test
+trait Foo { }
+
+type Bar = Foo;
+
diff --git a/src/test/ui/codemap_tests/unicode.rs b/src/test/ui/codemap_tests/unicode.rs
new file mode 100644
index 0000000000000..19660133d6222
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode.rs
@@ -0,0 +1,14 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// rustc-env:RUST_NEW_ERROR_FORMAT
+extern "路濫狼á́́" fn foo() {}
+
+fn main() { }
diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr
new file mode 100644
index 0000000000000..178bee7b7f3ab
--- /dev/null
+++ b/src/test/ui/codemap_tests/unicode.stderr
@@ -0,0 +1,8 @@
+error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic], found `路濫狼á́́`
+  --> $DIR/unicode.rs:12:8
+   |
+12 | extern "路濫狼á́́" fn foo() {}
+   |        ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/mismatched_types/issue-26480.stderr b/src/test/ui/mismatched_types/issue-26480.stderr
index c00594a59c115..ff6920d28ccf9 100644
--- a/src/test/ui/mismatched_types/issue-26480.stderr
+++ b/src/test/ui/mismatched_types/issue-26480.stderr
@@ -1,15 +1,16 @@
-error: mismatched types [--explain E0308]
+error[E0308]: mismatched types
   --> $DIR/issue-26480.rs:27:19
-   |>
-27 |>                   $arr.len() * size_of($arr[0]));
-   |>                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize
-$DIR/issue-26480.rs:38:5: 38:19: note: in this expansion of write! (defined in $DIR/issue-26480.rs)
+   |
+27 |                   $arr.len() * size_of($arr[0]));
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u64, found usize
+$DIR/issue-26480.rs:38:5: 38:19 note: in this expansion of write! (defined in $DIR/issue-26480.rs)
 
 error: non-scalar cast: `_` as `()`
   --> $DIR/issue-26480.rs:33:19
-   |>
-33 |>     ($x:expr) => ($x as ())
-   |>                   ^^^^^^^^
-$DIR/issue-26480.rs:39:5: 39:14: note: in this expansion of cast! (defined in $DIR/issue-26480.rs)
+   |
+33 |     ($x:expr) => ($x as ())
+   |                   ^^^^^^^^
+$DIR/issue-26480.rs:39:5: 39:14 note: in this expansion of cast! (defined in $DIR/issue-26480.rs)
 
 error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/mismatched_types/main.stderr b/src/test/ui/mismatched_types/main.stderr
index 1af332ee5bea7..2903aa08c0a91 100644
--- a/src/test/ui/mismatched_types/main.stderr
+++ b/src/test/ui/mismatched_types/main.stderr
@@ -1,9 +1,11 @@
-error: mismatched types [--explain E0308]
+error[E0308]: mismatched types
   --> $DIR/main.rs:14:18
-   |>
-14 |>     let x: u32 = (
-   |>                  ^ expected u32, found ()
-note: expected type `u32`
-note:    found type `()`
+   |
+14 |     let x: u32 = (
+   |                  ^ expected u32, found ()
+   |
+   = note: expected type `u32`
+   = note:    found type `()`
 
 error: aborting due to previous error
+