From 261efb6f5d0b3a7985bd1a76378ab5c9f7014c96 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Thu, 15 Mar 2018 17:10:09 -0500
Subject: [PATCH 01/37] suppress the default allow(unused) under
 --display-warnings

---
 src/librustdoc/markdown.rs |  1 +
 src/librustdoc/test.rs     | 27 +++++++++++++++++++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 0f107457d2bf8..b7d7cc0c44ce4 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -148,6 +148,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
 
     let mut opts = TestOptions::default();
     opts.no_crate_inject = true;
+    opts.display_warnings = display_warnings;
     let mut collector = Collector::new(input.to_owned(), cfgs, libs, externs,
                                        true, opts, maybe_sysroot, None,
                                        Some(PathBuf::from(input)),
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 117b21d47587f..58bcbe9aa93a1 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -45,7 +45,12 @@ use html::markdown;
 
 #[derive(Clone, Default)]
 pub struct TestOptions {
+    /// Whether to disable the default `extern crate my_crate;` when creating doctests.
     pub no_crate_inject: bool,
+    /// Whether to emit compilation warnings when compiling doctests. Setting this will suppress
+    /// the default `#![allow(unused)]`.
+    pub display_warnings: bool,
+    /// Additional crate-level attributes to add to doctests.
     pub attrs: Vec<String>,
 }
 
@@ -107,7 +112,8 @@ pub fn run(input_path: &Path,
     let crate_name = crate_name.unwrap_or_else(|| {
         ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input)
     });
-    let opts = scrape_test_config(hir_forest.krate());
+    let mut opts = scrape_test_config(hir_forest.krate());
+    opts.display_warnings |= display_warnings;
     let mut collector = Collector::new(crate_name,
                                        cfgs,
                                        libs,
@@ -146,6 +152,7 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
 
     let mut opts = TestOptions {
         no_crate_inject: false,
+        display_warnings: false,
         attrs: Vec::new(),
     };
 
@@ -347,7 +354,7 @@ pub fn make_test(s: &str,
     let mut line_offset = 0;
     let mut prog = String::new();
 
-    if opts.attrs.is_empty() {
+    if opts.attrs.is_empty() && !opts.display_warnings {
         // If there aren't any attributes supplied by #![doc(test(attr(...)))], then allow some
         // lints that are commonly triggered in doctests. The crate-level test attributes are
         // commonly used to make tests fail in case they trigger warnings, so having this there in
@@ -772,6 +779,7 @@ assert_eq!(2+2, 4);
         //adding it anyway
         let opts = TestOptions {
             no_crate_inject: true,
+            display_warnings: false,
             attrs: vec![],
         };
         let input =
@@ -924,4 +932,19 @@ assert_eq!(2+2, 4);".to_string();
         let output = make_test(input, None, true, &opts);
         assert_eq!(output, (expected.clone(), 1));
     }
+
+    #[test]
+    fn make_test_display_warnings() {
+        //if the user is asking to display doctest warnings, suppress the default allow(unused)
+        let mut opts = TestOptions::default();
+        opts.display_warnings = true;
+        let input =
+"assert_eq!(2+2, 4);";
+        let expected =
+"fn main() {
+assert_eq!(2+2, 4);
+}".to_string();
+        let output = make_test(input, None, false, &opts);
+        assert_eq!(output, (expected.clone(), 2));
+    }
 }

From 683ad942966c427be773b412d9314baa55a6e188 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Thu, 15 Mar 2018 10:38:12 +0100
Subject: [PATCH 02/37] Add OnDrop

---
 src/librustc_data_structures/lib.rs | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 81246aea1b56e..bf0b3726bb301 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -76,6 +76,14 @@ pub mod flock;
 pub mod sync;
 pub mod owning_ref;
 
+pub struct OnDrop<F: Fn()>(pub F);
+
+impl<F: Fn()> Drop for OnDrop<F> {
+      fn drop(&mut self) {
+            (self.0)();
+      }
+}
+
 // See comments in src/librustc/lib.rs
 #[doc(hidden)]
 pub fn __noop_fix_for_27438() {}

From 3b43dcbb4c62a36b68afd7f9a1bf12aed1b53d7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Wed, 14 Mar 2018 20:11:23 +0100
Subject: [PATCH 03/37] Replace Rc with Lrc

---
 src/librustc/middle/const_val.rs               | 4 ++--
 src/librustc/traits/query/dropck_outlives.rs   | 6 +++---
 src/librustc/traits/query/normalize.rs         | 6 +++---
 src/librustc/ty/structural_impls.rs            | 3 ++-
 src/librustc_mir/interpret/const_eval.rs       | 6 +++---
 src/librustc_traits/dropck_outlives.rs         | 4 ++--
 src/librustc_traits/normalize_projection_ty.rs | 4 ++--
 7 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs
index 8c3dfd0bce752..19a7576b7ceac 100644
--- a/src/librustc/middle/const_val.rs
+++ b/src/librustc/middle/const_val.rs
@@ -19,7 +19,7 @@ use graphviz::IntoCow;
 use syntax_pos::Span;
 
 use std::borrow::Cow;
-use std::rc::Rc;
+use rustc_data_structures::sync::Lrc;
 
 pub type EvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ConstEvalErr<'tcx>>;
 
@@ -52,7 +52,7 @@ impl<'tcx> ConstVal<'tcx> {
 #[derive(Clone, Debug)]
 pub struct ConstEvalErr<'tcx> {
     pub span: Span,
-    pub kind: Rc<ErrKind<'tcx>>,
+    pub kind: Lrc<ErrKind<'tcx>>,
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 1caab6fd89ef9..e16a1082214f7 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -15,7 +15,7 @@ use std::iter::FromIterator;
 use traits::query::CanonicalTyGoal;
 use ty::{self, Ty, TyCtxt};
 use ty::subst::Kind;
-use std::rc::Rc;
+use rustc_data_structures::sync::Lrc;
 
 impl<'cx, 'gcx, 'tcx> At<'cx, 'gcx, 'tcx> {
     /// Given a type `ty` of some value being dropped, computes a set
@@ -182,13 +182,13 @@ impl_stable_hash_for!(struct DropckOutlivesResult<'tcx> {
 
 impl<'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for QueryResult<'tcx, DropckOutlivesResult<'tcx>> {
     // we ought to intern this, but I'm too lazy just now
-    type Canonicalized = Rc<Canonical<'gcx, QueryResult<'gcx, DropckOutlivesResult<'gcx>>>>;
+    type Canonicalized = Lrc<Canonical<'gcx, QueryResult<'gcx, DropckOutlivesResult<'gcx>>>>;
 
     fn intern(
         _gcx: TyCtxt<'_, 'gcx, 'gcx>,
         value: Canonical<'gcx, Self::Lifted>,
     ) -> Self::Canonicalized {
-        Rc::new(value)
+        Lrc::new(value)
     }
 }
 
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 70c5cf5f39029..63f50cff4c2ad 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -17,7 +17,7 @@ use infer::at::At;
 use infer::canonical::{Canonical, Canonicalize, QueryResult};
 use middle::const_val::ConstVal;
 use mir::interpret::GlobalId;
-use std::rc::Rc;
+use rustc_data_structures::sync::Lrc;
 use traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
 use traits::query::CanonicalProjectionGoal;
 use traits::project::Normalized;
@@ -259,13 +259,13 @@ impl<'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for ty::ParamEnvAnd<'tcx, ty::Pr
 
 impl<'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for QueryResult<'tcx, NormalizationResult<'tcx>> {
     // we ought to intern this, but I'm too lazy just now
-    type Canonicalized = Rc<Canonical<'gcx, QueryResult<'gcx, NormalizationResult<'gcx>>>>;
+    type Canonicalized = Lrc<Canonical<'gcx, QueryResult<'gcx, NormalizationResult<'gcx>>>>;
 
     fn intern(
         _gcx: TyCtxt<'_, 'gcx, 'gcx>,
         value: Canonical<'gcx, Self::Lifted>,
     ) -> Self::Canonicalized {
-        Rc::new(value)
+        Lrc::new(value)
     }
 }
 
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index c9a69d5405c9a..3fc20508ad7ee 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -18,6 +18,7 @@ use ty::{self, Lift, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc_data_structures::sync::Lrc;
 use mir::interpret;
 
 use std::rc::Rc;
@@ -465,7 +466,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
         tcx.lift(&*self.kind).map(|kind| {
             ConstEvalErr {
                 span: self.span,
-                kind: Rc::new(kind),
+                kind: Lrc::new(kind),
             }
         })
     }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 82eb28287b033..50997089a5764 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -14,7 +14,7 @@ use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory};
 
 use std::fmt;
 use std::error::Error;
-use std::rc::Rc;
+use rustc_data_structures::sync::Lrc;
 
 pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -477,7 +477,7 @@ pub fn const_eval_provider<'a, 'tcx>(
         // Do match-check before building MIR
         if tcx.check_match(def_id).is_err() {
             return Err(ConstEvalErr {
-                kind: Rc::new(CheckMatchError),
+                kind: Lrc::new(CheckMatchError),
                 span,
             });
         }
@@ -489,7 +489,7 @@ pub fn const_eval_provider<'a, 'tcx>(
         // Do not continue into miri if typeck errors occurred; it will fail horribly
         if tables.tainted_by_errors {
             return Err(ConstEvalErr {
-                kind: Rc::new(TypeckError),
+                kind: Lrc::new(TypeckError),
                 span,
             });
         }
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index 2a8cfe5cc06b3..1fe2f87128abd 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -16,14 +16,14 @@ use rustc::traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResu
 use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use rustc::ty::subst::Subst;
 use rustc::util::nodemap::FxHashSet;
-use std::rc::Rc;
+use rustc_data_structures::sync::Lrc;
 use syntax::codemap::{Span, DUMMY_SP};
 use util;
 
 crate fn dropck_outlives<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
     goal: CanonicalTyGoal<'tcx>,
-) -> Result<Rc<Canonical<'tcx, QueryResult<'tcx, DropckOutlivesResult<'tcx>>>>, NoSolution> {
+) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, DropckOutlivesResult<'tcx>>>>, NoSolution> {
     debug!("dropck_outlives(goal={:#?})", goal);
 
     tcx.infer_ctxt().enter(|ref infcx| {
diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs
index 55785d9586cc3..62d5ef11551c0 100644
--- a/src/librustc_traits/normalize_projection_ty.rs
+++ b/src/librustc_traits/normalize_projection_ty.rs
@@ -14,7 +14,7 @@ use rustc::traits::{self, FulfillmentContext, Normalized, ObligationCause,
 use rustc::traits::query::{CanonicalProjectionGoal, NoSolution, normalize::NormalizationResult};
 use rustc::ty::{ParamEnvAnd, TyCtxt};
 use rustc::util::common::CellUsizeExt;
-use std::rc::Rc;
+use rustc_data_structures::sync::Lrc;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::DUMMY_SP;
 use util;
@@ -22,7 +22,7 @@ use util;
 crate fn normalize_projection_ty<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
     goal: CanonicalProjectionGoal<'tcx>,
-) -> Result<Rc<Canonical<'tcx, QueryResult<'tcx, NormalizationResult<'tcx>>>>, NoSolution> {
+) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, NormalizationResult<'tcx>>>>, NoSolution> {
     debug!("normalize_provider(goal={:#?})", goal);
 
     tcx.sess.perf_stats.normalize_projection_ty.increment();

From 910bf840cce1da57b96f7ac15f8b803675bb8a3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Thu, 15 Mar 2018 10:09:20 +0100
Subject: [PATCH 04/37] Always print `aborting due to n previous error(s)` and
 only print it once for multi-threaded code

---
 src/librustc_driver/lib.rs     | 54 +++++++++++++++++++---------------
 src/librustc_errors/lib.rs     | 34 +++++++++++----------
 src/librustc_typeck/astconv.rs |  3 +-
 3 files changed, 50 insertions(+), 41 deletions(-)

diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 5a1983bfec64f..2a15d57a262e1 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -63,6 +63,7 @@ use rustc_resolve as resolve;
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::OnDrop;
 use rustc::session::{self, config, Session, build_session, CompileResult};
 use rustc::session::CompileIncomplete;
 use rustc::session::config::{Input, PrintRequest, ErrorOutputType};
@@ -515,30 +516,35 @@ fn run_compiler_impl<'a>(args: &[String],
     target_features::add_configuration(&mut cfg, &sess, &*trans);
     sess.parse_sess.config = cfg;
 
-    let plugins = sess.opts.debugging_opts.extra_plugins.clone();
-
-    let cstore = CStore::new(trans.metadata_loader());
-
-    do_or_return!(callbacks.late_callback(&*trans,
-                                          &matches,
-                                          &sess,
-                                          &cstore,
-                                          &input,
-                                          &odir,
-                                          &ofile), Some(sess));
-
-    let control = callbacks.build_controller(&sess, &matches);
-
-    (driver::compile_input(trans,
-                           &sess,
-                           &cstore,
-                           &input_file_path,
-                           &input,
-                           &odir,
-                           &ofile,
-                           Some(plugins),
-                           &control),
-     Some(sess))
+    let result = {
+        let plugins = sess.opts.debugging_opts.extra_plugins.clone();
+
+        let cstore = CStore::new(trans.metadata_loader());
+
+        do_or_return!(callbacks.late_callback(&*trans,
+                                              &matches,
+                                              &sess,
+                                              &cstore,
+                                              &input,
+                                              &odir,
+                                              &ofile), Some(sess));
+
+        let _sess_abort_error = OnDrop(|| sess.diagnostic().print_error_count());
+
+        let control = callbacks.build_controller(&sess, &matches);
+
+        driver::compile_input(trans,
+                              &sess,
+                              &cstore,
+                              &input_file_path,
+                              &input,
+                              &odir,
+                              &ofile,
+                              Some(plugins),
+                              &control)
+    };
+
+    (result, Some(sess))
 }
 
 // Extract output directory and file from matches.
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 7148969191f2b..b3265c21884be 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -555,21 +555,15 @@ impl Handler {
     pub fn has_errors(&self) -> bool {
         self.err_count() > 0
     }
-    pub fn abort_if_errors(&self) {
-        let s;
-        match self.err_count() {
-            0 => {
-                if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
-                    DiagnosticBuilder::new_diagnostic(self, bug).emit();
-                }
-                return;
-            }
-            1 => s = "aborting due to previous error".to_string(),
-            _ => {
-                s = format!("aborting due to {} previous errors", self.err_count());
-            }
-        }
-        let err = self.fatal(&s);
+
+    pub fn print_error_count(&self) {
+        let s = match self.err_count() {
+            0 => return,
+            1 => "aborting due to previous error".to_string(),
+            _ => format!("aborting due to {} previous errors", self.err_count())
+        };
+
+        let _ = self.fatal(&s);
 
         let can_show_explain = self.emitter.borrow().should_show_explain();
         let are_there_diagnostics = !self.tracked_diagnostic_codes.borrow().is_empty();
@@ -600,8 +594,16 @@ impl Handler {
                 }
             }
         }
+    }
 
-        err.raise();
+    pub fn abort_if_errors(&self) {
+        if self.err_count() == 0 {
+            if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
+                DiagnosticBuilder::new_diagnostic(self, bug).emit();
+            }
+            return;
+        }
+        FatalError.raise();
     }
     pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) {
         if lvl == Warning && !self.flags.can_emit_warnings {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 827ca79334cbe..bc69fbdb77837 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -27,6 +27,7 @@ use std::slice;
 use require_c_abi_if_variadic;
 use util::common::ErrorReported;
 use util::nodemap::FxHashSet;
+use errors::FatalError;
 
 use std::iter;
 use syntax::{abi, ast};
@@ -337,7 +338,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
             Def::Trait(trait_def_id) => trait_def_id,
             Def::TraitAlias(alias_def_id) => alias_def_id,
             Def::Err => {
-                self.tcx().sess.fatal("cannot continue compilation due to previous error");
+                FatalError.raise();
             }
             _ => unreachable!(),
         }

From b1d872b38eaacefbef73faa6a4a0c07622a8c941 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Thu, 15 Mar 2018 16:13:47 +0100
Subject: [PATCH 05/37] Update tests

---
 src/test/ui-fulldeps/custom-derive/issue-36935.stderr         | 2 ++
 src/test/ui-fulldeps/proc-macro/load-panic.stderr             | 2 ++
 src/test/ui/codemap_tests/two_files.stderr                    | 3 ++-
 src/test/ui/cross-file-errors/main.stderr                     | 2 ++
 src/test/ui/did_you_mean/recursion_limit_macro.stderr         | 2 ++
 src/test/ui/error-codes/E0404.stderr                          | 3 ++-
 src/test/ui/error-codes/E0405.stderr                          | 3 ++-
 src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr   | 2 ++
 src/test/ui/feature-gate-fn_must_use.stderr                   | 2 ++
 .../feature-gate/issue-43106-gating-of-builtin-attrs.stderr   | 2 ++
 .../ui/feature-gate/issue-43106-gating-of-deprecated.stderr   | 2 ++
 src/test/ui/impl-trait/universal_wrong_bounds.stderr          | 4 +++-
 src/test/ui/issue-22644.stderr                                | 2 ++
 src/test/ui/issue-44406.stderr                                | 2 ++
 src/test/ui/lint-output-format-2.stderr                       | 2 ++
 src/test/ui/loops-reject-duplicate-labels-2.stderr            | 2 ++
 src/test/ui/loops-reject-duplicate-labels.stderr              | 2 ++
 src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr    | 2 ++
 src/test/ui/loops-reject-lifetime-shadowing-label.stderr      | 2 ++
 src/test/ui/macro-context.stderr                              | 2 ++
 src/test/ui/macros/macro_path_as_generic_bound.stderr         | 3 ++-
 src/test/ui/macros/trace_faulty_macros.stderr                 | 2 ++
 src/test/ui/raw_string.stderr                                 | 2 ++
 src/test/ui/resolve/issue-21221-1.stderr                      | 4 +++-
 src/test/ui/resolve/issue-21221-2.stderr                      | 3 ++-
 src/test/ui/resolve/issue-21221-3.stderr                      | 3 ++-
 src/test/ui/resolve/issue-21221-4.stderr                      | 3 ++-
 src/test/ui/resolve/issue-3907.stderr                         | 3 ++-
 src/test/ui/resolve/issue-5035.stderr                         | 4 +++-
 .../ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr | 4 +++-
 .../generic-associated-types-where.stderr                     | 2 --
 src/test/ui/span/issue-24690.stderr                           | 2 ++
 src/test/ui/span/issue-35987.stderr                           | 3 ++-
 33 files changed, 68 insertions(+), 15 deletions(-)

diff --git a/src/test/ui-fulldeps/custom-derive/issue-36935.stderr b/src/test/ui-fulldeps/custom-derive/issue-36935.stderr
index b082999a8978d..0278256994120 100644
--- a/src/test/ui-fulldeps/custom-derive/issue-36935.stderr
+++ b/src/test/ui-fulldeps/custom-derive/issue-36935.stderr
@@ -6,3 +6,5 @@ LL | #[derive(Foo, Bar)] //~ ERROR proc-macro derive panicked
    |
    = help: message: lolnope
 
+error: aborting due to previous error
+
diff --git a/src/test/ui-fulldeps/proc-macro/load-panic.stderr b/src/test/ui-fulldeps/proc-macro/load-panic.stderr
index edfd134469cda..30ad53f9041f0 100644
--- a/src/test/ui-fulldeps/proc-macro/load-panic.stderr
+++ b/src/test/ui-fulldeps/proc-macro/load-panic.stderr
@@ -6,3 +6,5 @@ LL | #[derive(A)]
    |
    = help: message: nope!
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/codemap_tests/two_files.stderr b/src/test/ui/codemap_tests/two_files.stderr
index 614531c982128..e247e86fbcb22 100644
--- a/src/test/ui/codemap_tests/two_files.stderr
+++ b/src/test/ui/codemap_tests/two_files.stderr
@@ -4,5 +4,6 @@ error[E0404]: expected trait, found type alias `Bar`
 LL | impl Bar for Baz { } //~ ERROR expected trait, found type alias
    |      ^^^ type aliases cannot be used for traits
 
-error: cannot continue compilation due to previous error
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/cross-file-errors/main.stderr b/src/test/ui/cross-file-errors/main.stderr
index a9db5214e6a2e..8fe795f7f1d8a 100644
--- a/src/test/ui/cross-file-errors/main.stderr
+++ b/src/test/ui/cross-file-errors/main.stderr
@@ -9,3 +9,5 @@ LL |         _
 LL |     underscore!();
    |     -------------- in this macro invocation
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/did_you_mean/recursion_limit_macro.stderr b/src/test/ui/did_you_mean/recursion_limit_macro.stderr
index f6bce55528c7d..265a688df9910 100644
--- a/src/test/ui/did_you_mean/recursion_limit_macro.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_macro.stderr
@@ -9,3 +9,5 @@ LL |     recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9);
    |
    = help: consider adding a `#![recursion_limit="20"]` attribute to your crate
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/error-codes/E0404.stderr b/src/test/ui/error-codes/E0404.stderr
index 9f705da586167..afb748bedbe0f 100644
--- a/src/test/ui/error-codes/E0404.stderr
+++ b/src/test/ui/error-codes/E0404.stderr
@@ -10,5 +10,6 @@ error[E0404]: expected trait, found struct `Foo`
 LL | fn baz<T: Foo>(_: T) {} //~ ERROR E0404
    |           ^^^ not a trait
 
