diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 302713a21db9e..32104e6f00d44 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -200,6 +200,11 @@ pub trait Emitter {
         true
     }
 
+    /// Checks if we can use colors in the current output stream.
+    fn supports_color(&self) -> bool {
+        false
+    }
+
     fn source_map(&self) -> Option<&Lrc<SourceMap>>;
 
     /// Formats the substitutions of the primary_span
@@ -504,6 +509,10 @@ impl Emitter for EmitterWriter {
     fn should_show_explain(&self) -> bool {
         !self.short_message
     }
+
+    fn supports_color(&self) -> bool {
+        self.dst.supports_color()
+    }
 }
 
 /// An emitter that does nothing when emitting a diagnostic.
@@ -2057,6 +2066,14 @@ impl Destination {
             Destination::Raw(ref mut t, true) => WritableDst::ColoredRaw(Ansi::new(t)),
         }
     }
+
+    fn supports_color(&self) -> bool {
+        match *self {
+            Self::Terminal(ref stream) => stream.supports_color(),
+            Self::Buffered(ref buffer) => buffer.buffer().supports_color(),
+            Self::Raw(_, supports_color) => supports_color,
+        }
+    }
 }
 
 impl<'a> WritableDst<'a> {
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 0a4f88dedbb07..3427c83a18f2a 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -23,6 +23,8 @@ extern "Rust" {
     // (the code expanding that attribute macro generates those functions), or to call
     // the default implementations in libstd (`__rdl_alloc` etc. in `library/std/src/alloc.rs`)
     // otherwise.
+    // The rustc fork of LLVM also special-cases these function names to be able to optimize them
+    // like `malloc`, `realloc`, and `free`, respectively.
     #[rustc_allocator]
     #[rustc_allocator_nounwind]
     fn __rust_alloc(size: usize, align: usize) -> *mut u8;
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 5e40e6b151d30..4128ffd7a1af4 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -1,13 +1,13 @@
 use rustc_ast as ast;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::ErrorReported;
+use rustc_errors::{ColorConfig, ErrorReported};
 use rustc_hir as hir;
 use rustc_hir::intravisit;
 use rustc_hir::{HirId, CRATE_HIR_ID};
 use rustc_interface::interface;
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::config::{self, CrateType};
+use rustc_session::config::{self, CrateType, ErrorOutputType};
 use rustc_session::{lint, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
 use rustc_span::source_map::SourceMap;
@@ -248,7 +248,8 @@ fn run_test(
     outdir: DirState,
     path: PathBuf,
 ) -> Result<(), TestFailure> {
-    let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts, edition);
+    let (test, line_offset, supports_color) =
+        make_test(test, Some(cratename), as_test_harness, opts, edition);
 
     let output_file = outdir.path().join("rust_out");
 
@@ -293,6 +294,20 @@ fn run_test(
             path.to_str().expect("target path must be valid unicode").to_string()
         }
     });
+    if let ErrorOutputType::HumanReadable(kind) = options.error_format {
+        let (_, color_config) = kind.unzip();
+        match color_config {
+            ColorConfig::Never => {
+                compiler.arg("--color").arg("never");
+            }
+            ColorConfig::Always => {
+                compiler.arg("--color").arg("always");
+            }
+            ColorConfig::Auto => {
+                compiler.arg("--color").arg(if supports_color { "always" } else { "never" });
+            }
+        }
+    }
 
     compiler.arg("-");
     compiler.stdin(Stdio::piped());
@@ -320,7 +335,10 @@ fn run_test(
         (true, false) => {}
         (false, true) => {
             if !error_codes.is_empty() {
-                error_codes.retain(|err| !out.contains(&format!("error[{}]: ", err)));
+                // We used to check if the output contained "error[{}]: " but since we added the
+                // colored output, we can't anymore because of the color escape characters before
+                // the ":".
+                error_codes.retain(|err| !out.contains(&format!("error[{}]", err)));
 
                 if !error_codes.is_empty() {
                     return Err(TestFailure::MissingErrorCodes(error_codes));
@@ -362,18 +380,19 @@ fn run_test(
 }
 
 /// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
-/// lines before the test code begins.
+/// lines before the test code begins as well as if the output stream supports colors or not.
 pub fn make_test(
     s: &str,
     cratename: Option<&str>,
     dont_insert_main: bool,
     opts: &TestOptions,
     edition: Edition,
-) -> (String, usize) {
+) -> (String, usize, bool) {
     let (crate_attrs, everything_else, crates) = partition_source(s);
     let everything_else = everything_else.trim();
     let mut line_offset = 0;
     let mut prog = String::new();
+    let mut supports_color = false;
 
     if opts.attrs.is_empty() && !opts.display_warnings {
         // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
@@ -399,7 +418,7 @@ pub fn make_test(
     // crate already is included.
     let result = rustc_driver::catch_fatal_errors(|| {
         rustc_span::with_session_globals(edition, || {
-            use rustc_errors::emitter::EmitterWriter;
+            use rustc_errors::emitter::{Emitter, EmitterWriter};
             use rustc_errors::Handler;
             use rustc_parse::maybe_new_parser_from_source_str;
             use rustc_session::parse::ParseSess;
@@ -411,8 +430,13 @@ pub fn make_test(
             // Any errors in parsing should also appear when the doctest is compiled for real, so just
             // send all the errors that librustc_ast emits directly into a `Sink` instead of stderr.
             let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+            supports_color =
+                EmitterWriter::stderr(ColorConfig::Auto, None, false, false, Some(80), false)
+                    .supports_color();
+
             let emitter =
                 EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
+
             // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser
             let handler = Handler::with_emitter(false, None, box emitter);
             let sess = ParseSess::with_span_handler(handler, sm);
@@ -482,7 +506,7 @@ pub fn make_test(
         Err(ErrorReported) => {
             // If the parser panicked due to a fatal error, pass the test code through unchanged.
             // The error will be reported during compilation.
-            return (s.to_owned(), 0);
+            return (s.to_owned(), 0, false);
         }
     };
 
@@ -532,7 +556,7 @@ pub fn make_test(
 
     debug!("final doctest:\n{}", prog);
 
-    (prog, line_offset)
+    (prog, line_offset, supports_color)
 }
 
 // FIXME(aburka): use a real parser to deal with multiline attributes
diff --git a/src/librustdoc/doctest/tests.rs b/src/librustdoc/doctest/tests.rs
index a96186a95e16b..a024e9c72a43e 100644
--- a/src/librustdoc/doctest/tests.rs
+++ b/src/librustdoc/doctest/tests.rs
@@ -11,8 +11,8 @@ fn main() {
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 }
 
 #[test]
@@ -26,8 +26,8 @@ fn main() {
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 }
 
 #[test]
@@ -44,8 +44,8 @@ use asdf::qwop;
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 3));
+    let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 3));
 }
 
 #[test]
@@ -61,8 +61,8 @@ use asdf::qwop;
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 }
 
 #[test]
@@ -79,8 +79,8 @@ use std::*;
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, Some("std"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 }
 
 #[test]
@@ -98,8 +98,8 @@ use asdf::qwop;
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 }
 
 #[test]
@@ -115,8 +115,8 @@ use asdf::qwop;
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 }
 
 #[test]
@@ -134,8 +134,8 @@ use asdf::qwop;
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 3));
+    let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 3));
 
     // Adding more will also bump the returned line offset.
     opts.attrs.push("feature(hella_dope)".to_string());
@@ -147,8 +147,8 @@ use asdf::qwop;
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 4));
+    let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 4));
 }
 
 #[test]
