diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 76d0e6e28aeda..4607ca5cf9f48 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -297,7 +297,12 @@ fn main() {
     }
 
     if verbose > 1 {
-        eprintln!("rustc command: {:?}", cmd);
+        eprintln!(
+            "rustc command: {:?}={:?} {:?}",
+            bootstrap::util::dylib_path_var(),
+            env::join_paths(&dylib_path).unwrap(),
+            cmd,
+        );
         eprintln!("sysroot: {:?}", sysroot);
         eprintln!("libdir: {:?}", libdir);
     }
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index e5824010ef2cc..00b30a00b0356 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1461,6 +1461,7 @@ mod __test {
             rustc_args: vec![],
             fail_fast: true,
             doc_tests: DocTests::No,
+            bless: false,
         };
 
         let build = Build::new(config);
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 5315a3028ffa9..90dd5d819b0da 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -59,6 +59,8 @@ pub enum Subcommand {
     },
     Test {
         paths: Vec<PathBuf>,
+        /// Whether to automatically update stderr/stdout files
+        bless: bool,
         test_args: Vec<String>,
         rustc_args: Vec<String>,
         fail_fast: bool,
@@ -173,6 +175,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
                 );
                 opts.optflag("", "no-doc", "do not run doc tests");
                 opts.optflag("", "doc", "only run doc tests");
+                opts.optflag("", "bless", "update all stderr/stdout files of failing ui tests");
             },
             "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
             "clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@@ -258,6 +261,7 @@ Arguments:
         ./x.py test src/test/run-pass
         ./x.py test src/libstd --test-args hash_map
         ./x.py test src/libstd --stage 0
+        ./x.py test src/test/ui --bless
 
     If no arguments are passed then the complete artifacts for that stage are
     compiled and tested.