-error: cannot continue compilation due to previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/error-codes/E0405.stderr b/src/test/ui/error-codes/E0405.stderr
index b5901dd9c848b..27190af1c6c11 100644
--- a/src/test/ui/error-codes/E0405.stderr
+++ b/src/test/ui/error-codes/E0405.stderr
@@ -4,5 +4,6 @@ error[E0405]: cannot find trait `SomeTrait` in this scope
 LL | impl SomeTrait for Foo {} //~ ERROR E0405
    |      ^^^^^^^^^ not found in this scope
 
-error: cannot continue compilation due to previous error
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr
index a9952ff4fac13..a2c1dedff385a 100644
--- a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr
+++ b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr
@@ -4,3 +4,5 @@ error: compilation successful
 LL | fn main() {} //~ ERROR compilation successful
    | ^^^^^^^^^^^^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate-fn_must_use.stderr b/src/test/ui/feature-gate-fn_must_use.stderr
index 4772cf28f6c12..431c57abd2653 100644
--- a/src/test/ui/feature-gate-fn_must_use.stderr
+++ b/src/test/ui/feature-gate-fn_must_use.stderr
@@ -20,3 +20,5 @@ error: compilation successful
 LL | fn main() {} //~ ERROR compilation successful
    | ^^^^^^^^^^^^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
index 9c4fb79f6f1aa..0beed62798710 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
@@ -1316,3 +1316,5 @@ LL | |     println!("Hello World");
 LL | | }
    | |_^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr
index 83f6e016370bb..802c5d9384d75 100644
--- a/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr
+++ b/src/test/ui/feature-gate/issue-43106-gating-of-deprecated.stderr
@@ -6,3 +6,5 @@ LL | |     println!("Hello World");
 LL | | }
    | |_^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/universal_wrong_bounds.stderr b/src/test/ui/impl-trait/universal_wrong_bounds.stderr
index a02fc1f748faa..3cc0bebe81655 100644
--- a/src/test/ui/impl-trait/universal_wrong_bounds.stderr
+++ b/src/test/ui/impl-trait/universal_wrong_bounds.stderr
@@ -24,5 +24,7 @@ help: possible candidate is found in another module, you can import it into scop
 LL | use std::fmt::Debug;
    |
 
-error: cannot continue compilation due to previous error
+error: aborting due to 3 previous errors
 
+Some errors occurred: E0405, E0425.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr
index 257b9bd235d76..aeb465b2ab233 100644
--- a/src/test/ui/issue-22644.stderr
+++ b/src/test/ui/issue-22644.stderr
@@ -89,3 +89,5 @@ error: expected type, found `4`
 LL |     println!("{}", a: &mut 4); //~ ERROR expected type, found `4`
    |                            ^ expecting a type here because of type ascription
 
+error: aborting due to 9 previous errors
+
diff --git a/src/test/ui/issue-44406.stderr b/src/test/ui/issue-44406.stderr
index 443b28cf09968..de7c11732e4a3 100644
--- a/src/test/ui/issue-44406.stderr
+++ b/src/test/ui/issue-44406.stderr
@@ -13,3 +13,5 @@ LL |         bar(baz: $rest)
 LL |     foo!(true); //~ ERROR expected type, found keyword
    |          ^^^^ expecting a type here because of type ascription
 
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint-output-format-2.stderr b/src/test/ui/lint-output-format-2.stderr
index b2d1e1ac05822..d484061ef9661 100644
--- a/src/test/ui/lint-output-format-2.stderr
+++ b/src/test/ui/lint-output-format-2.stderr
@@ -22,3 +22,5 @@ LL | |     let _y = bar();
 LL | | }
    | |_^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/loops-reject-duplicate-labels-2.stderr b/src/test/ui/loops-reject-duplicate-labels-2.stderr
index d35ed4ff88a67..830270a99d112 100644
--- a/src/test/ui/loops-reject-duplicate-labels-2.stderr
+++ b/src/test/ui/loops-reject-duplicate-labels-2.stderr
@@ -70,3 +70,5 @@ LL | |     foo();
 LL | | }
    | |_^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/loops-reject-duplicate-labels.stderr b/src/test/ui/loops-reject-duplicate-labels.stderr
index d1b874ea99729..a71f98b812a8c 100644
--- a/src/test/ui/loops-reject-duplicate-labels.stderr
+++ b/src/test/ui/loops-reject-duplicate-labels.stderr
@@ -73,3 +73,5 @@ LL | |     foo();
 LL | | }
    | |_^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr b/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr
index 0cdd58fdbd75d..af524d5b01766 100644
--- a/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr
+++ b/src/test/ui/loops-reject-labels-shadowing-lifetimes.stderr
@@ -108,3 +108,5 @@ LL | |     foo();
 LL | | }
    | |_^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/loops-reject-lifetime-shadowing-label.stderr b/src/test/ui/loops-reject-lifetime-shadowing-label.stderr
index a050aec50c72b..999cfb9cc3c6b 100644
--- a/src/test/ui/loops-reject-lifetime-shadowing-label.stderr
+++ b/src/test/ui/loops-reject-lifetime-shadowing-label.stderr
@@ -14,3 +14,5 @@ LL | |     foo();
 LL | | }
    | |_^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/macro-context.stderr b/src/test/ui/macro-context.stderr
index 4dc6bbe4d656c..b3e67fb2607cd 100644
--- a/src/test/ui/macro-context.stderr
+++ b/src/test/ui/macro-context.stderr
@@ -43,3 +43,5 @@ LL |     () => ( i ; typeof );   //~ ERROR expected expression, found reserved k
 LL |     m!();
    |     ----- in this macro invocation
 
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/macros/macro_path_as_generic_bound.stderr b/src/test/ui/macros/macro_path_as_generic_bound.stderr
index 06d22714dd8b6..0f9f0607c5bf2 100644
--- a/src/test/ui/macros/macro_path_as_generic_bound.stderr
+++ b/src/test/ui/macros/macro_path_as_generic_bound.stderr
@@ -4,5 +4,6 @@ error[E0433]: failed to resolve. Use of undeclared type or module `m`
 LL | foo!(m::m2::A); //~ ERROR failed to resolve
    |      ^ Use of undeclared type or module `m`
 
-error: cannot continue compilation due to previous error
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr
index 9fb5b17a3114b..a9ffef8ef8090 100644
--- a/src/test/ui/macros/trace_faulty_macros.stderr
+++ b/src/test/ui/macros/trace_faulty_macros.stderr
@@ -45,3 +45,5 @@ LL |     my_recursive_macro!();
    = note: expanding `my_recursive_macro! {  }`
    = note: to `my_recursive_macro ! (  ) ;`
 
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/raw_string.stderr b/src/test/ui/raw_string.stderr
index b8aa596ef953a..ddf1cfe406f7c 100644
--- a/src/test/ui/raw_string.stderr
+++ b/src/test/ui/raw_string.stderr
@@ -6,3 +6,5 @@ LL |     let x = r##"lol"#;
    |
    = note: this raw string should be terminated with `"##`
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr
index a9d2aeee2d151..3edfa33d80a02 100644
--- a/src/test/ui/resolve/issue-21221-1.stderr
+++ b/src/test/ui/resolve/issue-21221-1.stderr
@@ -45,5 +45,7 @@ help: possible candidate is found in another module, you can import it into scop
 LL | use std::ops::Div;
    |
 
-error: cannot continue compilation due to previous error
+error: aborting due to 4 previous errors
 
+Some errors occurred: E0405, E0412.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/issue-21221-2.stderr b/src/test/ui/resolve/issue-21221-2.stderr
index c61ffe3b33e8a..e11fe9ac4cf11 100644
--- a/src/test/ui/resolve/issue-21221-2.stderr
+++ b/src/test/ui/resolve/issue-21221-2.stderr
@@ -8,5 +8,6 @@ help: possible candidate is found in another module, you can import it into scop
 LL | use foo::bar::T;
    |
 
-error: cannot continue compilation due to previous error
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr
index 7725f74cb49fc..f406cd6e35fcf 100644
--- a/src/test/ui/resolve/issue-21221-3.stderr
+++ b/src/test/ui/resolve/issue-21221-3.stderr
@@ -8,5 +8,6 @@ help: possible candidate is found in another module, you can import it into scop
 LL | use issue_21221_3::outer::OuterTrait;
    |
 
-error: cannot continue compilation due to previous error
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr
index b0a4d5ba4d898..c0a7f1734f49c 100644
--- a/src/test/ui/resolve/issue-21221-4.stderr
+++ b/src/test/ui/resolve/issue-21221-4.stderr
@@ -8,5 +8,6 @@ help: possible candidate is found in another module, you can import it into scop
 LL | use issue_21221_4::T;
    |
 
-error: cannot continue compilation due to previous error
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr
index 2b8b2b20685f8..3627c09b28fd9 100644
--- a/src/test/ui/resolve/issue-3907.stderr
+++ b/src/test/ui/resolve/issue-3907.stderr
@@ -8,5 +8,6 @@ help: possible better candidate is found in another module, you can import it in
 LL | use issue_3907::Foo;
    |
 
-error: cannot continue compilation due to previous error
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0404`.
diff --git a/src/test/ui/resolve/issue-5035.stderr b/src/test/ui/resolve/issue-5035.stderr
index 6597f05889af8..353a0b1c3d9d0 100644
--- a/src/test/ui/resolve/issue-5035.stderr
+++ b/src/test/ui/resolve/issue-5035.stderr
@@ -13,5 +13,7 @@ LL | impl K for isize {} //~ ERROR expected trait, found type alias `K`
    |      did you mean `I`?
    |      type aliases cannot be used for traits
 
-error: cannot continue compilation due to previous error
+error: aborting due to 2 previous errors
 
+Some errors occurred: E0404, E0432.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr
index 6e7bd28d16fc3..f32c5e9b2c6bd 100644
--- a/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr
+++ b/src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr
@@ -10,5 +10,7 @@ error[E0404]: expected trait, found type alias `Typedef`
 LL | fn g<F:Typedef(isize) -> isize>(x: F) {}
    |        ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used for traits
 
-error: cannot continue compilation due to previous error
+error: aborting due to 2 previous errors
 
+Some errors occurred: E0404, E0405.
+For more information about an error, try `rustc --explain E0404`.
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr
index bb55d86f620b7..e69de29bb2d1d 100644
--- a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr
+++ b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr
@@ -1,2 +0,0 @@
-error: cannot continue compilation due to previous error
-
diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr
index 6a4ec73b27a66..b496a1a76c017 100644
--- a/src/test/ui/span/issue-24690.stderr
+++ b/src/test/ui/span/issue-24690.stderr
@@ -36,3 +36,5 @@ LL | |     println!("{}", theTwo);
 LL | | }
    | |_^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr
index 2d4a7cc72f5f6..1dd45bb1e5efe 100644
--- a/src/test/ui/span/issue-35987.stderr
+++ b/src/test/ui/span/issue-35987.stderr
@@ -8,5 +8,6 @@ help: possible better candidate is found in another module, you can import it in
 LL | use std::ops::Add;
    |
 
-error: cannot continue compilation due to previous error
+error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0404`.

From 9e6268191205c42bc7958d949fa48811d60857f9 Mon Sep 17 00:00:00 2001
From: Mike Hommey <mh@glandium.org>
Date: Sat, 17 Mar 2018 10:32:29 +0900
Subject: [PATCH 06/37] Remove core::fmt::num::Decimal

Before ebf9e1aaf6, it was used for Display::fmt, but ebf9e1aaf6 replaced
that with a faster implementation, and nothing else uses it.
---
 src/libcore/fmt/num.rs | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index 2992e7cf8db34..57e3b849ae1e3 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -107,10 +107,6 @@ struct Binary;
 #[derive(Clone, PartialEq)]
 struct Octal;
 
-/// A decimal (base 10) radix
-#[derive(Clone, PartialEq)]
-struct Decimal;
-
 /// A hexadecimal (base 16) radix, formatted with lower-case characters
 #[derive(Clone, PartialEq)]
 struct LowerHex;
@@ -136,7 +132,6 @@ macro_rules! radix {
 
 radix! { Binary,    2, "0b", x @  0 ...  1 => b'0' + x }
 radix! { Octal,     8, "0o", x @  0 ...  7 => b'0' + x }
-radix! { Decimal,  10, "",   x @  0 ...  9 => b'0' + x }
 radix! { LowerHex, 16, "0x", x @  0 ...  9 => b'0' + x,
                              x @ 10 ... 15 => b'a' + (x - 10) }
 radix! { UpperHex, 16, "0x", x @  0 ...  9 => b'0' + x,

From e85c9227c2e913b71f0d7b6cc2322d7897f28554 Mon Sep 17 00:00:00 2001
From: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
Date: Tue, 27 Feb 2018 16:51:12 +0900
Subject: [PATCH 07/37] rustc_driver: get rid of extra thread on Unix

---
 src/librustc_driver/lib.rs           | 51 +++++++++++++++++++++++-----
 src/libstd/sys_common/thread_info.rs |  4 +++
 src/libstd/thread/mod.rs             |  8 +++++
 3 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index f1f3a0519bbcb..8605764497a16 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -24,6 +24,7 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(set_stdio)]
+#![feature(rustc_stack_internals)]
 
 extern crate arena;
 extern crate getopts;
@@ -1461,16 +1462,50 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
     // Temporarily have stack size set to 16MB to deal with nom-using crates failing
     const STACK_SIZE: usize = 16 * 1024 * 1024; // 16MB
 
-    let mut cfg = thread::Builder::new().name("rustc".to_string());
+    #[cfg(unix)]
+    let spawn_thread = unsafe {
+        // Fetch the current resource limits
+        let mut rlim = libc::rlimit {
+            rlim_cur: 0,
+            rlim_max: 0,
+        };
+        if libc::getrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
+            let err = io::Error::last_os_error();
+            error!("in_rustc_thread: error calling getrlimit: {}", err);
+            true
+        } else if rlim.rlim_max < STACK_SIZE as libc::rlim_t {
+            true
+        } else {
+            rlim.rlim_cur = STACK_SIZE as libc::rlim_t;
+            if libc::setrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
+                let err = io::Error::last_os_error();
+                error!("in_rustc_thread: error calling setrlimit: {}", err);
+                true
+            } else {
+                std::thread::update_stack_guard();
+                false
+            }
+        }
+    };
 