@@ -164,8 +164,8 @@ fn main() {
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 }
 
 #[test]
@@ -180,8 +180,8 @@ fn main() {
     assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 1));
+    let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 1));
 }
 
 #[test]
@@ -196,8 +196,8 @@ fn main() {
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 }
 
 #[test]
@@ -210,8 +210,8 @@ assert_eq!(2+2, 4);";
 //Ceci n'est pas une `fn main`
 assert_eq!(2+2, 4);"
         .to_string();
-    let output = make_test(input, None, true, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 1));
+    let (output, len, _) = make_test(input, None, true, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 1));
 }
 
 #[test]
@@ -224,8 +224,8 @@ fn make_test_display_warnings() {
 assert_eq!(2+2, 4);
 }"
     .to_string();
-    let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 1));
+    let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 1));
 }
 
 #[test]
@@ -242,8 +242,8 @@ assert_eq!(2+2, 4);
 }"
     .to_string();
 
-    let output = make_test(input, None, false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 2));
+    let (output, len, _) = make_test(input, None, false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 2));
 
     let input = "extern crate hella_qwop;
 assert_eq!(asdf::foo, 4);";
@@ -256,8 +256,8 @@ assert_eq!(asdf::foo, 4);
 }"
     .to_string();
 
-    let output = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 3));
+    let (output, len, _) = make_test(input, Some("asdf"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 3));
 }
 
 #[test]