@@ -322,6 +326,7 @@ Arguments:
             "test" => {
                 Subcommand::Test {
                     paths,
+                    bless: matches.opt_present("bless"),
                     test_args: matches.opt_strs("test-args"),
                     rustc_args: matches.opt_strs("rustc-args"),
                     fail_fast: !matches.opt_present("no-fail-fast"),
@@ -424,6 +429,13 @@ impl Subcommand {
             _ => DocTests::Yes,
         }
     }
+
+    pub fn bless(&self) -> bool {
+        match *self {
+            Subcommand::Test { bless, .. } => bless,
+            _ => false,
+        }
+    }
 }
 
 fn split(s: Vec<String>) -> Vec<String> {
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 1f81a617237cc..7a4924f03c8d2 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -47,6 +47,16 @@ pub enum TestKind {
     Bench,
 }
 
+impl From<Kind> for TestKind {
+    fn from(kind: Kind) -> Self {
+        match kind {
+            Kind::Test => TestKind::Test,
+            Kind::Bench => TestKind::Bench,
+            _ => panic!("unexpected kind in crate: {:?}", kind)
+        }
+    }
+}
+
 impl TestKind {
     // Return the cargo subcommand for this test kind
     fn subcommand(self) -> &'static str {
@@ -951,6 +961,10 @@ impl Step for Compiletest {
         cmd.arg("--host").arg(&*compiler.host);
         cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
 
+        if builder.config.cmd.bless() {
+            cmd.arg("--bless");
+        }
+
         if let Some(ref nodejs) = builder.config.nodejs {
             cmd.arg("--nodejs").arg(nodejs);
         }
@@ -1342,13 +1356,7 @@ impl Step for CrateLibrustc {
 
         for krate in builder.in_tree_crates("rustc-main") {
             if run.path.ends_with(&krate.path) {
-                let test_kind = if builder.kind == Kind::Test {
-                    TestKind::Test
-                } else if builder.kind == Kind::Bench {
-                    TestKind::Bench
-                } else {
-                    panic!("unexpected builder.kind in crate: {:?}", builder.kind);
-                };
+                let test_kind = builder.kind.into();
 
                 builder.ensure(CrateLibrustc {
                     compiler,
@@ -1394,13 +1402,7 @@ impl Step for CrateNotDefault {
         let builder = run.builder;
         let compiler = builder.compiler(builder.top_stage, run.host);
 
-        let test_kind = if builder.kind == Kind::Test {
-            TestKind::Test
-        } else if builder.kind == Kind::Bench {
-            TestKind::Bench
-        } else {
-            panic!("unexpected builder.kind in crate: {:?}", builder.kind);
-        };
+        let test_kind = builder.kind.into();
 
         builder.ensure(CrateNotDefault {
             compiler,
@@ -1461,13 +1463,7 @@ impl Step for Crate {
         let compiler = builder.compiler(builder.top_stage, run.host);
 
         let make = |mode: Mode, krate: &CargoCrate| {
-            let test_kind = if builder.kind == Kind::Test {
-                TestKind::Test
-            } else if builder.kind == Kind::Bench {
-                TestKind::Bench
-            } else {
-                panic!("unexpected builder.kind in crate: {:?}", builder.kind);
-            };
+            let test_kind = builder.kind.into();
 
             builder.ensure(Crate {
                 compiler,
@@ -1625,13 +1621,7 @@ impl Step for CrateRustdoc {
     fn make_run(run: RunConfig) {
         let builder = run.builder;
 
-        let test_kind = if builder.kind == Kind::Test {
-            TestKind::Test
-        } else if builder.kind == Kind::Bench {
-            TestKind::Bench
-        } else {
-            panic!("unexpected builder.kind in crate: {:?}", builder.kind);
-        };
+        let test_kind = builder.kind.into();
 
         builder.ensure(CrateRustdoc {
             host: run.host,
diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md
index 29f1e2e5b781e..7dabb1bddea77 100644
--- a/src/test/COMPILER_TESTS.md
+++ b/src/test/COMPILER_TESTS.md
@@ -140,13 +140,9 @@ check that the test compiles successfully.
 ### Editing and updating the reference files
 
 If you have changed the compiler's output intentionally, or you are
-making a new test, you can use the script `ui/update-references.sh` to
-update the references. When you run the test framework, it will report
-various errors: in those errors is a command you can use to run the
-`ui/update-references.sh` script, which will then copy over the files
-from the build directory and use them as the new reference. You can
-also just run `ui/update-all-references.sh`. In both cases, you can run
-the script with `--help` to get a help message.
+making a new test, you can pass `--bless` to the command you used to
+run the tests. This will then copy over the files
+from the build directory and use them as the new reference.
 
 ### Normalization
 
diff --git a/src/test/ui/E0508.ast.nll.stderr b/src/test/ui/E0508.ast.nll.stderr
new file mode 100644
index 0000000000000..28403644a234a
--- /dev/null
+++ b/src/test/ui/E0508.ast.nll.stderr
@@ -0,0 +1,9 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508.rs:18:18
+   |
+LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
+   |                  ^^^^^^^^ cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0508.ast.stderr b/src/test/ui/E0508.ast.stderr
new file mode 100644
index 0000000000000..5878b795b771c
--- /dev/null
+++ b/src/test/ui/E0508.ast.stderr
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508.rs:18:18
+   |
+LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider using a reference instead: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0508.mir.stderr b/src/test/ui/E0508.mir.stderr
new file mode 100644
index 0000000000000..28403644a234a
--- /dev/null
+++ b/src/test/ui/E0508.mir.stderr
@@ -0,0 +1,9 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508.rs:18:18
+   |
+LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
+   |                  ^^^^^^^^ cannot move out of here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
diff --git a/src/test/ui/E0508.rs b/src/test/ui/E0508.rs
new file mode 100644
index 0000000000000..0c3dce6b0346a
--- /dev/null
+++ b/src/test/ui/E0508.rs
@@ -0,0 +1,20 @@
+// 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.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z borrowck=mir
+
+struct NonCopy;
+
+fn main() {
+    let array = [NonCopy; 1];
+    let _value = array[0];  //[ast]~ ERROR [E0508]
+                            //[mir]~^ ERROR [E0508]
+}
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 812e9c5f39d87..b2ce5ce52f719 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -118,6 +118,9 @@ impl CompareMode {
 
 #[derive(Clone)]
 pub struct Config {
+    /// Whether to overwrite stderr/stdout files instead of complaining about changes in output
+    pub bless: bool,
+
     /// The library paths required for running the compiler
     pub compile_lib_path: PathBuf,
 
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 42a2cdfa55b5a..2bfc1ece09590 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -166,6 +166,11 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "FLAGS",
         )
         .optflag("", "verbose", "run tests verbosely, showing all output")
+        .optflag(
+            "",
+            "bless",
+            "overwrite stderr/stdout files instead of complaining about a mismatch",
+        )
         .optflag(
             "",
             "quiet",
@@ -290,6 +295,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
     let src_base = opt_path(matches, "src-base");
     let run_ignored = matches.opt_present("ignored");
     Config {
+        bless: matches.opt_present("bless"),
         compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
         run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
         rustc_path: opt_path(matches, "rustc-path"),
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 59d94e1fa51e1..9e5ae213568f2 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2596,15 +2596,13 @@ impl<'test> TestCx<'test> {
         }
 
         if errors > 0 {
-            println!("To update references, run this command from build directory:");
+            println!("To update references, rerun the tests and pass the `--bless` flag");
             let relative_path_to_file = self.testpaths
                 .relative_dir
                 .join(self.testpaths.file.file_name().unwrap());
             println!(
-                "{}/update-references.sh '{}' '{}'",
-                self.config.src_base.display(),
-                self.config.build_base.display(),
-                relative_path_to_file.display()
+                "To only update this specific test, also pass `--test-args {}`",
+                relative_path_to_file.display(),
             );
             self.fatal_proc_rec(
                 &format!("{} errors occurred comparing output.", errors),
@@ -2926,29 +2924,31 @@ impl<'test> TestCx<'test> {
             return 0;
         }
 
-        if expected.is_empty() {
-            println!("normalized {}:\n{}\n", kind, actual);
-        } else {
-            println!("diff of {}:\n", kind);
-            let diff_results = make_diff(expected, actual, 3);
-            for result in diff_results {
-                let mut line_number = result.line_number;
-                for line in result.lines {
-                    match line {
-                        DiffLine::Expected(e) => {
-                            println!("-\t{}", e);
-                            line_number += 1;
-                        }
-                        DiffLine::Context(c) => {
-                            println!("{}\t{}", line_number, c);
-                            line_number += 1;
-                        }
-                        DiffLine::Resulting(r) => {
-                            println!("+\t{}", r);
+        if !self.config.bless {
+            if expected.is_empty() {
+                println!("normalized {}:\n{}\n", kind, actual);
+            } else {
+                println!("diff of {}:\n", kind);
+                let diff_results = make_diff(expected, actual, 3);
+                for result in diff_results {
+                    let mut line_number = result.line_number;
+                    for line in result.lines {
+                        match line {
+                            DiffLine::Expected(e) => {
+                                println!("-\t{}", e);
+                                line_number += 1;
+                            }
+                            DiffLine::Context(c) => {
+                                println!("{}\t{}", line_number, c);
+                                line_number += 1;
+                            }
+                            DiffLine::Resulting(r) => {
+                                println!("+\t{}", r);
+                            }
                         }
                     }
+                    println!("");
                 }
-                println!("");
             }
         }
 
@@ -2958,19 +2958,47 @@ impl<'test> TestCx<'test> {
             .with_extra_extension(mode)
             .with_extra_extension(kind);
 
-        match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
-            Ok(()) => {}
-            Err(e) => self.fatal(&format!(
-                "failed to write {} to `{}`: {}",
+        let mut files = vec![output_file];
+        if self.config.bless {
+            files.push(expected_output_path(
+                self.testpaths,
+                self.revision,
+                &self.config.compare_mode,
                 kind,
-                output_file.display(),
-                e
-            )),
+            ));
+        }
+
+        for output_file in &files {
+            if actual.is_empty() {
+                if let Err(e) = ::std::fs::remove_file(output_file) {
+                    self.fatal(&format!(
+                        "failed to delete `{}`: {}",
+                        output_file.display(),
+                        e,
+                    ));
+                }
+            } else {
+                match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
+                    Ok(()) => {}
+                    Err(e) => self.fatal(&format!(
+                        "failed to write {} to `{}`: {}",
+                        kind,
+                        output_file.display(),
+                        e
+                    )),
+                }
+            }
         }
 
         println!("\nThe actual {0} differed from the expected {0}.", kind);
-        println!("Actual {} saved to {}", kind, output_file.display());
-        1
+        for output_file in files {
+            println!("Actual {} saved to {}", kind, output_file.display());
+        }
+        if self.config.bless {
+            0
+        } else {
+            1
+        }
     }
 
     fn create_stamp(&self) {