-    // FIXME: Hacks on hacks. If the env is trying to override the stack size
-    // then *don't* set it explicitly.
-    if env::var_os("RUST_MIN_STACK").is_none() {
-        cfg = cfg.stack_size(STACK_SIZE);
-    }
+    #[cfg(not(unix))]
+    let spawn_thread = true;
+
+    // The or condition is added from backward compatibility.
+    if spawn_thread || env::var_os("RUST_MIN_STACK").is_some() {
+        let mut cfg = thread::Builder::new().name("rustc".to_string());
+
+        // FIXME: Hacks on hacks. If the env is trying to override the stack size
+        // then *don't* set it explicitly.
+        if env::var_os("RUST_MIN_STACK").is_none() {
+            cfg = cfg.stack_size(STACK_SIZE);
+        }
 
-    let thread = cfg.spawn(f);
-    thread.unwrap().join()
+        let thread = cfg.spawn(f);
+        thread.unwrap().join()
+    } else {
+        Ok(f())
+    }
 }
 
 /// Get a list of extra command-line flags provided by the user, as strings.
diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs
index 6a2b6742367a5..d75cbded7347b 100644
--- a/src/libstd/sys_common/thread_info.rs
+++ b/src/libstd/sys_common/thread_info.rs
@@ -50,3 +50,7 @@ pub fn set(stack_guard: Option<Guard>, thread: Thread) {
         thread,
     }));
 }
+
+pub fn reset_guard(stack_guard: Option<Guard>) {
+    THREAD_INFO.with(move |c| c.borrow_mut().as_mut().unwrap().stack_guard = stack_guard);
+}
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 71aee673cfe3e..b686ddc205ea7 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -208,6 +208,14 @@ pub use self::local::{LocalKey, AccessError};
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner;
 
+/// Function used for resetting the main stack guard address after setrlimit().
+/// This is POSIX specific and unlikely to be directly stabilized.
+#[unstable(feature = "rustc_stack_internals", issue = "0")]
+pub unsafe fn update_stack_guard() {
+    let main_guard = imp::guard::init();
+    thread_info::reset_guard(main_guard);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Builder
 ////////////////////////////////////////////////////////////////////////////////

From 1bb89f1b3cf1e4b5fa83391872136251c0030c1e Mon Sep 17 00:00:00 2001
From: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
Date: Tue, 6 Mar 2018 13:33:36 +0900
Subject: [PATCH 08/37] rustc_driver: get rid of extra thread on Windows

---
 src/librustc_driver/lib.rs | 6 +++++-
 src/rustc/rustc.rs         | 9 +++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 8605764497a16..761797239412e 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -1488,7 +1488,11 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
         }
     };
 
-    #[cfg(not(unix))]
+    // We set the stack size at link time. See src/rustc/rustc.rs.
+    #[cfg(windows)]
+    let spawn_thread = false;
+
+    #[cfg(not(any(windows,unix)))]
     let spawn_thread = true;
 
     // The or condition is added from backward compatibility.
diff --git a/src/rustc/rustc.rs b/src/rustc/rustc.rs
index bfd01146d2c46..bd36aaf01f860 100644
--- a/src/rustc/rustc.rs
+++ b/src/rustc/rustc.rs
@@ -9,6 +9,15 @@
 // except according to those terms.
 
 #![feature(rustc_private)]
+#![feature(link_args)]
+
+// Set the stack size at link time on Windows. See rustc_driver::in_rustc_thread
+// for the rationale.
+#[cfg_attr(all(windows, target_env = "msvc"), link_args = "/STACK:16777216")]
+// We only build for msvc and gnu now, but we use a exhaustive condition here
+// so we can expect either the stack size to be set or the build fails.
+#[cfg_attr(all(windows, not(target_env = "msvc")), link_args = "-Wl,--stack,16777216")]
+extern {}
 
 extern crate rustc_driver;
 

From a185b56b7caca17c7aa9d6f702fe1b2209c82e4e Mon Sep 17 00:00:00 2001
From: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
Date: Sun, 18 Mar 2018 23:02:06 +0900
Subject: [PATCH 09/37] Address review comments

---
 src/librustc_driver/lib.rs    |  8 +++++---
 src/libstd/rt.rs              | 15 +++++++++++++++
 src/libstd/sys/unix/thread.rs | 20 +++++++++++++++++++-
 src/libstd/thread/mod.rs      |  8 --------
 4 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 761797239412e..e39a2c2f5dcd9 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -1476,13 +1476,15 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
         } else if rlim.rlim_max < STACK_SIZE as libc::rlim_t {
             true
         } else {
+            std::rt::deinit_stack_guard();
             rlim.rlim_cur = STACK_SIZE as libc::rlim_t;
             if libc::setrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
                 let err = io::Error::last_os_error();
-                error!("in_rustc_thread: error calling setrlimit: {}", err);
-                true
+                // We have already deinited the stack. Further corruption is
+                // not allowed.
+                panic!("in_rustc_thread: error calling setrlimit: {}", err);
             } else {
-                std::thread::update_stack_guard();
+                std::rt::update_stack_guard();
                 false
             }
         }
diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs
index e1392762a59dc..8f945470b7e94 100644
--- a/src/libstd/rt.rs
+++ b/src/libstd/rt.rs
@@ -73,3 +73,18 @@ fn lang_start<T: ::process::Termination + 'static>
 {
     lang_start_internal(&move || main().report(), argc, argv)
 }
+
+/// Function used for reverting changes to the main stack before setrlimit().
+/// This is POSIX (non-Linux) specific and unlikely to be directly stabilized.
+#[unstable(feature = "rustc_stack_internals", issue = "0")]
+pub unsafe fn deinit_stack_guard() {
+    ::sys::thread::guard::deinit();
+}
+
+/// Function used for resetting the main stack guard address after setrlimit().
+/// This is POSIX specific and unlikely to be directly stabilized.
+#[unstable(feature = "rustc_stack_internals", issue = "0")]
+pub unsafe fn update_stack_guard() {
+    let main_guard = ::sys::thread::guard::init();
+    ::sys_common::thread_info::reset_guard(main_guard);
+}
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index 72cdb9440b8e7..d94e11a5207cb 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -222,7 +222,7 @@ pub mod guard {
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
     use libc;
-    use libc::mmap;
+    use libc::{mmap, munmap};
     use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
     use ops::Range;
     use sys::os;
@@ -336,6 +336,24 @@ pub mod guard {
         }
     }
 
+    pub unsafe fn deinit() {
+        if !cfg!(target_os = "linux") {
+            if let Some(mut stackaddr) = get_stack_start() {
+                // Ensure address is aligned. Same as above.
+                let remainder = (stackaddr as usize) % PAGE_SIZE;
+                if remainder != 0 {
+                    stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder)
+                        as *mut libc::c_void;
+                }
+
+                // Undo the guard page mapping.
+                if munmap(stackaddr, PAGE_SIZE) != 0 {
+                    panic!("unable to deallocate the guard page");
+                }
+            }
+        }
+    }
+
     #[cfg(any(target_os = "macos",
               target_os = "bitrig",
               target_os = "openbsd",
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index b686ddc205ea7..71aee673cfe3e 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -208,14 +208,6 @@ pub use self::local::{LocalKey, AccessError};
 #[unstable(feature = "libstd_thread_internals", issue = "0")]
 #[doc(hidden)] pub use self::local::os::Key as __OsLocalKeyInner;
 