@@ -274,6 +274,6 @@ test_wrapper! {
 }"
     .to_string();
 
-    let output = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION);
-    assert_eq!(output, (expected, 1));
+    let (output, len, _) = make_test(input, Some("my_crate"), false, &opts, DEFAULT_EDITION);
+    assert_eq!((output, len), (expected, 1));
 }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 4769edc50ff07..b5fe593dc0105 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -46,7 +46,9 @@ fn write_header(out: &mut String, class: Option<&str>) {
 }
 
 fn write_code(out: &mut String, src: &str) {
-    Classifier::new(src).highlight(&mut |highlight| {
+    // This replace allows to fix how the code source with DOS backline characters is displayed.
+    let src = src.replace("\r\n", "\n");
+    Classifier::new(&src).highlight(&mut |highlight| {
         match highlight {
             Highlight::Token { text, class } => string(out, Escape(text), class),
             Highlight::EnterSpan { class } => enter_span(out, class),
diff --git a/src/librustdoc/html/highlight/fixtures/dos_line.html b/src/librustdoc/html/highlight/fixtures/dos_line.html
new file mode 100644
index 0000000000000..4400f85681d8a
--- /dev/null
+++ b/src/librustdoc/html/highlight/fixtures/dos_line.html
@@ -0,0 +1,3 @@
+<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">foo</span>() {
+<span class="macro">println</span><span class="macro">!</span>(<span class="string">&quot;foo&quot;</span>);
+}
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
index c79471b1fae6b..f57f52d6f0875 100644
--- a/src/librustdoc/html/highlight/tests.rs
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -1,17 +1,6 @@
 use super::write_code;
 use expect_test::expect_file;
 
-#[test]
-fn test_html_highlighting() {
-    let src = include_str!("fixtures/sample.rs");
-    let html = {
-        let mut out = String::new();
-        write_code(&mut out, src);
-        format!("{}<pre><code>{}</code></pre>\n", STYLE, out)
-    };
-    expect_file!["fixtures/sample.html"].assert_eq(&html);
-}
-
 const STYLE: &str = r#"
 <style>
 .kw { color: #8959A8; }
@@ -23,3 +12,24 @@ const STYLE: &str = r#"
 .question-mark { color: #ff9011; }
 </style>
 "#;
+
+#[test]
+fn test_html_highlighting() {
+    let src = include_str!("fixtures/sample.rs");
+    let html = {
+        let mut out = String::new();
+        write_code(&mut out, src);
+        format!("{}<pre><code>{}</code></pre>\n", STYLE, out)
+    };
+    expect_file!["fixtures/sample.html"].assert_eq(&html);
+}
+
+#[test]
+fn test_dos_backline() {
+    let src = "pub fn foo() {\r\n\
+    println!(\"foo\");\r\n\
+}\r\n";
+    let mut html = String::new();
+    write_code(&mut html, src);
+    expect_file!["fixtures/dos_line.html"].assert_eq(&html);
+}
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index ca8b811681cc9..cec4e334395e0 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -243,7 +243,8 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
                 .collect::<Vec<Cow<'_, str>>>()
                 .join("\n");
             let krate = krate.as_ref().map(|s| &**s);
-            let (test, _) = doctest::make_test(&test, krate, false, &Default::default(), edition);
+            let (test, _, _) =
+                doctest::make_test(&test, krate, false, &Default::default(), edition);
             let channel = if test.contains("#![feature(") { "&amp;version=nightly" } else { "" };
 
             let edition_string = format!("&amp;edition={}", edition);