-/// Function used for resetting the main stack guard address after setrlimit().
-/// This is POSIX specific and unlikely to be directly stabilized.
-#[unstable(feature = "rustc_stack_internals", issue = "0")]
-pub unsafe fn update_stack_guard() {
-    let main_guard = imp::guard::init();
-    thread_info::reset_guard(main_guard);
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Builder
 ////////////////////////////////////////////////////////////////////////////////

From c5c650d670f5f191ea9667b455c15a607e550fdb Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Mon, 19 Mar 2018 00:26:41 -0500
Subject: [PATCH 10/37] Split out termination_trait_test feature gate

---
 src/libsyntax/feature_gate.rs                 |  3 +++
 src/libsyntax/test.rs                         |  8 +++----
 .../feature-gate-termination_trait_test.rs    | 22 +++++++++++++++++++
 .../termination-trait-in-test.rs              |  2 +-
 4 files changed, 30 insertions(+), 5 deletions(-)
 create mode 100644 src/test/compile-fail/feature-gate-termination_trait_test.rs

diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index fa600cd686064..0950965233f6a 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -432,6 +432,9 @@ declare_features! (
     // Termination trait in main (RFC 1937)
     (active, termination_trait, "1.24.0", Some(43301), None),
 
+    // Termination trait in tests (RFC 1937)
+    (active, termination_trait_test, "1.24.0", Some(48854), None),
+
     // Allows use of the :lifetime macro fragment specifier
     (active, macro_lifetime_matcher, "1.24.0", Some(46895), None),
 
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 9edfa767d3195..d107ab59a9ad9 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -332,7 +332,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
             ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
                 // If the termination trait is active, the compiler will check that the output
                 // type implements the `Termination` trait as `libtest` enforces that.
-                let output_matches = if cx.features.termination_trait {
+                let output_matches = if cx.features.termination_trait_test {
                     true
                 } else {
                     let no_output = match decl.output {
@@ -359,7 +359,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
         match has_test_signature(cx, i) {
             Yes => true,
             No => {
-                if cx.features.termination_trait {
+                if cx.features.termination_trait_test {
                     diag.span_err(i.span, "functions used as tests can not have any arguments");
                 } else {
                     diag.span_err(i.span, "functions used as tests must have signature fn() -> ()");
@@ -388,7 +388,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
 
                 // If the termination trait is active, the compiler will check that the output
                 // type implements the `Termination` trait as `libtest` enforces that.
-                let output_matches = if cx.features.termination_trait {
+                let output_matches = if cx.features.termination_trait_test {
                     true
                 } else {
                     let no_output = match decl.output {
@@ -416,7 +416,7 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     if has_bench_attr && !has_bench_signature {
         let diag = cx.span_diagnostic;
 
-        if cx.features.termination_trait {
+        if cx.features.termination_trait_test {
             diag.span_err(i.span, "functions used as benches must have signature \
                                    `fn(&mut Bencher) -> impl Termination`");
         } else {
diff --git a/src/test/compile-fail/feature-gate-termination_trait_test.rs b/src/test/compile-fail/feature-gate-termination_trait_test.rs
new file mode 100644
index 0000000000000..4af7e94671627
--- /dev/null
+++ b/src/test/compile-fail/feature-gate-termination_trait_test.rs
@@ -0,0 +1,22 @@
+// Copyright 2017 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.
+
+// compile-flags: --test
+
+fn main() {}
+
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn it_works() -> Result<(), ()> {
+    //~^ ERROR functions used as tests must have signature fn() -> ()
+        Ok(())
+    }
+}
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs
index 494500d522abe..11997eb691728 100644
--- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs
+++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-in-test.rs
@@ -10,7 +10,7 @@
 
 // compile-flags: --test
 
-#![feature(termination_trait)]
+#![feature(termination_trait_test)]
 #![feature(test)]
 
 extern crate test;

From 685c3c1b4a7c1949048177409ca43fc05daefd3f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sun, 18 Mar 2018 23:01:11 -0700
Subject: [PATCH 11/37] Reduce the diagnostic span when multiple fields are
 missing in pattern

---
 src/librustc_typeck/check/_match.rs           | 70 +++++++++++--------
 .../ui/missing-fields-in-struct-pattern.rs    | 17 +++++
 2 files changed, 59 insertions(+), 28 deletions(-)
 create mode 100644 src/test/ui/missing-fields-in-struct-pattern.rs

diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 379fd93ba2bd6..0b5383f1f8d1e 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -904,6 +904,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
         // Keep track of which fields have already appeared in the pattern.
         let mut used_fields = FxHashMap();
 
+        let mut inexistent_fields = vec![];
         // Typecheck each field.
         for &Spanned { node: ref field, span } in fields {
             let field_ty = match used_fields.entry(field.name) {
@@ -927,34 +928,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                             self.field_ty(span, f, substs)
                         })
                         .unwrap_or_else(|| {
-                            let mut err = struct_span_err!(
-                                tcx.sess,
-                                span,
-                                E0026,
-                                "{} `{}` does not have a field named `{}`",
-                                kind_name,
-                                tcx.item_path_str(variant.did),
-                                field.name
-                            );
-                            err.span_label(span,
-                                           format!("{} `{}` does not have field `{}`",
-                                                   kind_name,
-                                                   tcx.item_path_str(variant.did),
-                                                   field.name));
-                            if tcx.sess.teach(&err.get_code().unwrap()) {
-                                err.note(
-                                    "This error indicates that a struct pattern attempted to \
-                                     extract a non-existent field from a struct. Struct fields \
-                                     are identified by the name used before the colon : so struct \
-                                     patterns should resemble the declaration of the struct type \
-                                     being matched.\n\n\
-                                     If you are using shorthand field patterns but want to refer \
-                                     to the struct field by a different name, you should rename \
-                                     it explicitly."
-                                );
-                            }
-                            err.emit();
-
+                            inexistent_fields.push((span, field.name));
                             tcx.types.err
                         })
                 }
@@ -963,6 +937,46 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
             self.check_pat_walk(&field.pat, field_ty, def_bm, true);
         }
 
+        if inexistent_fields.len() > 0 {
+            let field_names = if inexistent_fields.len() == 1 {
+                format!("a field named `{}`", inexistent_fields[0].1)
+            } else {
+                format!("fields named {}",
+                        inexistent_fields.iter()
+                            .map(|(_, name)| format!("`{}`", name))
+                            .collect::<Vec<String>>()
+                            .join(", "))
+            };
+            let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
+            let mut err = struct_span_err!(tcx.sess,
+                                           spans,
+                                           E0026,
+                                           "{} `{}` does not have {}",
+                                           kind_name,
+                                           tcx.item_path_str(variant.did),
+                                           field_names);
+            for (span, name) in &inexistent_fields {
+                err.span_label(*span,
+                               format!("{} `{}` does not have field `{}`",
+                                       kind_name,
+                                       tcx.item_path_str(variant.did),
+                                       name));
+            }
+            if tcx.sess.teach(&err.get_code().unwrap()) {
+                err.note(
+                    "This error indicates that a struct pattern attempted to \
+                     extract a non-existent field from a struct. Struct fields \
+                     are identified by the name used before the colon : so struct \
+                     patterns should resemble the declaration of the struct type \
+                     being matched.\n\n\
+                     If you are using shorthand field patterns but want to refer \
+                     to the struct field by a different name, you should rename \
+                     it explicitly."
+                );
+            }
+            err.emit();
+        }
+
         // Require `..` if struct has non_exhaustive attribute.
         if adt.is_struct() && adt.is_non_exhaustive() && !adt.did.is_local() && !etc {
             span_err!(tcx.sess, span, E0638,
diff --git a/src/test/ui/missing-fields-in-struct-pattern.rs b/src/test/ui/missing-fields-in-struct-pattern.rs
new file mode 100644
index 0000000000000..2469f24534543
--- /dev/null
+++ b/src/test/ui/missing-fields-in-struct-pattern.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 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.
+
+struct S(usize, usize, usize, usize);
+
+fn main() {
+    if let S { a, b, c, d } = S(1, 2, 3, 4) {
+        println!("hi");
+    }
+}

From 97b3bf99f667736c3220a91b72a587eafe4cda49 Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Mon, 19 Mar 2018 01:31:04 -0500
Subject: [PATCH 12/37] Stabilize termination_trait

This stabilizes `main` with non-() return types; see #48453.
---
 src/librustc_typeck/check/mod.rs              | 35 +++++++++----------
 src/librustc_typeck/lib.rs                    |  3 +-
 src/libstd/lib.rs                             |  2 +-
 src/libsyntax/feature_gate.rs                 |  5 ++-
 .../termination-trait-main-i32.rs}            |  3 +-
 .../termination-trait-main-wrong-type.rs      |  1 -
 .../termination-trait-not-satisfied.rs        |  2 --
 .../termination-trait-for-never.rs            |  2 --
 ...mination-trait-for-result-box-error_err.rs |  2 --
 .../termination-trait-for-empty.rs            |  2 --
 .../termination-trait-for-exitcode.rs         |  1 -
 ...rmination-trait-for-result-box-error_ok.rs |  2 --
 .../termination-trait-for-result.rs           |  2 --
 13 files changed, 22 insertions(+), 40 deletions(-)
 rename src/test/compile-fail/{feature-gate-termination_trait.rs => rfc-1937-termination-trait/termination-trait-main-i32.rs} (82%)

diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4a685cfddb7a4..42bf516a0afa5 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1106,25 +1106,22 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     }
     fcx.demand_suptype(span, ret_ty, actual_return_ty);
 
-    if fcx.tcx.features().termination_trait {
-        // If the termination trait language item is activated, check that the main return type
-        // implements the termination trait.
-        if let Some(term_id) = fcx.tcx.lang_items().termination() {
-            if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
-                if id == fn_id {
-                    match fcx.sess().entry_type.get() {
-                        Some(config::EntryMain) => {
-                            let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
-                            let trait_ref = ty::TraitRef::new(term_id, substs);
-                            let cause = traits::ObligationCause::new(
-                                span, fn_id, ObligationCauseCode::MainFunctionType);
-
-                            inherited.register_predicate(
-                                traits::Obligation::new(
-                                    cause, param_env, trait_ref.to_predicate()));
-                        },
-                        _ => {},
-                    }
+    // Check that the main return type implements the termination trait.
+    if let Some(term_id) = fcx.tcx.lang_items().termination() {
+        if let Some((id, _)) = *fcx.tcx.sess.entry_fn.borrow() {
+            if id == fn_id {
+                match fcx.sess().entry_type.get() {
+                    Some(config::EntryMain) => {
+                        let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
+                        let trait_ref = ty::TraitRef::new(term_id, substs);
+                        let cause = traits::ObligationCause::new(
+                            span, fn_id, ObligationCauseCode::MainFunctionType);
+
+                        inherited.register_predicate(
+                            traits::Obligation::new(
+                                cause, param_env, trait_ref.to_predicate()));
+                    },
+                    _ => {},
                 }
             }
         }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 964c0021133aa..8089014044211 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -208,8 +208,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
 
             let actual = tcx.fn_sig(main_def_id);
-            let expected_return_type = if tcx.lang_items().termination().is_some()
-                && tcx.features().termination_trait {
+            let expected_return_type = if tcx.lang_items().termination().is_some() {
                 // we take the return type of the given main function, the real check is done
                 // in `check_fn`
                 actual.output().skip_binder()
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 70a1f82c9a159..33da0e5788653 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -308,7 +308,6 @@
 #![feature(str_char)]
 #![feature(str_internals)]
 #![feature(str_utf16)]
-#![feature(termination_trait)]
 #![feature(test, rustc_private)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
@@ -325,6 +324,7 @@
 #![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(windows, feature(used))]
 #![cfg_attr(stage0, feature(never_type))]
+#![cfg_attr(stage0, feature(termination_trait))]
 
 #![default_lib_allocator]
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 0950965233f6a..781071b7f7f07 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -429,9 +429,6 @@ declare_features! (
     // `foo.rs` as an alternative to `foo/mod.rs`
     (active, non_modrs_mods, "1.24.0", Some(44660), None),
 
-    // Termination trait in main (RFC 1937)
-    (active, termination_trait, "1.24.0", Some(43301), None),
-
     // Termination trait in tests (RFC 1937)
     (active, termination_trait_test, "1.24.0", Some(48854), None),
 
@@ -558,6 +555,8 @@ declare_features! (
     (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None),
     // allow `..=` in patterns (RFC 1192)
     (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None),
+    // Termination trait in main (RFC 1937)
+    (accepted, termination_trait, "1.26.0", Some(43301), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
diff --git a/src/test/compile-fail/feature-gate-termination_trait.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
similarity index 82%
rename from src/test/compile-fail/feature-gate-termination_trait.rs
rename to src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
index 5a56445b64e57..ff2b32f3fd93b 100644
--- a/src/test/compile-fail/feature-gate-termination_trait.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn main() -> i32 { //~ ERROR main function has wrong type [E0580]
+fn main() -> i32 {
+//~^ ERROR the trait bound `i32: std::process::Termination` is not satisfied [E0277]
     0
 }
diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
index 93e2561adf753..ea39ba92f4143 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
@@ -7,7 +7,6 @@
 // <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.
-#![feature(termination_trait)]
 
 fn main() -> char {
 //~^ ERROR: the trait bound `char: std::process::Termination` is not satisfied
diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
index e87e0ceebf1b1..bab02fc559706 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(termination_trait)]
-
 struct ReturnType {}
 
 fn main() -> ReturnType { //~ ERROR `ReturnType: std::process::Termination` is not satisfied
diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs
index c1dd44a91765e..863de85af88fb 100644
--- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs
+++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-never.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(termination_trait)]
-
 // error-pattern:oh, dear
 
 fn main() -> ! {
diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs
index 8ce27c0a06250..0c6cb4de9567d 100644
--- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs
+++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-result-box-error_err.rs
@@ -11,8 +11,6 @@
 // must-compile-successfully
 // failure-status: 1
 
-#![feature(termination_trait)]
-
 use std::io::{Error, ErrorKind};
 
 fn main() -> Result<(), Box<Error>> {
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs
index 5e534da012875..046d27a9f0fe5 100644
--- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs
+++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-empty.rs
@@ -8,6 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(termination_trait)]
-
 fn main() {}
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs
index 80fa4d17b6116..4aa7d8c3a77d2 100644
--- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs
+++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-exitcode.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(termination_trait)]
 #![feature(process_exitcode_placeholder)]
 
 use std::process::ExitCode;
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs
index 269ac451cf4d8..33686ed0b8fa2 100644
--- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs
+++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result-box-error_ok.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(termination_trait)]
-
 use std::io::Error;
 
 fn main() -> Result<(), Box<Error>> {
diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs
index 751db0fb50082..1c87e31e763e9 100644
--- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs
+++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-result.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(termination_trait)]
-
 use std::io::Error;
 
 fn main() -> Result<(), Error> {

From e5a55e74405dedf8bc0744300a8c506eea94bc18 Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Mon, 19 Mar 2018 01:59:51 -0500
Subject: [PATCH 13/37] Stabilize termination_trait in 1.25, not 1.26

---
 src/libsyntax/feature_gate.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 781071b7f7f07..e71726bcebdc9 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -551,12 +551,12 @@ declare_features! (
     (accepted, match_beginning_vert, "1.25.0", Some(44101), None),
     // Nested groups in `use` (RFC 2128)
     (accepted, use_nested_groups, "1.25.0", Some(44494), None),
+    // Termination trait in main (RFC 1937)
+    (accepted, termination_trait, "1.25.0", Some(43301), None),
     // a..=b and ..=b
     (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None),
     // allow `..=` in patterns (RFC 1192)
     (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None),
-    // Termination trait in main (RFC 1937)
-    (accepted, termination_trait, "1.26.0", Some(43301), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must

From 8236e431ce67f0cd32e0584a826586648842eaa3 Mon Sep 17 00:00:00 2001
From: Seo Sanghyeon <sanxiyn@gmail.com>
Date: Mon, 19 Mar 2018 22:09:47 +0900
Subject: [PATCH 14/37] Document only-X test header

---
 src/test/COMPILER_TESTS.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/test/COMPILER_TESTS.md b/src/test/COMPILER_TESTS.md
index c255294e790b7..8553665c01797 100644
--- a/src/test/COMPILER_TESTS.md
+++ b/src/test/COMPILER_TESTS.md
@@ -54,6 +54,8 @@ be compiled or run.
 * `ignore-test` always ignores the test
 * `ignore-lldb` and `ignore-gdb` will skip a debuginfo test on that debugger.
 
+`only-X` is the opposite. The test will run only when `X` matches.
+
 Some examples of `X` in `ignore-X`:
 
 * Architecture: `aarch64`, `arm`, `asmjs`, `mips`, `wasm32`, `x86_64`, `x86`, ...

From f332a9ce5676859f0f07c4d6bf2d2c415be67066 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Sun, 18 Mar 2018 23:26:57 -0700
Subject: [PATCH 15/37] Single diagnostic for all non-mentioned fields in a
 pattern

---
 src/librustc_typeck/check/_match.rs           | 22 ++++++++++++++-----
 .../ui/missing-fields-in-struct-pattern.rs    |  2 ++
 .../missing-fields-in-struct-pattern.stderr   | 22 +++++++++++++++++++
 3 files changed, 41 insertions(+), 5 deletions(-)
 create mode 100644 src/test/ui/missing-fields-in-struct-pattern.stderr

diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 0b5383f1f8d1e..cc72a565ba28e 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -993,13 +993,25 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                 tcx.sess.span_err(span, "`..` cannot be used in union patterns");
             }
         } else if !etc {
-            for field in variant.fields
+            let unmentioned_fields = variant.fields
                 .iter()
-                .filter(|field| !used_fields.contains_key(&field.name)) {
+                .map(|field| field.name)
+                .filter(|field| !used_fields.contains_key(&field))
+                .collect::<Vec<_>>();
+            if unmentioned_fields.len() > 0 {
+                let field_names = if unmentioned_fields.len() == 1 {
+                    format!("field `{}`", unmentioned_fields[0])
+                } else {
+                    format!("fields {}",
+                            unmentioned_fields.iter()
+                                .map(|name| format!("`{}`", name))
+                                .collect::<Vec<String>>()
+                                .join(", "))
+                };
                 let mut diag = struct_span_err!(tcx.sess, span, E0027,
-                                                "pattern does not mention field `{}`",
-                                                field.name);
-                diag.span_label(span, format!("missing field `{}`", field.name));
+                                                "pattern does not mention {}",
+                                                field_names);
+                diag.span_label(span, format!("missing {}", field_names));
                 if variant.ctor_kind == CtorKind::Fn {
                     diag.note("trying to match a tuple variant with a struct variant pattern");
                 }
diff --git a/src/test/ui/missing-fields-in-struct-pattern.rs b/src/test/ui/missing-fields-in-struct-pattern.rs
index 2469f24534543..28ed151b98606 100644
--- a/src/test/ui/missing-fields-in-struct-pattern.rs
+++ b/src/test/ui/missing-fields-in-struct-pattern.rs
@@ -12,6 +12,8 @@ struct S(usize, usize, usize, usize);
 
 fn main() {
     if let S { a, b, c, d } = S(1, 2, 3, 4) {
+    //~^ ERROR struct `S` does not have fields named `a`, `b`, `c`, `d` [E0026]
+    //~^ ERROR pattern does not mention fields `0`, `1`, `2`, `3` [E0027]
         println!("hi");
     }
 }
diff --git a/src/test/ui/missing-fields-in-struct-pattern.stderr b/src/test/ui/missing-fields-in-struct-pattern.stderr
new file mode 100644
index 0000000000000..88fba19d14e35
--- /dev/null
+++ b/src/test/ui/missing-fields-in-struct-pattern.stderr
@@ -0,0 +1,22 @@
+error[E0026]: struct `S` does not have fields named `a`, `b`, `c`, `d`
+  --> $DIR/missing-fields-in-struct-pattern.rs:14:16
+   |
+LL |     if let S { a, b, c, d } = S(1, 2, 3, 4) {
+   |                ^  ^  ^  ^ struct `S` does not have field `d`
+   |                |  |  |
+   |                |  |  struct `S` does not have field `c`
+   |                |  struct `S` does not have field `b`
+   |                struct `S` does not have field `a`
+
+error[E0027]: pattern does not mention fields `0`, `1`, `2`, `3`
+  --> $DIR/missing-fields-in-struct-pattern.rs:14:12
+   |
+LL |     if let S { a, b, c, d } = S(1, 2, 3, 4) {
+   |            ^^^^^^^^^^^^^^^^ missing fields `0`, `1`, `2`, `3`
+   |
+   = note: trying to match a tuple variant with a struct variant pattern
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0026, E0027.
+For more information about an error, try `rustc --explain E0026`.

From 062a46fdd1d49b1ccdc4f713433521463224d7d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Mon, 19 Mar 2018 14:13:57 -0700
Subject: [PATCH 16/37] Reduce diagnostic verbosity by removing labels

---
 src/librustc_typeck/check/_match.rs             | 17 +++++++++--------
 .../compile-fail/struct-pat-derived-error.rs    |  6 ++----
 src/test/ui/error-codes/E0026-teach.stderr      |  2 +-
 src/test/ui/error-codes/E0026.stderr            |  2 +-
 src/test/ui/missing-fields-in-struct-pattern.rs |  2 +-
 .../ui/missing-fields-in-struct-pattern.stderr  |  6 +-----
 src/test/ui/numeric-fields.stderr               |  2 +-
 src/test/ui/type-check/issue-41314.stderr       |  2 +-
 src/test/ui/union/union-fields-2.stderr         |  2 +-
 9 files changed, 18 insertions(+), 23 deletions(-)

diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index cc72a565ba28e..7965806af5d09 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -938,14 +938,14 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
         }
 
         if inexistent_fields.len() > 0 {
-            let field_names = if inexistent_fields.len() == 1 {
-                format!("a field named `{}`", inexistent_fields[0].1)
+            let (field_names, t, plural) = if inexistent_fields.len() == 1 {
+                (format!("a field named `{}`", inexistent_fields[0].1), "this", "")
             } else {
-                format!("fields named {}",
-                        inexistent_fields.iter()
+                (format!("fields named {}",
+                         inexistent_fields.iter()
                             .map(|(_, name)| format!("`{}`", name))
                             .collect::<Vec<String>>()
-                            .join(", "))
+                            .join(", ")), "these", "s")
             };
             let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::<Vec<_>>();
             let mut err = struct_span_err!(tcx.sess,
@@ -955,12 +955,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                                            kind_name,
                                            tcx.item_path_str(variant.did),
                                            field_names);
-            for (span, name) in &inexistent_fields {
+            if let Some((span, _)) = inexistent_fields.last() {
                 err.span_label(*span,
-                               format!("{} `{}` does not have field `{}`",
+                               format!("{} `{}` does not have {} field{}",
                                        kind_name,
                                        tcx.item_path_str(variant.did),
-                                       name));
+                                       t,
+                                       plural));
             }
             if tcx.sess.teach(&err.get_code().unwrap()) {
                 err.note(
diff --git a/src/test/compile-fail/struct-pat-derived-error.rs b/src/test/compile-fail/struct-pat-derived-error.rs
index f525ec373753d..d3130c4e831f6 100644
--- a/src/test/compile-fail/struct-pat-derived-error.rs
+++ b/src/test/compile-fail/struct-pat-derived-error.rs
@@ -16,10 +16,8 @@ struct a {
 impl a {
     fn foo(&self) {
         let a { x, y } = self.d; //~ ERROR no field `d` on type `&a`
-        //~^ ERROR struct `a` does not have a field named `x`
-        //~^^ ERROR struct `a` does not have a field named `y`
-        //~^^^ ERROR pattern does not mention field `b`
-        //~^^^^ ERROR pattern does not mention field `c`
+        //~^ ERROR struct `a` does not have fields named `x`, `y`
+        //~| ERROR pattern does not mention fields `b`, `c`
     }
 }
 
diff --git a/src/test/ui/error-codes/E0026-teach.stderr b/src/test/ui/error-codes/E0026-teach.stderr
index 63d072fe03d0a..67ea32fba86d6 100644
--- a/src/test/ui/error-codes/E0026-teach.stderr
+++ b/src/test/ui/error-codes/E0026-teach.stderr
@@ -2,7 +2,7 @@ error[E0026]: struct `Thing` does not have a field named `z`
   --> $DIR/E0026-teach.rs:21:23
    |
 LL |         Thing { x, y, z } => {}
-   |                       ^ struct `Thing` does not have field `z`
+   |                       ^ struct `Thing` does not have this field
    |
    = note: This error indicates that a struct pattern attempted to extract a non-existent field from a struct. Struct fields are identified by the name used before the colon : so struct patterns should resemble the declaration of the struct type being matched.
            
diff --git a/src/test/ui/error-codes/E0026.stderr b/src/test/ui/error-codes/E0026.stderr
index af8519511276c..9dabbc8a775fb 100644
--- a/src/test/ui/error-codes/E0026.stderr
+++ b/src/test/ui/error-codes/E0026.stderr
@@ -2,7 +2,7 @@ error[E0026]: struct `Thing` does not have a field named `z`
   --> $DIR/E0026.rs:19:23
    |
 LL |         Thing { x, y, z } => {}
-   |                       ^ struct `Thing` does not have field `z`
+   |                       ^ struct `Thing` does not have this field
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/missing-fields-in-struct-pattern.rs b/src/test/ui/missing-fields-in-struct-pattern.rs
index 28ed151b98606..dfde37994998b 100644
--- a/src/test/ui/missing-fields-in-struct-pattern.rs
+++ b/src/test/ui/missing-fields-in-struct-pattern.rs
@@ -13,7 +13,7 @@ struct S(usize, usize, usize, usize);
 fn main() {
     if let S { a, b, c, d } = S(1, 2, 3, 4) {
     //~^ ERROR struct `S` does not have fields named `a`, `b`, `c`, `d` [E0026]
-    //~^ ERROR pattern does not mention fields `0`, `1`, `2`, `3` [E0027]
+    //~| ERROR pattern does not mention fields `0`, `1`, `2`, `3` [E0027]
         println!("hi");
     }
 }
diff --git a/src/test/ui/missing-fields-in-struct-pattern.stderr b/src/test/ui/missing-fields-in-struct-pattern.stderr
index 88fba19d14e35..d1c3260f11e30 100644
--- a/src/test/ui/missing-fields-in-struct-pattern.stderr
+++ b/src/test/ui/missing-fields-in-struct-pattern.stderr
@@ -2,11 +2,7 @@ error[E0026]: struct `S` does not have fields named `a`, `b`, `c`, `d`
   --> $DIR/missing-fields-in-struct-pattern.rs:14:16
    |
 LL |     if let S { a, b, c, d } = S(1, 2, 3, 4) {
-   |                ^  ^  ^  ^ struct `S` does not have field `d`
-   |                |  |  |
-   |                |  |  struct `S` does not have field `c`
-   |                |  struct `S` does not have field `b`
-   |                struct `S` does not have field `a`
+   |                ^  ^  ^  ^ struct `S` does not have these fields
 
 error[E0027]: pattern does not mention fields `0`, `1`, `2`, `3`
   --> $DIR/missing-fields-in-struct-pattern.rs:14:12
diff --git a/src/test/ui/numeric-fields.stderr b/src/test/ui/numeric-fields.stderr
index 607980ba3bf54..68a87da8ded32 100644
--- a/src/test/ui/numeric-fields.stderr
+++ b/src/test/ui/numeric-fields.stderr
@@ -10,7 +10,7 @@ error[E0026]: struct `S` does not have a field named `0x1`
   --> $DIR/numeric-fields.rs:17:17
    |
 LL |         S{0: a, 0x1: b, ..} => {}
-   |                 ^^^^^^ struct `S` does not have field `0x1`
+   |                 ^^^^^^ struct `S` does not have this field
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/type-check/issue-41314.stderr b/src/test/ui/type-check/issue-41314.stderr
index bcb0f9a99a779..f7d4bb9a02f45 100644
--- a/src/test/ui/type-check/issue-41314.stderr
+++ b/src/test/ui/type-check/issue-41314.stderr
@@ -2,7 +2,7 @@ error[E0026]: variant `X::Y` does not have a field named `number`
   --> $DIR/issue-41314.rs:17:16
    |
 LL |         X::Y { number } => {} //~ ERROR does not have a field named `number`
-   |                ^^^^^^ variant `X::Y` does not have field `number`
+   |                ^^^^^^ variant `X::Y` does not have this field
 
 error[E0027]: pattern does not mention field `0`
   --> $DIR/issue-41314.rs:17:9
diff --git a/src/test/ui/union/union-fields-2.stderr b/src/test/ui/union/union-fields-2.stderr
index 3ea4d3426dad7..cfb5bc7520b59 100644
--- a/src/test/ui/union/union-fields-2.stderr
+++ b/src/test/ui/union/union-fields-2.stderr
@@ -52,7 +52,7 @@ error[E0026]: union `U` does not have a field named `c`
   --> $DIR/union-fields-2.rs:28:19
    |
 LL |     let U { a, b, c } = u; //~ ERROR union patterns should have exactly one field
-   |                   ^ union `U` does not have field `c`
+   |                   ^ union `U` does not have this field
 
 error: union patterns should have exactly one field
   --> $DIR/union-fields-2.rs:28:9

From be29e52c5a3d9da894a0292f9175106a955071c9 Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Tue, 20 Mar 2018 00:02:17 -0500
Subject: [PATCH 17/37] Match against friendly error message

---
 .../rfc-1937-termination-trait/termination-trait-main-i32.rs    | 2 +-
 .../termination-trait-main-wrong-type.rs                        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
index ff2b32f3fd93b..67ee39d10d91c 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// error-pattern:`main` can only return types that implement std::process::Termination, not `i32`
 fn main() -> i32 {
-//~^ ERROR the trait bound `i32: std::process::Termination` is not satisfied [E0277]
     0
 }
diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
index ea39ba92f4143..5f4ccf2b5862e 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// error-pattern:`main` can only return types that implement std::process::Termination, not `char
 fn main() -> char {
-//~^ ERROR: the trait bound `char: std::process::Termination` is not satisfied
     ' '
 }

From 5ccf3ffab24a4237e467b884af6783b1af54bdd8 Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Tue, 20 Mar 2018 00:06:46 -0500
Subject: [PATCH 18/37] diagnostics: Remove main return type errors from E0580

---
 src/librustc/diagnostics.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs
index b3a904f2f5fec..7627071e56037 100644
--- a/src/librustc/diagnostics.rs
+++ b/src/librustc/diagnostics.rs
@@ -1764,12 +1764,12 @@ The `main` function was incorrectly declared.
 Erroneous code example:
 
 ```compile_fail,E0580
-fn main() -> i32 { // error: main function has wrong type
-    0
+fn main(x: i32) { // error: main function has wrong type
+    println!("{}", x);
 }
 ```
 
-The `main` function prototype should never take arguments or return type.
+The `main` function prototype should never take arguments.
 Example:
 
 ```

From 8c8a72f8224b9cbf283cd120d87397c032ed62f1 Mon Sep 17 00:00:00 2001
From: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
Date: Tue, 20 Mar 2018 21:15:21 +0900
Subject: [PATCH 19/37] Reinit the stack guard on unexpected failure

---
 src/librustc_driver/lib.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index e39a2c2f5dcd9..e56c9928dccd6 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -1480,9 +1480,9 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
             rlim.rlim_cur = STACK_SIZE as libc::rlim_t;
             if libc::setrlimit(libc::RLIMIT_STACK, &mut rlim) != 0 {
                 let err = io::Error::last_os_error();
-                // We have already deinited the stack. Further corruption is
-                // not allowed.
-                panic!("in_rustc_thread: error calling setrlimit: {}", err);
+                error!("in_rustc_thread: error calling setrlimit: {}", err);
+                std::rt::update_stack_guard();
+                true
             } else {
                 std::rt::update_stack_guard();
                 false

From 2928c7a8a253b655132ac9f2beb4ca74540f0e14 Mon Sep 17 00:00:00 2001
From: Tatsuyuki Ishi <ishitatsuyuki@gmail.com>
Date: Tue, 20 Mar 2018 21:22:45 +0900
Subject: [PATCH 20/37] Refactor the stack addr aligning code into a function

---
 src/libstd/sys/unix/thread.rs | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index d94e11a5207cb..4364089a18184 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -284,10 +284,10 @@ pub mod guard {
         ret
     }
 
-    pub unsafe fn init() -> Option<Guard> {
-        PAGE_SIZE = os::page_size();
-
-        let mut stackaddr = get_stack_start()?;
+    // Precondition: PAGE_SIZE is initialized.
+    unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
+        assert!(PAGE_SIZE != 0);
+        let stackaddr = get_stack_start()?;
 
         // Ensure stackaddr is page aligned! A parent process might
         // have reset RLIMIT_STACK to be non-page aligned. The
@@ -296,10 +296,17 @@ pub mod guard {
         // page-aligned, calculate the fix such that stackaddr <
         // new_page_aligned_stackaddr < stackaddr + stacksize
         let remainder = (stackaddr as usize) % PAGE_SIZE;
-        if remainder != 0 {
-            stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder)
-                as *mut libc::c_void;
-        }
+        Some(if remainder == 0 {
+            stackaddr
+        } else {
+            ((stackaddr as usize) + PAGE_SIZE - remainder) as *mut libc::c_void
+        })
+    }
+
+    pub unsafe fn init() -> Option<Guard> {
+        PAGE_SIZE = os::page_size();
+
+        let stackaddr = get_stack_start_aligned()?;
 
         if cfg!(target_os = "linux") {
             // Linux doesn't allocate the whole stack right away, and
@@ -338,14 +345,7 @@ pub mod guard {
 
     pub unsafe fn deinit() {
         if !cfg!(target_os = "linux") {
-            if let Some(mut stackaddr) = get_stack_start() {
-                // Ensure address is aligned. Same as above.
-                let remainder = (stackaddr as usize) % PAGE_SIZE;
-                if remainder != 0 {
-                    stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder)
-                        as *mut libc::c_void;
-                }
-
+            if let Some(stackaddr) = get_stack_start_aligned() {
                 // Undo the guard page mapping.
                 if munmap(stackaddr, PAGE_SIZE) != 0 {
                     panic!("unable to deallocate the guard page");

From df76629da77b58cd9a63d41b7bc1cc987dcc2bb8 Mon Sep 17 00:00:00 2001
From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 20 Mar 2018 17:14:33 +0100
Subject: [PATCH 21/37] Remove outdated comment

---
 src/librustc/ty/sty.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index bb5c7b5fd2a5e..3fe310c54bfe1 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1667,7 +1667,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
 pub struct Const<'tcx> {
     pub ty: Ty<'tcx>,
 
-    // FIXME(eddyb) Replace this with a miri value.
     pub val: ConstVal<'tcx>,
 }
 

From 3c8d55549728ec117fb6e3de93ce3d96fb6622d4 Mon Sep 17 00:00:00 2001
From: Kurtis Nusbaum <kcommiter@gmail.com>
Date: Wed, 14 Mar 2018 20:30:06 -0700
Subject: [PATCH 22/37] rename epoch to edition

---
 src/librustc/lint/context.rs                  | 12 ++---
 src/librustc/lint/mod.rs                      | 20 ++++-----
 src/librustc/session/config.rs                | 24 +++++-----
 src/librustc/session/mod.rs                   | 10 ++---
 src/librustc_driver/driver.rs                 |  2 +-
 src/librustc_lint/lib.rs                      | 34 +++++++-------
 src/librustc_typeck/check/method/probe.rs     |  2 +-
 src/libsyntax/config.rs                       |  6 +--
 src/libsyntax/{epoch.rs => edition.rs}        | 44 +++++++++----------
 src/libsyntax/feature_gate.rs                 | 20 ++++-----
 src/libsyntax/lib.rs                          |  2 +-
 ....rs => edition-raw-pointer-method-2015.rs} |  4 +-
 ....rs => edition-raw-pointer-method-2018.rs} |  4 +-
 src/test/run-pass/dyn-trait.rs                |  2 +-
 src/test/run-pass/epoch-gate-feature.rs       |  2 +-
 ...ference-variable-behind-raw-pointer.stderr |  2 +-
 16 files changed, 95 insertions(+), 95 deletions(-)
 rename src/libsyntax/{epoch.rs => edition.rs} (56%)
 rename src/test/compile-fail/{epoch-raw-pointer-method-2015.rs => edition-raw-pointer-method-2015.rs} (85%)
 rename src/test/compile-fail/{epoch-raw-pointer-method-2018.rs => edition-raw-pointer-method-2018.rs} (85%)

diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 4fa6594df169c..936aa71f16cea 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -41,7 +41,7 @@ use util::nodemap::FxHashMap;
 use std::default::Default as StdDefault;
 use std::cell::{Ref, RefCell};
 use syntax::ast;
-use syntax::epoch;
+use syntax::edition;
 use syntax_pos::{MultiSpan, Span};
 use errors::DiagnosticBuilder;
 use hir;
@@ -103,9 +103,9 @@ pub struct FutureIncompatibleInfo {
     pub id: LintId,
     /// e.g., a URL for an issue/PR/RFC or error code
     pub reference: &'static str,
-    /// If this is an epoch fixing lint, the epoch in which
+    /// If this is an edition fixing lint, the edition in which
     /// this lint becomes obsolete
-    pub epoch: Option<epoch::Epoch>,
+    pub edition: Option<edition::Edition>,
 }
 
 /// The target of the `by_name` map, which accounts for renaming/deprecation.
@@ -201,11 +201,11 @@ impl LintStore {
                                         sess: Option<&Session>,
                                         lints: Vec<FutureIncompatibleInfo>) {
 
-        for epoch in epoch::ALL_EPOCHS {
-            let lints = lints.iter().filter(|f| f.epoch == Some(*epoch)).map(|f| f.id)
+        for edition in edition::ALL_EPOCHS {
+            let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id)
                              .collect::<Vec<_>>();
             if !lints.is_empty() {
-                self.register_group(sess, false, epoch.lint_name(), lints)
+                self.register_group(sess, false, edition.lint_name(), lints)
             }
         }
 
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 7c103dc272109..cd038d067a1fd 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -42,7 +42,7 @@ use session::{Session, DiagnosticMessageId};
 use std::hash;
 use syntax::ast;
 use syntax::codemap::MultiSpan;
-use syntax::epoch::Epoch;
+use syntax::edition::Edition;
 use syntax::symbol::Symbol;
 use syntax::visit as ast_visit;
 use syntax_pos::Span;
@@ -77,8 +77,8 @@ pub struct Lint {
     /// e.g. "imports that are never used"
     pub desc: &'static str,
 
-    /// Deny lint after this epoch
-    pub epoch_deny: Option<Epoch>,
+    /// Deny lint after this edition
+    pub edition_deny: Option<Edition>,
 }
 
 impl Lint {
@@ -88,8 +88,8 @@ impl Lint {
     }
 
     pub fn default_level(&self, session: &Session) -> Level {
-        if let Some(epoch_deny) = self.epoch_deny {
-            if session.epoch() >= epoch_deny {
+        if let Some(edition_deny) = self.edition_deny {
+            if session.edition() >= edition_deny {
                 return Level::Deny
             }
         }
@@ -100,12 +100,12 @@ impl Lint {
 /// Declare a static item of type `&'static Lint`.
 #[macro_export]
 macro_rules! declare_lint {
-    ($vis: vis $NAME: ident, $Level: ident, $desc: expr, $epoch: expr) => (
+    ($vis: vis $NAME: ident, $Level: ident, $desc: expr, $edition: expr) => (
         $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
             name: stringify!($NAME),
             default_level: $crate::lint::$Level,
             desc: $desc,
-            epoch_deny: Some($epoch)
+            edition_deny: Some($edition)
         };
     );
     ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
@@ -113,7 +113,7 @@ macro_rules! declare_lint {
             name: stringify!($NAME),
             default_level: $crate::lint::$Level,
             desc: $desc,
-            epoch_deny: None,
+            edition_deny: None,
         };
     );
 }
@@ -499,8 +499,8 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
     // Check for future incompatibility lints and issue a stronger warning.
     let lints = sess.lint_store.borrow();
     if let Some(future_incompatible) = lints.future_incompatible(LintId::of(lint)) {
-        let future = if let Some(epoch) = future_incompatible.epoch {
-            format!("the {} epoch", epoch)
+        let future = if let Some(edition) = future_incompatible.edition {
+            format!("the {} edition", edition)
         } else {
             "a future release".to_owned()
         };
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 0d91074e946bd..4ba634f8b25cd 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -28,7 +28,7 @@ use middle::cstore;
 
 use syntax::ast::{self, IntTy, UintTy};
 use syntax::codemap::{FileName, FilePathMapping};
-use syntax::epoch::Epoch;
+use syntax::edition::Edition;
 use syntax::parse::token;
 use syntax::parse;
 use syntax::symbol::Symbol;
@@ -771,7 +771,7 @@ macro_rules! options {
             Some("`string` or `string=string`");
         pub const parse_lto: Option<&'static str> =
             Some("one of `thin`, `fat`, or omitted");
-        pub const parse_epoch: Option<&'static str> =
+        pub const parse_edition: Option<&'static str> =
             Some("one of: `2015`, `2018`");
     }
 
@@ -780,7 +780,7 @@ macro_rules! options {
         use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
         use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
         use std::path::PathBuf;
-        use syntax::epoch::Epoch;
+        use syntax::edition::Edition;
 
         $(
             pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@@ -983,11 +983,11 @@ macro_rules! options {
             true
         }
 
-        fn parse_epoch(slot: &mut Epoch, v: Option<&str>) -> bool {
+        fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
             match v {
                 Some(s) => {
-                    let epoch = s.parse();
-                    if let Ok(parsed) = epoch {
+                    let edition = s.parse();
+                    if let Ok(parsed) = edition {
                         *slot = parsed;
                         true
                     } else {
@@ -1280,10 +1280,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         `everybody_loops` (all function bodies replaced with `loop {}`),
         `hir` (the HIR), `hir,identified`, or
         `hir,typed` (HIR with types for each node)."),
-    epoch: Epoch = (Epoch::Epoch2015, parse_epoch, [TRACKED],
-        "The epoch to build Rust with. Newer epochs may include features
-         that require breaking changes. The default epoch is 2015 (the first
-         epoch). Crates compiled with different epochs can be linked together."),
+    edition: Edition = (Edition::Edition2015, parse_edition, [TRACKED],
+        "The edition to build Rust with. Newer editions may include features
+         that require breaking changes. The default edition is 2015 (the first
+         edition). Crates compiled with different editions can be linked together."),
     run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
           "run `dsymutil` and delete intermediate object files"),
     ui_testing: bool = (false, parse_bool, [UNTRACKED],
@@ -2258,7 +2258,7 @@ mod dep_tracking {
     use std::hash::Hash;
     use std::path::PathBuf;
     use std::collections::hash_map::DefaultHasher;
-    use super::{CrateType, DebugInfoLevel, Epoch, ErrorOutputType, Lto, OptLevel, OutputTypes,
+    use super::{CrateType, DebugInfoLevel, Edition, ErrorOutputType, Lto, OptLevel, OutputTypes,
                 Passes, Sanitizer};
     use syntax::feature_gate::UnstableFeatures;
     use rustc_back::{PanicStrategy, RelroLevel};
@@ -2320,7 +2320,7 @@ mod dep_tracking {
     impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
     impl_dep_tracking_hash_via_hash!(Sanitizer);
     impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
-    impl_dep_tracking_hash_via_hash!(Epoch);
+    impl_dep_tracking_hash_via_hash!(Edition);
 
     impl_dep_tracking_hash_for_sortable_vec_of!(String);
     impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 3f52ecfc0999b..556255e06ed00 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -31,7 +31,7 @@ use rustc_data_structures::sync::{Lrc, Lock};
 use syntax::ast::NodeId;
 use errors::{self, DiagnosticBuilder, DiagnosticId};
 use errors::emitter::{Emitter, EmitterWriter};
-use syntax::epoch::Epoch;
+use syntax::edition::Edition;
 use syntax::json::JsonEmitter;
 use syntax::feature_gate;
 use syntax::symbol::Symbol;
@@ -976,13 +976,13 @@ impl Session {
         self.opts.debugging_opts.teach && !self.parse_sess.span_diagnostic.code_emitted(code)
     }
 
-    /// Are we allowed to use features from the Rust 2018 epoch?
+    /// Are we allowed to use features from the Rust 2018 edition?
     pub fn rust_2018(&self) -> bool {
-        self.opts.debugging_opts.epoch >= Epoch::Epoch2018
+        self.opts.debugging_opts.edition >= Edition::Edition2018
     }
 
-    pub fn epoch(&self) -> Epoch {
-        self.opts.debugging_opts.epoch
+    pub fn edition(&self) -> Edition {
+        self.opts.debugging_opts.edition
     }
 }
 
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index f2fe6542db171..a3115544f30b9 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -648,7 +648,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
 {
     let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess,
                                                          sess.opts.test,
-                                                         sess.opts.debugging_opts.epoch);
+                                                         sess.opts.debugging_opts.edition);
     // these need to be set "early" so that expansion sees `quote` if enabled.
     sess.init_features(features);
 
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index ce896bfb701ba..59d2d3e8fdc07 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -48,7 +48,7 @@ use rustc::session;
 use rustc::util;
 
 use session::Session;
-use syntax::epoch::Epoch;
+use syntax::edition::Edition;
 use lint::LintId;
 use lint::FutureIncompatibleInfo;
 
@@ -197,82 +197,82 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
         FutureIncompatibleInfo {
             id: LintId::of(PRIVATE_IN_PUBLIC),
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),
             reference: "issue #34537 <https://github.com/rust-lang/rust/issues/34537>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(PATTERNS_IN_FNS_WITHOUT_BODY),
             reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(SAFE_EXTERN_STATICS),
             reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(INVALID_TYPE_PARAM_DEFAULT),
             reference: "issue #36887 <https://github.com/rust-lang/rust/issues/36887>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(LEGACY_DIRECTORY_OWNERSHIP),
             reference: "issue #37872 <https://github.com/rust-lang/rust/issues/37872>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(LEGACY_IMPORTS),
             reference: "issue #38260 <https://github.com/rust-lang/rust/issues/38260>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(LEGACY_CONSTRUCTOR_VISIBILITY),
             reference: "issue #39207 <https://github.com/rust-lang/rust/issues/39207>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(MISSING_FRAGMENT_SPECIFIER),
             reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(ILLEGAL_FLOATING_POINT_LITERAL_PATTERN),
             reference: "issue #41620 <https://github.com/rust-lang/rust/issues/41620>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(ANONYMOUS_PARAMETERS),
             reference: "issue #41686 <https://github.com/rust-lang/rust/issues/41686>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES),
             reference: "issue #42238 <https://github.com/rust-lang/rust/issues/42238>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(LATE_BOUND_LIFETIME_ARGUMENTS),
             reference: "issue #42868 <https://github.com/rust-lang/rust/issues/42868>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(SAFE_PACKED_BORROWS),
             reference: "issue #46043 <https://github.com/rust-lang/rust/issues/46043>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(INCOHERENT_FUNDAMENTAL_IMPLS),
             reference: "issue #46205 <https://github.com/rust-lang/rust/issues/46205>",
-            epoch: None,
+            edition: None,
         },
         FutureIncompatibleInfo {
             id: LintId::of(TYVAR_BEHIND_RAW_POINTER),
             reference: "issue #46906 <https://github.com/rust-lang/rust/issues/46906>",
-            epoch: Some(Epoch::Epoch2018),
+            edition: Some(Edition::Edition2018),
         }
         ]);
 
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 4d344eb279903..c7921d2bd4588 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -326,7 +326,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     if reached_raw_pointer
                     && !self.tcx.features().arbitrary_self_types {
                         // this case used to be allowed by the compiler,
-                        // so we do a future-compat lint here for the 2015 epoch
+                        // so we do a future-compat lint here for the 2015 edition
                         // (see https://github.com/rust-lang/rust/issues/46906)
                         if self.tcx.sess.rust_2018() {
                           span_err!(self.tcx.sess, span, E0908,
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 6013c20daf235..56b1306e5b33f 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -13,7 +13,7 @@ use feature_gate::{feature_err, EXPLAIN_STMT_ATTR_SYNTAX, Features, get_features
 use {fold, attr};
 use ast;
 use codemap::Spanned;
-use epoch::Epoch;
+use edition::Edition;
 use parse::{token, ParseSess};
 
 use ptr::P;
@@ -27,7 +27,7 @@ pub struct StripUnconfigured<'a> {
 }
 
 // `cfg_attr`-process the crate's attributes and compute the crate's features.
-pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, epoch: Epoch)
+pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, edition: Edition)
                 -> (ast::Crate, Features) {
     let features;
     {
@@ -47,7 +47,7 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, epoc
             return (krate, Features::new());
         }
 
-        features = get_features(&sess.span_diagnostic, &krate.attrs, epoch);
+        features = get_features(&sess.span_diagnostic, &krate.attrs, edition);
 
         // Avoid reconfiguring malformed `cfg_attr`s
         if err_count == sess.span_diagnostic.err_count() {
diff --git a/src/libsyntax/epoch.rs b/src/libsyntax/edition.rs
similarity index 56%
rename from src/libsyntax/epoch.rs
rename to src/libsyntax/edition.rs
index 32cbc79c550e3..12ac6410ce193 100644
--- a/src/libsyntax/epoch.rs
+++ b/src/libsyntax/edition.rs
@@ -11,58 +11,58 @@
 use std::fmt;
 use std::str::FromStr;
 
-/// The epoch of the compiler (RFC 2052)
+/// The edition of the compiler (RFC 2052)
 #[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)]
 #[non_exhaustive]
-pub enum Epoch {
-    // epochs must be kept in order, newest to oldest
+pub enum Edition {
+    // editions must be kept in order, newest to oldest
 
-    /// The 2015 epoch
-    Epoch2015,
-    /// The 2018 epoch
-    Epoch2018,
+    /// The 2015 edition
+    Edition2015,
+    /// The 2018 edition
+    Edition2018,
 
-    // when adding new epochs, be sure to update:
+    // when adding new editions, be sure to update:
     //
-    // - the list in the `parse_epoch` static in librustc::session::config
+    // - the list in the `parse_edition` static in librustc::session::config
     // - add a `rust_####()` function to the session
     // - update the enum in Cargo's sources as well
     //
-    // When -Zepoch becomes --epoch, there will
-    // also be a check for the epoch being nightly-only
+    // When -Zedition becomes --edition, there will
+    // also be a check for the edition being nightly-only
     // somewhere. That will need to be updated
-    // whenever we're stabilizing/introducing a new epoch
+    // whenever we're stabilizing/introducing a new edition
     // as well as changing the default Cargo template.
 }
 
 // must be in order from oldest to newest
-pub const ALL_EPOCHS: &[Epoch] = &[Epoch::Epoch2015, Epoch::Epoch2018];
+pub const ALL_EPOCHS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
 
-impl fmt::Display for Epoch {
+impl fmt::Display for Edition {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let s = match *self {
-            Epoch::Epoch2015 => "2015",
-            Epoch::Epoch2018 => "2018",
+            Edition::Edition2015 => "2015",
+            Edition::Edition2018 => "2018",
         };
         write!(f, "{}", s)
     }
 }
 
-impl Epoch {
+impl Edition {
     pub fn lint_name(&self) -> &'static str {
         match *self {
-            Epoch::Epoch2015 => "epoch_2015",
-            Epoch::Epoch2018 => "epoch_2018",
+            Edition::Edition2015 => "edition_2015",
+            Edition::Edition2018 => "edition_2018",
         }
     }
 }
 
-impl FromStr for Epoch {
+impl FromStr for Edition {
     type Err = ();
     fn from_str(s: &str) -> Result<Self, ()> {
         match s {
-            "2015" => Ok(Epoch::Epoch2015),
-            "2018" => Ok(Epoch::Epoch2018),
+            "2015" => Ok(Edition::Edition2015),
+            "2018" => Ok(Edition::Edition2018),
             _ => Err(())
         }
     }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 915396d29fe26..8feb8d6a4020d 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -28,7 +28,7 @@ use self::AttributeGate::*;
 use abi::Abi;
 use ast::{self, NodeId, PatKind, RangeEnd};
 use attr;
-use epoch::Epoch;
+use edition::Edition;
 use codemap::Spanned;
 use syntax_pos::{Span, DUMMY_SP};
 use errors::{DiagnosticBuilder, Handler, FatalError};
@@ -55,13 +55,13 @@ macro_rules! set {
 }
 
 macro_rules! declare_features {
-    ($((active, $feature: ident, $ver: expr, $issue: expr, $epoch: expr),)+) => {
+    ($((active, $feature: ident, $ver: expr, $issue: expr, $edition: expr),)+) => {
         /// Represents active features that are currently being implemented or
         /// currently being considered for addition/removal.
         const ACTIVE_FEATURES:
                 &'static [(&'static str, &'static str, Option<u32>,
-                           Option<Epoch>, fn(&mut Features, Span))] =
-            &[$((stringify!($feature), $ver, $issue, $epoch, set!($feature))),+];
+                           Option<Edition>, fn(&mut Features, Span))] =
+            &[$((stringify!($feature), $ver, $issue, $edition, set!($feature))),+];
 
         /// A set of features to be used by later passes.
         #[derive(Clone)]
@@ -402,7 +402,7 @@ declare_features! (
     (active, match_default_bindings, "1.22.0", Some(42640), None),
 
     // Trait object syntax with `dyn` prefix
-    (active, dyn_trait, "1.22.0", Some(44662), Some(Epoch::Epoch2018)),
+    (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)),
 
     // `crate` as visibility modifier, synonymous to `pub(crate)`
     (active, crate_visibility_modifier, "1.23.0", Some(45388), None),
@@ -1800,16 +1800,16 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 }
 
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
-                    epoch: Epoch) -> Features {
+                    edition: Edition) -> Features {
     let mut features = Features::new();
 
     let mut feature_checker = FeatureChecker::default();
 
-    for &(.., f_epoch, set) in ACTIVE_FEATURES.iter() {
-        if let Some(f_epoch) = f_epoch {
-            if epoch >= f_epoch {
+    for &(.., f_edition, set) in ACTIVE_FEATURES.iter() {
+        if let Some(f_edition) = f_edition {
+            if edition >= f_edition {
                 // FIXME(Manishearth) there is currently no way to set
-                // lang features by epoch
+                // lang features by edition
                 set(&mut features, DUMMY_SP);
             }
         }
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index 5f58b3bc3a050..74f1ee373ec63 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -145,7 +145,7 @@ pub mod codemap;
 #[macro_use]
 pub mod config;
 pub mod entry;
-pub mod epoch;
+pub mod edition;
 pub mod feature_gate;
 pub mod fold;
 pub mod parse;
diff --git a/src/test/compile-fail/epoch-raw-pointer-method-2015.rs b/src/test/compile-fail/edition-raw-pointer-method-2015.rs
similarity index 85%
rename from src/test/compile-fail/epoch-raw-pointer-method-2015.rs
rename to src/test/compile-fail/edition-raw-pointer-method-2015.rs
index 6aa83a38b7ee9..fdc9b4f704cd1 100644
--- a/src/test/compile-fail/epoch-raw-pointer-method-2015.rs
+++ b/src/test/compile-fail/edition-raw-pointer-method-2015.rs
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Zepoch=2015 -Zunstable-options
+// compile-flags: -Zedition=2015 -Zunstable-options
 
-// tests that epochs work with the tyvar warning-turned-error
+// tests that editions work with the tyvar warning-turned-error
 
 #[deny(warnings)]
 fn main() {
diff --git a/src/test/compile-fail/epoch-raw-pointer-method-2018.rs b/src/test/compile-fail/edition-raw-pointer-method-2018.rs
similarity index 85%
rename from src/test/compile-fail/epoch-raw-pointer-method-2018.rs
rename to src/test/compile-fail/edition-raw-pointer-method-2018.rs
index c4815de2306e9..58b34591029ba 100644
--- a/src/test/compile-fail/epoch-raw-pointer-method-2018.rs
+++ b/src/test/compile-fail/edition-raw-pointer-method-2018.rs
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// compile-flags: -Zepoch=2018 -Zunstable-options
+// compile-flags: -Zedition=2018 -Zunstable-options
 
-// tests that epochs work with the tyvar warning-turned-error
+// tests that editions work with the tyvar warning-turned-error
 
 #[deny(warnings)]
 fn main() {
diff --git a/src/test/run-pass/dyn-trait.rs b/src/test/run-pass/dyn-trait.rs
index fdec6a26ac945..399823ec92d0c 100644
--- a/src/test/run-pass/dyn-trait.rs
+++ b/src/test/run-pass/dyn-trait.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-pretty `dyn ::foo` parses differently in the current epoch
+// ignore-pretty `dyn ::foo` parses differently in the current edition
 
 #![feature(dyn_trait)]
 
diff --git a/src/test/run-pass/epoch-gate-feature.rs b/src/test/run-pass/epoch-gate-feature.rs
index 37d092c06e02b..f3d8f216e1132 100644
--- a/src/test/run-pass/epoch-gate-feature.rs
+++ b/src/test/run-pass/epoch-gate-feature.rs
@@ -11,7 +11,7 @@
 // Checks if the correct registers are being used to pass arguments
 // when the sysv64 ABI is specified.
 
-// compile-flags: -Zepoch=2018
+// compile-flags: -Zedition=2018
 
 pub trait Foo {}
 
diff --git a/src/test/ui/inference-variable-behind-raw-pointer.stderr b/src/test/ui/inference-variable-behind-raw-pointer.stderr
index eb40151615dad..fe6dc0b07482f 100644
--- a/src/test/ui/inference-variable-behind-raw-pointer.stderr
+++ b/src/test/ui/inference-variable-behind-raw-pointer.stderr
@@ -5,6 +5,6 @@ LL |     if data.is_null() {}
    |             ^^^^^^^
    |
    = note: #[warn(tyvar_behind_raw_pointer)] on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 epoch!
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
    = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
 

From 11f14060a4da7776c5f56e7dc53cc9545e4ab25f Mon Sep 17 00:00:00 2001
From: Kurtis Nusbaum <kcommiter@gmail.com>
Date: Wed, 14 Mar 2018 20:56:13 -0700
Subject: [PATCH 23/37] change all appropriate EPOCH to EDITION

---
 src/librustc/lint/context.rs | 2 +-
 src/libsyntax/edition.rs     | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 936aa71f16cea..3c833251f72a7 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -201,7 +201,7 @@ impl LintStore {
                                         sess: Option<&Session>,
                                         lints: Vec<FutureIncompatibleInfo>) {
 
-        for edition in edition::ALL_EPOCHS {
+        for edition in edition::ALL_EDITIONS {
             let lints = lints.iter().filter(|f| f.edition == Some(*edition)).map(|f| f.id)
                              .collect::<Vec<_>>();
             if !lints.is_empty() {
diff --git a/src/libsyntax/edition.rs b/src/libsyntax/edition.rs
index 12ac6410ce193..61246d4493ca3 100644
--- a/src/libsyntax/edition.rs
+++ b/src/libsyntax/edition.rs
@@ -36,7 +36,7 @@ pub enum Edition {
 }
 
 // must be in order from oldest to newest
-pub const ALL_EPOCHS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
+pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
 
 impl fmt::Display for Edition {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

From 72334fee6fad3c51a036d7f592915ea472959714 Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Tue, 20 Mar 2018 14:19:16 -0500
Subject: [PATCH 24/37] typeck: Report main return type errors on return type
 span

---
 src/librustc_typeck/check/mod.rs                      |  3 ++-
 .../termination-trait-main-wrong-type.rs              |  3 +--
 .../termination-trait-main-wrong-type.stderr          | 11 +++++++++++
 3 files changed, 14 insertions(+), 3 deletions(-)
 rename src/test/{compile-fail => ui}/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs (80%)
 create mode 100644 src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr

diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 42bf516a0afa5..a951fa7eb220e 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1114,8 +1114,9 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
                     Some(config::EntryMain) => {
                         let substs = fcx.tcx.mk_substs(iter::once(Kind::from(ret_ty)));
                         let trait_ref = ty::TraitRef::new(term_id, substs);
+                        let return_ty_span = decl.output.span();
                         let cause = traits::ObligationCause::new(
-                            span, fn_id, ObligationCauseCode::MainFunctionType);
+                            return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
 
                         inherited.register_predicate(
                             traits::Obligation::new(
diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
similarity index 80%
rename from src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
rename to src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
index 5f4ccf2b5862e..425f51ca2fb54 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:`main` can only return types that implement std::process::Termination, not `char
-fn main() -> char {
+fn main() -> char { //~ ERROR
     ' '
 }
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
new file mode 100644
index 0000000000000..d09aac3ac2f27
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `char: std::process::Termination` is not satisfied
+  --> $DIR/termination-trait-main-wrong-type.rs:11:14
+   |
+LL | fn main() -> char { //~ ERROR
+   |              ^^^^ `main` can only return types that implement std::process::Termination, not `char`
+   |
+   = help: the trait `std::process::Termination` is not implemented for `char`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.

From 1937661961fa54aa2bce8c301d85536916224a74 Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Tue, 20 Mar 2018 22:45:35 -0500
Subject: [PATCH 25/37] Revert "Stabilize termination_trait in 1.25, not 1.26"

This reverts commit e5a55e74405dedf8bc0744300a8c506eea94bc18.
---
 src/libsyntax/feature_gate.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index e71726bcebdc9..781071b7f7f07 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -551,12 +551,12 @@ declare_features! (
     (accepted, match_beginning_vert, "1.25.0", Some(44101), None),
     // Nested groups in `use` (RFC 2128)
     (accepted, use_nested_groups, "1.25.0", Some(44494), None),
-    // Termination trait in main (RFC 1937)
-    (accepted, termination_trait, "1.25.0", Some(43301), None),
     // a..=b and ..=b
     (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None),
     // allow `..=` in patterns (RFC 1192)
     (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None),
+    // Termination trait in main (RFC 1937)
+    (accepted, termination_trait, "1.26.0", Some(43301), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must

From 94bdeb64f96b266d990ba7b76cd78a1e2ed1977f Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Tue, 20 Mar 2018 23:01:42 -0500
Subject: [PATCH 26/37] termination_trait: Add () example to error message

---
 src/libstd/process.rs                                           | 2 +-
 .../rfc-1937-termination-trait/termination-trait-main-i32.rs    | 2 +-
 .../termination-trait-main-wrong-type.stderr                    | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index d5ac2d19e831f..a6aa3502f26bb 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1443,7 +1443,7 @@ pub fn id() -> u32 {
 #[cfg_attr(not(test), lang = "termination")]
 #[unstable(feature = "termination_trait_lib", issue = "43301")]
 #[rustc_on_unimplemented =
-  "`main` can only return types that implement {Termination}, not `{Self}`"]
+  "`main` can only return types like `()` that implement {Termination}, not `{Self}`"]
 pub trait Termination {
     /// Is called to get the representation of the value as status code.
     /// This status code is returned to the operating system.
diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
index 67ee39d10d91c..ffff33da581bf 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:`main` can only return types that implement std::process::Termination, not `i32`
+// error-pattern:`main` can only return types like `()` that implement std::process::Termination, no
 fn main() -> i32 {
     0
 }
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
index d09aac3ac2f27..24371c27742d2 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `char: std::process::Termination` is not satisfied
   --> $DIR/termination-trait-main-wrong-type.rs:11:14
    |
 LL | fn main() -> char { //~ ERROR
-   |              ^^^^ `main` can only return types that implement std::process::Termination, not `char`
+   |              ^^^^ `main` can only return types like `()` that implement std::process::Termination, not `char`
    |
    = help: the trait `std::process::Termination` is not implemented for `char`
 

From 2cdc7af41366182259a05435e325d7444653a3e8 Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Wed, 21 Mar 2018 00:24:06 -0500
Subject: [PATCH 27/37] Use NOTE instead of error-pattern directive

---
 .../rfc-1937-termination-trait/termination-trait-main-i32.rs   | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
index ffff33da581bf..053d6bbf93a2d 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:`main` can only return types like `()` that implement std::process::Termination, no
 fn main() -> i32 {
+//~^ ERROR `i32: std::process::Termination` is not satisfied
+//~| NOTE `main` can only return types like `()` that implement std::process::Termination, not `i32`
     0
 }

From b6934c91b23517c4e17d8016b6c46ffd0703eded Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Wed, 21 Mar 2018 13:32:46 -0500
Subject: [PATCH 28/37] termination_trait: Put examples in error help, not
 label

---
 src/librustc/traits/error_reporting.rs        | 23 +++++++++++--------
 src/libstd/process.rs                         |  2 +-
 .../termination-trait-main-i32.rs             |  2 +-
 .../termination-trait-main-wrong-type.stderr  |  4 ++--
 4 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 7e5dc02798dff..8572c4077142b 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -585,20 +585,25 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                          trait_ref.to_predicate(), post_message)
                             }));
 
+                        let explanation = match obligation.cause.code {
+                            ObligationCauseCode::MainFunctionType => {
+                                "consider using `()`, or a `Result`".to_owned()
+                            }
+                            _ => {
+                                format!("{}the trait `{}` is not implemented for `{}`",
+                                         pre_message,
+                                         trait_ref,
+                                         trait_ref.self_ty())
+                            }
+                        };
+
                         if let Some(ref s) = label {
                             // If it has a custom "#[rustc_on_unimplemented]"
                             // error message, let's display it as the label!
                             err.span_label(span, s.as_str());
-                            err.help(&format!("{}the trait `{}` is not implemented for `{}`",
-                                              pre_message,
-                                              trait_ref,
-                                              trait_ref.self_ty()));
+                            err.help(&explanation);
                         } else {
-                            err.span_label(span,
-                                           &*format!("{}the trait `{}` is not implemented for `{}`",
-                                                     pre_message,
-                                                     trait_ref,
-                                                     trait_ref.self_ty()));
+                            err.span_label(span, explanation);
                         }
                         if let Some(ref s) = note {
                             // If it has a custom "#[rustc_on_unimplemented]" note, let's display it
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index a6aa3502f26bb..d5ac2d19e831f 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1443,7 +1443,7 @@ pub fn id() -> u32 {
 #[cfg_attr(not(test), lang = "termination")]
 #[unstable(feature = "termination_trait_lib", issue = "43301")]
 #[rustc_on_unimplemented =
-  "`main` can only return types like `()` that implement {Termination}, not `{Self}`"]
+  "`main` can only return types that implement {Termination}, not `{Self}`"]
 pub trait Termination {
     /// Is called to get the representation of the value as status code.
     /// This status code is returned to the operating system.
diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
index 053d6bbf93a2d..2cf9fdcfb4dbd 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
@@ -10,6 +10,6 @@
 
 fn main() -> i32 {
 //~^ ERROR `i32: std::process::Termination` is not satisfied
-//~| NOTE `main` can only return types like `()` that implement std::process::Termination, not `i32`
+//~| NOTE `main` can only return types that implement std::process::Termination, not `i32`
     0
 }
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
index 24371c27742d2..211247757cbc1 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
@@ -2,9 +2,9 @@ error[E0277]: the trait bound `char: std::process::Termination` is not satisfied
   --> $DIR/termination-trait-main-wrong-type.rs:11:14
    |
 LL | fn main() -> char { //~ ERROR
-   |              ^^^^ `main` can only return types like `()` that implement std::process::Termination, not `char`
+   |              ^^^^ `main` can only return types that implement std::process::Termination, not `char`
    |
-   = help: the trait `std::process::Termination` is not implemented for `char`
+   = help: consider using `()`, or a `Result`
 
 error: aborting due to previous error
 

From 178652a2988d9ecd478a4116237e1d7ea6b777f7 Mon Sep 17 00:00:00 2001
From: David Wood <david@davidtw.co>
Date: Tue, 20 Mar 2018 02:06:38 +0000
Subject: [PATCH 29/37] Add support to rustbuild for a 'rustc docs' component
 tarball

---
 src/bootstrap/builder.rs |  12 ++--
 src/bootstrap/dist.rs    |  69 +++++++++++++++++---
 src/bootstrap/doc.rs     | 133 ++++++++++++++++++++++++++++++---------
 src/bootstrap/lib.rs     |   5 ++
 4 files changed, 178 insertions(+), 41 deletions(-)

diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 675d3dd437eef..9f779da6f65b3 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -316,11 +316,13 @@ impl<'a> Builder<'a> {
                 test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme),
             Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
-                doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
-                doc::Reference, doc::Rustdoc, doc::RustByExample, doc::CargoBook),
-            Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts,
-                dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo,
-                dist::Rls, dist::Rustfmt, dist::Extended, dist::HashSign),
+                doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc,
+                doc::ErrorIndex, doc::Nomicon, doc::Reference, doc::Rustdoc, doc::RustByExample,
+                doc::CargoBook),
+            Kind::Dist => describe!(dist::Docs, dist::RustcDocs, dist::Mingw, dist::Rustc,
+                dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src,
+                dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Rustfmt, dist::Extended,
+                dist::HashSign),
             Kind::Install => describe!(install::Docs, install::Std, install::Cargo, install::Rls,
                 install::Rustfmt, install::Analysis, install::Src, install::Rustc),
         }
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index dcb572416594e..e25a7e1852586 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -102,7 +102,7 @@ impl Step for Docs {
 
         let dst = image.join("share/doc/rust/html");
         t!(fs::create_dir_all(&dst));
-        let src = build.out.join(host).join("doc");
+        let src = build.doc_out(host);
         cp_r(&src, &dst);
 
         let mut cmd = rust_installer(builder);
@@ -120,14 +120,69 @@ impl Step for Docs {
         build.run(&mut cmd);
         t!(fs::remove_dir_all(&image));
 
-        // As part of this step, *also* copy the docs directory to a directory which
-        // buildbot typically uploads.
-        if host == build.build {
-            let dst = distdir(build).join("doc").join(build.rust_package_vers());
-            t!(fs::create_dir_all(&dst));
-            cp_r(&src, &dst);
+        distdir(build).join(format!("{}-{}.tar.gz", name, host))
+    }
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct RustcDocs {
+    pub stage: u32,
+    pub host: Interned<String>,
+}
+
+impl Step for RustcDocs {
+    type Output = PathBuf;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.path("src/librustc")
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(RustcDocs {
+            stage: run.builder.top_stage,
+            host: run.target,
+        });
+    }
+
+    /// Builds the `rustc-docs` installer component.
+    fn run(self, builder: &Builder) -> PathBuf {
+        let build = builder.build;
+        let host = self.host;
+
+        let name = pkgname(build, "rustc-docs");
+
+        println!("Dist compiler docs ({})", host);
+        if !build.config.compiler_docs {
+            println!("\tskipping - compiler docs disabled");
+            return distdir(build).join(format!("{}-{}.tar.gz", name, host));
         }
 
+        builder.default_doc(None);
+
+        let image = tmpdir(build).join(format!("{}-{}-image", name, host));
+        let _ = fs::remove_dir_all(&image);
+
+        let dst = image.join("share/doc/rustc/html");
+        t!(fs::create_dir_all(&dst));
+        let src = build.compiler_doc_out(host);
+        cp_r(&src, &dst);
+
+        let mut cmd = rust_installer(builder);
+        cmd.arg("generate")
+           .arg("--product-name=Rustc-Documentation")
+           .arg("--rel-manifest-dir=rustlib")
+           .arg("--success-message=Rustc-documentation-is-installed.")
+           .arg("--image-dir").arg(&image)
+           .arg("--work-dir").arg(&tmpdir(build))
+           .arg("--output-dir").arg(&distdir(build))
+           .arg(format!("--package-name={}-{}", name, host))
+           .arg("--component-name=rustc-docs")
+           .arg("--legacy-manifest-dirs=rustlib,cargo")
+           .arg("--bulk-dirs=share/doc/rustc/html");
+        build.run(&mut cmd);
+        t!(fs::remove_dir_all(&image));
+
         distdir(build).join(format!("{}-{}.tar.gz", name, host))
     }
 }
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 5bc582b3507bb..ca45adb4649af 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -483,21 +483,17 @@ impl Step for Std {
         let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "doc");
         compile::std_cargo(builder, &compiler, target, &mut cargo);
 
-        // We don't want to build docs for internal std dependencies unless
-        // in compiler-docs mode. When not in that mode, we whitelist the crates
-        // for which docs must be built.
-        if !build.config.compiler_docs {
-            cargo.arg("--no-deps");
-            for krate in &["alloc", "core", "std", "std_unicode"] {
-                cargo.arg("-p").arg(krate);
-                // Create all crate output directories first to make sure rustdoc uses
-                // relative links.
-                // FIXME: Cargo should probably do this itself.
-                t!(fs::create_dir_all(out_dir.join(krate)));
-            }
+        // Keep a whitelist so we do not build internal stdlib crates, these will be
+        // build by the rustc step later if enabled.
+        cargo.arg("--no-deps");
+        for krate in &["alloc", "core", "std", "std_unicode"] {
+            cargo.arg("-p").arg(krate);
+            // Create all crate output directories first to make sure rustdoc uses
+            // relative links.
+            // FIXME: Cargo should probably do this itself.
+            t!(fs::create_dir_all(out_dir.join(krate)));
         }
 
-
         build.run(&mut cargo);
         cp_r(&my_out, &out);
     }
@@ -563,6 +559,81 @@ impl Step for Test {
     }
 }
 
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct WhitelistedRustc {
+    stage: u32,
+    target: Interned<String>,
+}
+
+impl Step for WhitelistedRustc {
+    type Output = ();
+    const DEFAULT: bool = true;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        let builder = run.builder;
+        run.krate("rustc-main").default_condition(builder.build.config.docs)
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(WhitelistedRustc {
+            stage: run.builder.top_stage,
+            target: run.target,
+        });
+    }
+
+    /// Generate whitelisted compiler crate documentation.
+    ///
+    /// This will generate all documentation for crates that are whitelisted
+    /// to be included in the standard documentation. This documentation is
+    /// included in the standard Rust documentation, so we should always
+    /// document it and symlink to merge with the rest of the std and test
+    /// documentation. We don't build other compiler documentation
+    /// here as we want to be able to keep it separate from the standard
+    /// documentation. This is largely just a wrapper around `cargo doc`.
+    fn run(self, builder: &Builder) {
+        let build = builder.build;
+        let stage = self.stage;
+        let target = self.target;
+        println!("Documenting stage{} whitelisted compiler ({})", stage, target);
+        let out = build.doc_out(target);
+        t!(fs::create_dir_all(&out));
+        let compiler = builder.compiler(stage, build.build);
+        let rustdoc = builder.rustdoc(compiler.host);
+        let compiler = if build.force_use_stage1(compiler, target) {
+            builder.compiler(1, compiler.host)
+        } else {
+            compiler
+        };
+
+        // Build libstd docs so that we generate relative links
+        builder.ensure(Std { stage, target });
+
+        builder.ensure(compile::Rustc { compiler, target });
+        let out_dir = build.stage_out(compiler, Mode::Librustc)
+                           .join(target).join("doc");
+
+        // See docs in std above for why we symlink
+        let my_out = build.crate_doc_out(target);
+        build.clear_if_dirty(&my_out, &rustdoc);
+        t!(symlink_dir_force(&my_out, &out_dir));
+
+        let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
+        compile::rustc_cargo(build, &mut cargo);
+
+        // We don't want to build docs for internal compiler dependencies in this
+        // step (there is another step for that). Therefore, we whitelist the crates
+        // for which docs must be built.
+        cargo.arg("--no-deps");
+        for krate in &["proc_macro"] {
+            cargo.arg("-p").arg(krate);
+        }
+
+        build.run(&mut cargo);
+        cp_r(&my_out, &out);
+    }
+}
+
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct Rustc {
     stage: u32,
@@ -586,16 +657,18 @@ impl Step for Rustc {
         });
     }
 
-    /// Generate all compiler documentation.
+    /// Generate compiler documentation.
     ///
-    /// This will generate all documentation for the compiler libraries and their
-    /// dependencies. This is largely just a wrapper around `cargo doc`.
+    /// This will generate all documentation for compiler and dependencies.
+    /// Compiler documentation is distributed separately, so we make sure
+    /// we do not merge it with the other documentation from std, test and
+    /// proc_macros. This is largely just a wrapper around `cargo doc`.
     fn run(self, builder: &Builder) {
         let build = builder.build;
         let stage = self.stage;
         let target = self.target;
         println!("Documenting stage{} compiler ({})", stage, target);
-        let out = build.doc_out(target);
+        let out = build.compiler_doc_out(target);
         t!(fs::create_dir_all(&out));
         let compiler = builder.compiler(stage, build.build);
         let rustdoc = builder.rustdoc(compiler.host);
@@ -605,6 +678,11 @@ impl Step for Rustc {
             compiler
         };
 
+        if !build.config.compiler_docs {
+            println!("\tskipping - compiler docs disabled");
+            return;
+        }
+
         // Build libstd docs so that we generate relative links
         builder.ensure(Std { stage, target });
 
@@ -613,6 +691,12 @@ impl Step for Rustc {
                            .join(target).join("doc");
 
         // See docs in std above for why we symlink
+        //
+        // This step must happen after other documentation steps. This
+        // invariant ensures that compiler documentation is not included
+        // in the standard documentation tarballs but that all the
+        // documentation from the standard documentation tarballs is included
+        // in the compiler documentation tarball.
         let my_out = build.crate_doc_out(target);
         build.clear_if_dirty(&my_out, &rustdoc);
         t!(symlink_dir_force(&my_out, &out_dir));
@@ -620,18 +704,9 @@ impl Step for Rustc {
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
         compile::rustc_cargo(build, &mut cargo);
 
-        if build.config.compiler_docs {
-            // src/rustc/Cargo.toml contains a bin crate called rustc which
-            // would otherwise overwrite the docs for the real rustc lib crate.
-            cargo.arg("-p").arg("rustc_driver");
-        } else {
-            // Like with libstd above if compiler docs aren't enabled then we're not
-            // documenting internal dependencies, so we have a whitelist.
-            cargo.arg("--no-deps");
-            for krate in &["proc_macro"] {
-                cargo.arg("-p").arg(krate);
-            }
-        }
+        // src/rustc/Cargo.toml contains a bin crate called rustc which
+        // would otherwise overwrite the docs for the real rustc lib crate.
+        cargo.arg("-p").arg("rustc_driver");
 
         build.run(&mut cargo);
         cp_r(&my_out, &out);
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index b778ba33d89cc..b2c8ac24d72d8 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -511,6 +511,11 @@ impl Build {
         self.out.join(&*target).join("doc")
     }
 
+    /// Output directory for all documentation for a target
+    fn compiler_doc_out(&self, target: Interned<String>) -> PathBuf {
+        self.out.join(&*target).join("compiler-doc")
+    }
+
     /// Output directory for some generated md crate documentation for a target (temporary)
     fn md_doc_out(&self, target: Interned<String>) -> Interned<PathBuf> {
         INTERNER.intern_path(self.out.join(&*target).join("md-doc"))

From 1392179cdc9c96e75353771959c246553b918d57 Mon Sep 17 00:00:00 2001
From: David Wood <david@davidtw.co>
Date: Tue, 20 Mar 2018 02:07:16 +0000
Subject: [PATCH 30/37] Configure the dist-x86_64-linux builder to produce
 compiler documentation

---
 src/ci/docker/dist-x86_64-linux/Dockerfile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile
index 3b98b0aa926bd..28c97e8c6dbf9 100644
--- a/src/ci/docker/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/dist-x86_64-linux/Dockerfile
@@ -84,7 +84,8 @@ ENV HOSTS=x86_64-unknown-linux-gnu
 ENV RUST_CONFIGURE_ARGS \
       --enable-full-tools \
       --enable-sanitizers \
-      --enable-profiler
+      --enable-profiler \
+      --enable-compiler-docs
 ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
 
 # This is the only builder which will create source tarballs

From 2b13d95da02d318c12814261dd36edd91ae6879e Mon Sep 17 00:00:00 2001
From: Tyler Mandry <tmandry@gmail.com>
Date: Wed, 21 Mar 2018 23:28:48 -0500
Subject: [PATCH 31/37] termination_trait: Make error message more helpful

---
 src/librustc/traits/error_reporting.rs           | 16 +++++++---------
 src/libstd/process.rs                            |  5 +++--
 .../termination-trait-main-i32.rs                |  5 +++--
 .../termination-trait-not-satisfied.rs           |  2 +-
 .../termination-trait-main-wrong-type.stderr     |  4 ++--
 5 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 8572c4077142b..47e6b0feceae3 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -585,17 +585,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                          trait_ref.to_predicate(), post_message)
                             }));
 
-                        let explanation = match obligation.cause.code {
-                            ObligationCauseCode::MainFunctionType => {
+                        let explanation =
+                            if obligation.cause.code == ObligationCauseCode::MainFunctionType {
                                 "consider using `()`, or a `Result`".to_owned()
-                            }
-                            _ => {
+                            } else {
                                 format!("{}the trait `{}` is not implemented for `{}`",
-                                         pre_message,
-                                         trait_ref,
-                                         trait_ref.self_ty())
-                            }
-                        };
+                                        pre_message,
+                                        trait_ref,
+                                        trait_ref.self_ty())
+                            };
 
                         if let Some(ref s) = label {
                             // If it has a custom "#[rustc_on_unimplemented]"
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index d5ac2d19e831f..c877bf6aa35cd 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1442,8 +1442,9 @@ pub fn id() -> u32 {
 /// a successful execution. In case of a failure, `libc::EXIT_FAILURE` is returned.
 #[cfg_attr(not(test), lang = "termination")]
 #[unstable(feature = "termination_trait_lib", issue = "43301")]
-#[rustc_on_unimplemented =
-  "`main` can only return types that implement {Termination}, not `{Self}`"]
+#[rustc_on_unimplemented(
+  message="`main` has invalid return type `{Self}`",
+  label="`main` can only return types that implement {Termination}")]
 pub trait Termination {
     /// Is called to get the representation of the value as status code.
     /// This status code is returned to the operating system.
diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
index 2cf9fdcfb4dbd..0e6ddf7c92f1a 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-main-i32.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 fn main() -> i32 {
-//~^ ERROR `i32: std::process::Termination` is not satisfied
-//~| NOTE `main` can only return types that implement std::process::Termination, not `i32`
+//~^ ERROR `main` has invalid return type `i32`
+//~| NOTE `main` can only return types that implement std::process::Termination
+//~| HELP consider using `()`, or a `Result`
     0
 }
diff --git a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
index bab02fc559706..b5f5472b49290 100644
--- a/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
+++ b/src/test/compile-fail/rfc-1937-termination-trait/termination-trait-not-satisfied.rs
@@ -10,6 +10,6 @@
 
 struct ReturnType {}
 
-fn main() -> ReturnType { //~ ERROR `ReturnType: std::process::Termination` is not satisfied
+fn main() -> ReturnType { //~ ERROR `main` has invalid return type `ReturnType`
     ReturnType {}
 }
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
index 211247757cbc1..5109d9275c58b 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-main-wrong-type.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `char: std::process::Termination` is not satisfied
+error[E0277]: `main` has invalid return type `char`
   --> $DIR/termination-trait-main-wrong-type.rs:11:14
    |
 LL | fn main() -> char { //~ ERROR
-   |              ^^^^ `main` can only return types that implement std::process::Termination, not `char`
+   |              ^^^^ `main` can only return types that implement std::process::Termination
    |
    = help: consider using `()`, or a `Result`
 

From b48a26cdd1d086a3ca7ffae35b73b72f9ce85b8f Mon Sep 17 00:00:00 2001
From: Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Date: Thu, 22 Mar 2018 09:56:04 +0100
Subject: [PATCH 32/37] Produce nice array lengths on a best effort basis

---
 src/librustc/traits/error_reporting.rs        | 16 ++++++++++---
 src/librustc/util/ppaux.rs                    |  4 ++--
 src/test/ui/did_you_mean/bad-assoc-ty.stderr  |  2 +-
 .../ui/unevaluated_fixed_size_array_len.rs    | 23 +++++++++++++++++++
 .../unevaluated_fixed_size_array_len.stderr   | 17 ++++++++++++++
 5 files changed, 56 insertions(+), 6 deletions(-)
 create mode 100644 src/test/ui/unevaluated_fixed_size_array_len.rs
 create mode 100644 src/test/ui/unevaluated_fixed_size_array_len.stderr

diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index ab3c619dcdcd0..79d5cf7935941 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -443,10 +443,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         } else {
             4
         };
+
+        let normalize = |candidate| self.tcx.global_tcx().infer_ctxt().enter(|ref infcx| {
+            let normalized = infcx
+                .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+                .normalize(candidate)
+                .ok();
+            match normalized {
+                Some(normalized) => format!("\n  {:?}", normalized.value),
+                None => format!("\n  {:?}", candidate),
+            }
+        });
+
         err.help(&format!("the following implementations were found:{}{}",
-                          &impl_candidates[0..end].iter().map(|candidate| {
-                              format!("\n  {:?}", candidate)
-                          }).collect::<String>(),
+                          &impl_candidates[0..end].iter().map(normalize).collect::<String>(),
                           if impl_candidates.len() > 5 {
                               format!("\nand {} others", impl_candidates.len() - 4)
                           } else {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 2c3ee1ec285a9..056f1278c47c7 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -1177,8 +1177,8 @@ define_print! {
                         ConstVal::Value(Value::ByVal(PrimVal::Bytes(sz))) => {
                             write!(f, "{}", sz)?;
                         }
-                        ConstVal::Unevaluated(_def_id, substs) => {
-                            write!(f, "<unevaluated{:?}>", &substs[..])?;
+                        ConstVal::Unevaluated(_def_id, _substs) => {
+                            write!(f, "_")?;
                         }
                         _ => {
                             write!(f, "{:?}", sz)?;
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
index 45dce3d8740d1..169a12ef92e98 100644
--- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
@@ -46,7 +46,7 @@ error[E0223]: ambiguous associated type
 LL | type A = [u8; 4]::AssocTy;
    |          ^^^^^^^^^^^^^^^^ ambiguous associated type
    |
-   = note: specify the type using the syntax `<[u8; <unevaluated[]>] as Trait>::AssocTy`
+   = note: specify the type using the syntax `<[u8; _] as Trait>::AssocTy`
 
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:15:10
diff --git a/src/test/ui/unevaluated_fixed_size_array_len.rs b/src/test/ui/unevaluated_fixed_size_array_len.rs
new file mode 100644
index 0000000000000..a6ed9f32106fb
--- /dev/null
+++ b/src/test/ui/unevaluated_fixed_size_array_len.rs
@@ -0,0 +1,23 @@
+// Copyright 2018 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.
+
+// https://github.com/rust-lang/rust/issues/49208
+
+trait Foo {
+    fn foo();
+}
+
+impl Foo for [(); 1] {
+    fn foo() {}
+}
+
+fn main() {
+    <[(); 0] as Foo>::foo() //~ ERROR E0277
+}
diff --git a/src/test/ui/unevaluated_fixed_size_array_len.stderr b/src/test/ui/unevaluated_fixed_size_array_len.stderr
new file mode 100644
index 0000000000000..6e959da99397b
--- /dev/null
+++ b/src/test/ui/unevaluated_fixed_size_array_len.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `[(); 0]: Foo` is not satisfied
+  --> $DIR/unevaluated_fixed_size_array_len.rs:22:5
+   |
+LL |     <[(); 0] as Foo>::foo() //~ ERROR E0277
+   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `[(); 0]`
+   |
+   = help: the following implementations were found:
+             <[(); 1] as Foo>
+note: required by `Foo::foo`
+  --> $DIR/unevaluated_fixed_size_array_len.rs:14:5
+   |
+LL |     fn foo();
+   |     ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.

From 25c5b03aa58331e2d7c92c11dddd023b96d7fb98 Mon Sep 17 00:00:00 2001
From: Hidehito Yabuuchi <hdht.ybuc@gmail.com>
Date: Thu, 22 Mar 2018 20:57:12 +0900
Subject: [PATCH 33/37] Better diagnostics for '..' pattern fragment not in the
 last position

---
 src/libsyntax/parse/parser.rs  |  8 +++++++-
 src/test/ui/issue-49257.rs     | 23 +++++++++++++++++++++++
 src/test/ui/issue-49257.stderr | 21 +++++++++++++++++++++
 3 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 src/test/ui/issue-49257.rs
 create mode 100644 src/test/ui/issue-49257.stderr

diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 6d8975197d55c..c471b2325f9dd 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -3672,7 +3672,13 @@ impl<'a> Parser<'a> {
                 if self.token != token::CloseDelim(token::Brace) {
                     let token_str = self.this_token_to_string();
                     let mut err = self.fatal(&format!("expected `{}`, found `{}`", "}", token_str));
-                    err.span_label(self.span, "expected `}`");
+                    if self.token == token::Comma { // Issue #49257
+                        err.span_label(self.span,
+                                       "`..` must be in the last position, \
+                                        and cannot have a trailing comma");
+                    } else {
+                        err.span_label(self.span, "expected `}`");
+                    }
                     return Err(err);
                 }
                 etc = true;
diff --git a/src/test/ui/issue-49257.rs b/src/test/ui/issue-49257.rs
new file mode 100644
index 0000000000000..75b9e12684165
--- /dev/null
+++ b/src/test/ui/issue-49257.rs
@@ -0,0 +1,23 @@
+// Copyright 2018 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.
+
+// Test for #49257:
+// emits good diagnostics for `..` pattern fragments not in the last position.
+
+#![allow(unused)]
+
+struct Point { x: u8, y: u8 }
+
+fn main() {
+    let p = Point { x: 0, y: 0 };
+    let Point { .., y } = p; //~ ERROR expected `}`, found `,`
+    //~^ pattern does not mention field `x`
+    //~^^ pattern does not mention field `y`
+}
diff --git a/src/test/ui/issue-49257.stderr b/src/test/ui/issue-49257.stderr
new file mode 100644
index 0000000000000..ecaf36520aec9
--- /dev/null
+++ b/src/test/ui/issue-49257.stderr
@@ -0,0 +1,21 @@
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:20:19
+   |
+LL |     let Point { .., y } = p; //~ ERROR expected `}`, found `,`
+   |                   ^ `..` must be in the last position, and cannot have a trailing comma
+
+error[E0027]: pattern does not mention field `x`
+  --> $DIR/issue-49257.rs:20:9
+   |
+LL |     let Point { .., y } = p; //~ ERROR expected `}`, found `,`
+   |         ^^^^^^^^^^^^^^^ missing field `x`
+
+error[E0027]: pattern does not mention field `y`
+  --> $DIR/issue-49257.rs:20:9
+   |
+LL |     let Point { .., y } = p; //~ ERROR expected `}`, found `,`
+   |         ^^^^^^^^^^^^^^^ missing field `y`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0027`.

From de1c929adaeb5b1e466b6f8485a9f7cf92969185 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Marie?= <semarie@users.noreply.github.com>
Date: Thu, 22 Mar 2018 11:27:59 +0100
Subject: [PATCH 34/37] Use GNU version of fgrep/egrep tool if available

It is mostly for BSD system. Some tests (run-make/issue-35164 and
run-make/cat-and-grep-sanity-check) are failing with BSD
fgrep, whereas they pass with gnu version (gfgrep).
---
 src/etc/cat-and-grep.sh | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/etc/cat-and-grep.sh b/src/etc/cat-and-grep.sh
index ef9884d2e980d..361e8d8e60eed 100755
--- a/src/etc/cat-and-grep.sh
+++ b/src/etc/cat-and-grep.sh
@@ -63,6 +63,11 @@ done
 
 shift $((OPTIND - 1))
 
+# use gnu version of tool if available (for bsd)
+if command -v "g${GREPPER}"; then
+    GREPPER="g${GREPPER}"
+fi
+
 LOG=$(mktemp -t cgrep.XXXXXX)
 trap "rm -f $LOG" EXIT
 

From 347b9d6b563f8f436a27fa5cfd10bc2e43cbb8b7 Mon Sep 17 00:00:00 2001
From: Hidehito Yabuuchi <hdht.ybuc@gmail.com>
Date: Fri, 23 Mar 2018 01:15:27 +0900
Subject: [PATCH 35/37] Fix error annotations in test

---
 src/test/ui/issue-49257.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/test/ui/issue-49257.rs b/src/test/ui/issue-49257.rs
index 75b9e12684165..61883294594bc 100644
--- a/src/test/ui/issue-49257.rs
+++ b/src/test/ui/issue-49257.rs
@@ -18,6 +18,6 @@ struct Point { x: u8, y: u8 }
 fn main() {
     let p = Point { x: 0, y: 0 };
     let Point { .., y } = p; //~ ERROR expected `}`, found `,`
-    //~^ pattern does not mention field `x`
-    //~^^ pattern does not mention field `y`
+    //~| ERROR pattern does not mention field `x`
+    //~| ERROR pattern does not mention field `y`
 }

From 1b0e9f5af9283b003f5fce6f19ede145c1776684 Mon Sep 17 00:00:00 2001
From: David Wood <david@davidtw.co>
Date: Thu, 22 Mar 2018 14:57:28 +0000
Subject: [PATCH 36/37] Only generate documentation for local rustc crates.

---
 src/bootstrap/doc.rs | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)

diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index ca45adb4649af..e525bdb98fc0c 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -17,12 +17,13 @@
 //! Everything here is basically just a shim around calling either `rustbook` or
 //! `rustdoc`.
 
+use std::collections::HashSet;
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io;
 use std::path::{PathBuf, Path};
 
-use Mode;
+use {Build, Mode};
 use build_helper::up_to_date;
 
 use util::{cp_r, symlink_dir};
@@ -704,15 +705,41 @@ impl Step for Rustc {
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
         compile::rustc_cargo(build, &mut cargo);
 
-        // src/rustc/Cargo.toml contains a bin crate called rustc which
-        // would otherwise overwrite the docs for the real rustc lib crate.
-        cargo.arg("-p").arg("rustc_driver");
+        // Only include compiler crates, no dependencies of those, such as `libc`.
+        cargo.arg("--no-deps");
+
+        // Find dependencies for top level crates.
+        let mut compiler_crates = HashSet::new();
+        for root_crate in &["rustc", "rustc_driver"] {
+            let interned_root_crate = INTERNER.intern_str(root_crate);
+            find_compiler_crates(&build, &interned_root_crate, &mut compiler_crates);
+        }
+
+        for krate in &compiler_crates {
+            cargo.arg("-p").arg(krate);
+        }
 
         build.run(&mut cargo);
         cp_r(&my_out, &out);
     }
 }
 
+fn find_compiler_crates(
+    build: &Build,
+    name: &Interned<String>,
+    crates: &mut HashSet<Interned<String>>
+) {
+    // Add current crate.
+    crates.insert(*name);
+
+    // Look for dependencies.
+    for dep in build.crates.get(name).unwrap().deps.iter() {
+        if build.crates.get(dep).unwrap().is_local(build) {
+            find_compiler_crates(build, dep, crates);
+        }
+    }
+}
+
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
     target: Interned<String>,

From 73fa6d52ed99651940267affa941a1069cc20f35 Mon Sep 17 00:00:00 2001
From: David Wood <david@davidtw.co>
Date: Thu, 22 Mar 2018 20:49:05 +0000
Subject: [PATCH 37/37] Remove std/test documentation from compiler docs.

---
 src/bootstrap/dist.rs |  4 ++--
 src/bootstrap/doc.rs  | 16 ++++------------
 2 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index e25a7e1852586..5563b153f5aff 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -163,7 +163,7 @@ impl Step for RustcDocs {
         let image = tmpdir(build).join(format!("{}-{}-image", name, host));
         let _ = fs::remove_dir_all(&image);
 
-        let dst = image.join("share/doc/rustc/html");
+        let dst = image.join("share/doc/rust/html");
         t!(fs::create_dir_all(&dst));
         let src = build.compiler_doc_out(host);
         cp_r(&src, &dst);
@@ -179,7 +179,7 @@ impl Step for RustcDocs {
            .arg(format!("--package-name={}-{}", name, host))
            .arg("--component-name=rustc-docs")
            .arg("--legacy-manifest-dirs=rustlib,cargo")
-           .arg("--bulk-dirs=share/doc/rustc/html");
+           .arg("--bulk-dirs=share/doc/rust/html");
         build.run(&mut cmd);
         t!(fs::remove_dir_all(&image));
 
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index e525bdb98fc0c..44073a5b07572 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -690,17 +690,10 @@ impl Step for Rustc {
         builder.ensure(compile::Rustc { compiler, target });
         let out_dir = build.stage_out(compiler, Mode::Librustc)
                            .join(target).join("doc");
-
-        // See docs in std above for why we symlink
-        //
-        // This step must happen after other documentation steps. This
-        // invariant ensures that compiler documentation is not included
-        // in the standard documentation tarballs but that all the
-        // documentation from the standard documentation tarballs is included
-        // in the compiler documentation tarball.
-        let my_out = build.crate_doc_out(target);
-        build.clear_if_dirty(&my_out, &rustdoc);
-        t!(symlink_dir_force(&my_out, &out_dir));
+        // We do not symlink to the same shared folder that already contains std library
+        // documentation from previous steps as we do not want to include that.
+        build.clear_if_dirty(&out, &rustdoc);
+        t!(symlink_dir_force(&out, &out_dir));
 
         let mut cargo = builder.cargo(compiler, Mode::Librustc, target, "doc");
         compile::rustc_cargo(build, &mut cargo);
@@ -720,7 +713,6 @@ impl Step for Rustc {
         }
 
         build.run(&mut cargo);
-        cp_r(&my_out, &out);
     }
 }