From d3394685be76dd0853d4bb0d0cfea10f31b4a9db Mon Sep 17 00:00:00 2001
From: Andy Russell <arussell123@gmail.com>
Date: Wed, 23 Jan 2019 13:44:43 -0500
Subject: [PATCH 01/25] improve unused doc comment diagnostic reporting

Report all unused attributes on a given doc comment instead of just the
first one, and extend the span of sugared doc comments to encompass the
whole comment.
---
 src/librustc_lint/builtin.rs       | 41 +++++++++++++++++++++++-------
 src/test/ui/useless_comment.rs     |  8 +++++-
 src/test/ui/useless_comment.stderr | 24 +++++++++++++----
 3 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 925cde5b5cc8b..ef7be4d0b1848 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -799,27 +799,50 @@ impl LintPass for UnusedDocComment {
 }
 
 impl UnusedDocComment {
-    fn warn_if_doc<'a, 'tcx,
-                   I: Iterator<Item=&'a ast::Attribute>,
-                   C: LintContext<'tcx>>(&self, mut attrs: I, cx: &C) {
-        if let Some(attr) = attrs.find(|a| a.is_value_str() && a.check_name("doc")) {
-            cx.struct_span_lint(UNUSED_DOC_COMMENTS, attr.span, "doc comment not used by rustdoc")
-              .emit();
+    fn warn_if_doc(&self, cx: &EarlyContext<'_>, attrs: &[ast::Attribute]) {
+        let mut attrs = attrs.into_iter().peekable();
+
+        // Accumulate a single span for sugared doc comments.
+        let mut sugared_span: Option<Span> = None;
+
+        while let Some(attr) = attrs.next() {
+            if attr.is_sugared_doc {
+                sugared_span = Some(
+                    sugared_span.map_or_else(
+                        || attr.span,
+                        |span| span.with_hi(attr.span.hi()),
+                    ),
+                );
+            }
+
+            if attrs.peek().map(|next_attr| next_attr.is_sugared_doc).unwrap_or_default() {
+                continue;
+            }
+
+            let span = sugared_span.take().unwrap_or_else(|| attr.span);
+
+            if attr.name() == "doc" {
+                cx.struct_span_lint(
+                    UNUSED_DOC_COMMENTS,
+                    span,
+                    "doc comment not used by rustdoc",
+                ).emit();
+            }
         }
     }
 }
 
 impl EarlyLintPass for UnusedDocComment {
     fn check_local(&mut self, cx: &EarlyContext<'_>, decl: &ast::Local) {
-        self.warn_if_doc(decl.attrs.iter(), cx);
+        self.warn_if_doc(cx, &decl.attrs);
     }
 
     fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
-        self.warn_if_doc(arm.attrs.iter(), cx);
+        self.warn_if_doc(cx, &arm.attrs);
     }
 
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
-        self.warn_if_doc(expr.attrs.iter(), cx);
+        self.warn_if_doc(cx, &expr.attrs);
     }
 }
 
diff --git a/src/test/ui/useless_comment.rs b/src/test/ui/useless_comment.rs
index 531eec007fc48..e8a0e3c10d222 100644
--- a/src/test/ui/useless_comment.rs
+++ b/src/test/ui/useless_comment.rs
@@ -4,7 +4,9 @@ fn foo() {
     /// a //~ ERROR doc comment not used by rustdoc
     let x = 12;
 
-    /// b //~ doc comment not used by rustdoc
+    /// multi-line //~ doc comment not used by rustdoc
+    /// doc comment
+    /// that is unused
     match x {
         /// c //~ ERROR doc comment not used by rustdoc
         1 => {},
@@ -13,6 +15,10 @@ fn foo() {
 
     /// foo //~ ERROR doc comment not used by rustdoc
     unsafe {}
+
+    #[doc = "foo"] //~ ERROR doc comment not used by rustdoc
+    #[doc = "bar"] //~ ERROR doc comment not used by rustdoc
+    3;
 }
 
 fn main() {
diff --git a/src/test/ui/useless_comment.stderr b/src/test/ui/useless_comment.stderr
index cc818f6ce7c39..a284c08f47ace 100644
--- a/src/test/ui/useless_comment.stderr
+++ b/src/test/ui/useless_comment.stderr
@@ -13,20 +13,34 @@ LL | #![deny(unused_doc_comments)]
 error: doc comment not used by rustdoc
   --> $DIR/useless_comment.rs:7:5
    |
-LL |     /// b //~ doc comment not used by rustdoc
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | /     /// multi-line //~ doc comment not used by rustdoc
+LL | |     /// doc comment
+LL | |     /// that is unused
+   | |______________________^
 
 error: doc comment not used by rustdoc
-  --> $DIR/useless_comment.rs:9:9
+  --> $DIR/useless_comment.rs:11:9
    |
 LL |         /// c //~ ERROR doc comment not used by rustdoc
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: doc comment not used by rustdoc
-  --> $DIR/useless_comment.rs:14:5
+  --> $DIR/useless_comment.rs:16:5
    |
 LL |     /// foo //~ ERROR doc comment not used by rustdoc
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 4 previous errors
+error: doc comment not used by rustdoc
+  --> $DIR/useless_comment.rs:19:5
+   |
+LL |     #[doc = "foo"] //~ ERROR doc comment not used by rustdoc
+   |     ^^^^^^^^^^^^^^
+
+error: doc comment not used by rustdoc
+  --> $DIR/useless_comment.rs:20:5
+   |
+LL |     #[doc = "bar"] //~ ERROR doc comment not used by rustdoc
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
 

From b5fadf044ca96b602239633b929f2d14388c6b8c Mon Sep 17 00:00:00 2001
From: Andy Russell <arussell123@gmail.com>
Date: Thu, 24 Jan 2019 15:49:03 -0500
Subject: [PATCH 02/25] expand unused doc comment diagnostic

Report the diagnostic on macro expansions, and add a label indicating
why the comment is unused.
---
 src/libcore/num/mod.rs                        |  2 +-
 src/librustc/hir/mod.rs                       | 16 +--
 src/librustc/middle/region.rs                 | 35 ++++---
 src/librustc/ty/context.rs                    | 19 ++--
 src/librustc/ty/mod.rs                        | 70 ++++++-------
 src/librustc/ty/sty.rs                        | 78 +++++++--------
 src/librustc_data_structures/indexed_vec.rs   | 30 +++++-
 src/librustc_lint/builtin.rs                  | 53 +++++++---
 src/librustc_lint/lib.rs                      |  2 +-
 .../borrow_check/nll/region_infer/values.rs   |  6 +-
 .../nll/type_check/liveness/liveness_map.rs   |  8 +-
 src/librustc_mir/dataflow/move_paths/mod.rs   | 36 ++++---
 src/libstd/io/stdio.rs                        |  2 +-
 src/test/ui/useless_comment.rs                | 31 ++++--
 src/test/ui/useless_comment.stderr            | 98 ++++++++++++++-----
 15 files changed, 313 insertions(+), 173 deletions(-)

diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 6fb67ea9c9acb..1eda784d66be1 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -4617,7 +4617,7 @@ macro_rules! rev {
     )*}
 }
 
-/// intra-sign conversions
+// intra-sign conversions
 try_from_upper_bounded!(u16, u8);
 try_from_upper_bounded!(u32, u16, u8);
 try_from_upper_bounded!(u64, u32, u16, u8);
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index d7d56ef659afb..e9a4b19f7653d 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -115,15 +115,15 @@ impl serialize::UseSpecializedDecodable for HirId {
 // hack to ensure that we don't try to access the private parts of `ItemLocalId` in this module
 mod item_local_id_inner {
     use rustc_data_structures::indexed_vec::Idx;
-    /// An `ItemLocalId` uniquely identifies something within a given "item-like",
-    /// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
-    /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
-    /// the node's position within the owning item in any way, but there is a
-    /// guarantee that the `LocalItemId`s within an owner occupy a dense range of
-    /// integers starting at zero, so a mapping that maps all or most nodes within
-    /// an "item-like" to something else can be implement by a `Vec` instead of a
-    /// tree or hash map.
     newtype_index! {
+        /// An `ItemLocalId` uniquely identifies something within a given "item-like",
+        /// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
+        /// guarantee that the numerical value of a given `ItemLocalId` corresponds to
+        /// the node's position within the owning item in any way, but there is a
+        /// guarantee that the `LocalItemId`s within an owner occupy a dense range of
+        /// integers starting at zero, so a mapping that maps all or most nodes within
+        /// an "item-like" to something else can be implement by a `Vec` instead of a
+        /// tree or hash map.
         pub struct ItemLocalId { .. }
     }
 }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index fd188b33d7e1f..6527ed46cbc9e 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -132,25 +132,24 @@ pub enum ScopeData {
     Remainder(FirstStatementIndex)
 }
 
-/// Represents a subscope of `block` for a binding that is introduced
-/// by `block.stmts[first_statement_index]`. Such subscopes represent
-/// a suffix of the block. Note that each subscope does not include
-/// the initializer expression, if any, for the statement indexed by
-/// `first_statement_index`.
-///
-/// For example, given `{ let (a, b) = EXPR_1; let c = EXPR_2; ... }`:
-///
-/// * The subscope with `first_statement_index == 0` is scope of both
-///   `a` and `b`; it does not include EXPR_1, but does include
-///   everything after that first `let`. (If you want a scope that
-///   includes EXPR_1 as well, then do not use `Scope::Remainder`,
-///   but instead another `Scope` that encompasses the whole block,
-///   e.g., `Scope::Node`.
-///
-/// * The subscope with `first_statement_index == 1` is scope of `c`,
-///   and thus does not include EXPR_2, but covers the `...`.
-
 newtype_index! {
+    /// Represents a subscope of `block` for a binding that is introduced
+    /// by `block.stmts[first_statement_index]`. Such subscopes represent
+    /// a suffix of the block. Note that each subscope does not include
+    /// the initializer expression, if any, for the statement indexed by
+    /// `first_statement_index`.
+    ///
+    /// For example, given `{ let (a, b) = EXPR_1; let c = EXPR_2; ... }`:
+    ///
+    /// * The subscope with `first_statement_index == 0` is scope of both
+    ///   `a` and `b`; it does not include EXPR_1, but does include
+    ///   everything after that first `let`. (If you want a scope that
+    ///   includes EXPR_1 as well, then do not use `Scope::Remainder`,
+    ///   but instead another `Scope` that encompasses the whole block,
+    ///   e.g., `Scope::Node`.
+    ///
+    /// * The subscope with `first_statement_index == 1` is scope of `c`,
+    ///   and thus does not include EXPR_2, but covers the `...`.
     pub struct FirstStatementIndex { .. }
 }
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6bb3222512565..5313098bcc535 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1883,9 +1883,11 @@ pub mod tls {
         rayon_core::tlv::get()
     }
 
-    /// A thread local variable which stores a pointer to the current ImplicitCtxt
     #[cfg(not(parallel_compiler))]
-    thread_local!(static TLV: Cell<usize> = Cell::new(0));
+    thread_local!(
+        /// A thread local variable which stores a pointer to the current ImplicitCtxt
+        static TLV: Cell<usize> = Cell::new(0)
+    );
 
     /// Sets TLV to `value` during the call to `f`.
     /// It is restored to its previous value after.
@@ -2002,10 +2004,15 @@ pub mod tls {
         })
     }
 
-    /// Stores a pointer to the GlobalCtxt if one is available.
-    /// This is used to access the GlobalCtxt in the deadlock handler
-    /// given to Rayon.
-    scoped_thread_local!(pub static GCX_PTR: Lock<usize>);
+    scoped_thread_local! {
+        // FIXME: This should be a doc comment, but the macro does not allow attributes:
+        // https://github.com/alexcrichton/scoped-tls/pull/8
+        //
+        // Stores a pointer to the GlobalCtxt if one is available.
+        // This is used to access the GlobalCtxt in the deadlock handler
+        // given to Rayon.
+        pub static GCX_PTR: Lock<usize>
+    }
 
     /// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local.
     /// This is used in the deadlock handler.
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 02e4fb12af5c9..eed9c3ed7ef95 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1489,42 +1489,42 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
     }
 }
 
-/// "Universes" are used during type- and trait-checking in the
-/// presence of `for<..>` binders to control what sets of names are
-/// visible. Universes are arranged into a tree: the root universe
-/// contains names that are always visible. Each child then adds a new
-/// set of names that are visible, in addition to those of its parent.
-/// We say that the child universe "extends" the parent universe with
-/// new names.
-///
-/// To make this more concrete, consider this program:
-///
-/// ```
-/// struct Foo { }
-/// fn bar<T>(x: T) {
-///   let y: for<'a> fn(&'a u8, Foo) = ...;
-/// }
-/// ```
-///
-/// The struct name `Foo` is in the root universe U0. But the type
-/// parameter `T`, introduced on `bar`, is in an extended universe U1
-/// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
-/// of `bar`, we cannot name `T`. Then, within the type of `y`, the
-/// region `'a` is in a universe U2 that extends U1, because we can
-/// name it inside the fn type but not outside.
-///
-/// Universes are used to do type- and trait-checking around these
-/// "forall" binders (also called **universal quantification**). The
-/// idea is that when, in the body of `bar`, we refer to `T` as a
-/// type, we aren't referring to any type in particular, but rather a
-/// kind of "fresh" type that is distinct from all other types we have
-/// actually declared. This is called a **placeholder** type, and we
-/// use universes to talk about this. In other words, a type name in
-/// universe 0 always corresponds to some "ground" type that the user
-/// declared, but a type name in a non-zero universe is a placeholder
-/// type -- an idealized representative of "types in general" that we
-/// use for checking generic functions.
 newtype_index! {
+    /// "Universes" are used during type- and trait-checking in the
+    /// presence of `for<..>` binders to control what sets of names are
+    /// visible. Universes are arranged into a tree: the root universe
+    /// contains names that are always visible. Each child then adds a new
+    /// set of names that are visible, in addition to those of its parent.
+    /// We say that the child universe "extends" the parent universe with
+    /// new names.
+    ///
+    /// To make this more concrete, consider this program:
+    ///
+    /// ```
+    /// struct Foo { }
+    /// fn bar<T>(x: T) {
+    ///   let y: for<'a> fn(&'a u8, Foo) = ...;
+    /// }
+    /// ```
+    ///
+    /// The struct name `Foo` is in the root universe U0. But the type
+    /// parameter `T`, introduced on `bar`, is in an extended universe U1
+    /// -- i.e., within `bar`, we can name both `T` and `Foo`, but outside
+    /// of `bar`, we cannot name `T`. Then, within the type of `y`, the
+    /// region `'a` is in a universe U2 that extends U1, because we can
+    /// name it inside the fn type but not outside.
+    ///
+    /// Universes are used to do type- and trait-checking around these
+    /// "forall" binders (also called **universal quantification**). The
+    /// idea is that when, in the body of `bar`, we refer to `T` as a
+    /// type, we aren't referring to any type in particular, but rather a
+    /// kind of "fresh" type that is distinct from all other types we have
+    /// actually declared. This is called a **placeholder** type, and we
+    /// use universes to talk about this. In other words, a type name in
+    /// universe 0 always corresponds to some "ground" type that the user
+    /// declared, but a type name in a non-zero universe is a placeholder
+    /// type -- an idealized representative of "types in general" that we
+    /// use for checking generic functions.
     pub struct UniverseIndex {
         DEBUG_FORMAT = "U{}",
     }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 66efd2aea155a..8015b8ac09c4b 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1061,46 +1061,46 @@ impl<'a, 'gcx, 'tcx> ParamTy {
     }
 }
 
-/// A [De Bruijn index][dbi] is a standard means of representing
-/// regions (and perhaps later types) in a higher-ranked setting. In
-/// particular, imagine a type like this:
-///
-///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
-///     ^          ^            |        |         |
-///     |          |            |        |         |
-///     |          +------------+ 0      |         |
-///     |                                |         |
-///     +--------------------------------+ 1       |
-///     |                                          |
-///     +------------------------------------------+ 0
-///
-/// In this type, there are two binders (the outer fn and the inner
-/// fn). We need to be able to determine, for any given region, which
-/// fn type it is bound by, the inner or the outer one. There are
-/// various ways you can do this, but a De Bruijn index is one of the
-/// more convenient and has some nice properties. The basic idea is to
-/// count the number of binders, inside out. Some examples should help
-/// clarify what I mean.
-///
-/// Let's start with the reference type `&'b isize` that is the first
-/// argument to the inner function. This region `'b` is assigned a De
-/// Bruijn index of 0, meaning "the innermost binder" (in this case, a
-/// fn). The region `'a` that appears in the second argument type (`&'a
-/// isize`) would then be assigned a De Bruijn index of 1, meaning "the
-/// second-innermost binder". (These indices are written on the arrays
-/// in the diagram).
-///
-/// What is interesting is that De Bruijn index attached to a particular
-/// variable will vary depending on where it appears. For example,
-/// the final type `&'a char` also refers to the region `'a` declared on
-/// the outermost fn. But this time, this reference is not nested within
-/// any other binders (i.e., it is not an argument to the inner fn, but
-/// rather the outer one). Therefore, in this case, it is assigned a
-/// De Bruijn index of 0, because the innermost binder in that location
-/// is the outer fn.
-///
-/// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
 newtype_index! {
+    /// A [De Bruijn index][dbi] is a standard means of representing
+    /// regions (and perhaps later types) in a higher-ranked setting. In
+    /// particular, imagine a type like this:
+    ///
+    ///     for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
+    ///     ^          ^            |        |         |
+    ///     |          |            |        |         |
+    ///     |          +------------+ 0      |         |
+    ///     |                                |         |
+    ///     +--------------------------------+ 1       |
+    ///     |                                          |
+    ///     +------------------------------------------+ 0
+    ///
+    /// In this type, there are two binders (the outer fn and the inner
+    /// fn). We need to be able to determine, for any given region, which
+    /// fn type it is bound by, the inner or the outer one. There are
+    /// various ways you can do this, but a De Bruijn index is one of the
+    /// more convenient and has some nice properties. The basic idea is to
+    /// count the number of binders, inside out. Some examples should help
+    /// clarify what I mean.
+    ///
+    /// Let's start with the reference type `&'b isize` that is the first
+    /// argument to the inner function. This region `'b` is assigned a De
+    /// Bruijn index of 0, meaning "the innermost binder" (in this case, a
+    /// fn). The region `'a` that appears in the second argument type (`&'a
+    /// isize`) would then be assigned a De Bruijn index of 1, meaning "the
+    /// second-innermost binder". (These indices are written on the arrays
+    /// in the diagram).
+    ///
+    /// What is interesting is that De Bruijn index attached to a particular
+    /// variable will vary depending on where it appears. For example,
+    /// the final type `&'a char` also refers to the region `'a` declared on
+    /// the outermost fn. But this time, this reference is not nested within
+    /// any other binders (i.e., it is not an argument to the inner fn, but
+    /// rather the outer one). Therefore, in this case, it is assigned a
+    /// De Bruijn index of 0, because the innermost binder in that location
+    /// is the outer fn.
+    ///
+    /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
     pub struct DebruijnIndex {
         DEBUG_FORMAT = "DebruijnIndex({})",
         const INNERMOST = 0,
diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs
index 09aec50e4bb11..1153c3e79bfd5 100644
--- a/src/librustc_data_structures/indexed_vec.rs
+++ b/src/librustc_data_structures/indexed_vec.rs
@@ -58,9 +58,10 @@ macro_rules! newtype_index {
     // ---- public rules ----
 
     // Use default constants
-    ($v:vis struct $name:ident { .. }) => (
+    ($(#[$attrs:meta])* $v:vis struct $name:ident { .. }) => (
         newtype_index!(
             // Leave out derives marker so we can use its absence to ensure it comes first
+            @attrs        [$(#[$attrs])*]
             @type         [$name]
             // shave off 256 indices at the end to allow space for packing these indices into enums
             @max          [0xFFFF_FF00]
@@ -69,9 +70,10 @@ macro_rules! newtype_index {
     );
 
     // Define any constants
-    ($v:vis struct $name:ident { $($tokens:tt)+ }) => (
+    ($(#[$attrs:meta])* $v:vis struct $name:ident { $($tokens:tt)+ }) => (
         newtype_index!(
             // Leave out derives marker so we can use its absence to ensure it comes first
+            @attrs        [$(#[$attrs])*]
             @type         [$name]
             // shave off 256 indices at the end to allow space for packing these indices into enums
             @max          [0xFFFF_FF00]
@@ -84,10 +86,12 @@ macro_rules! newtype_index {
 
     // Base case, user-defined constants (if any) have already been defined
     (@derives      [$($derives:ident,)*]
+     @attrs        [$(#[$attrs:meta])*]
      @type         [$type:ident]
      @max          [$max:expr]
      @vis          [$v:vis]
      @debug_format [$debug_format:tt]) => (
+        $(#[$attrs])*
         #[derive(Copy, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)]
         #[rustc_layout_scalar_valid_range_end($max)]
         $v struct $type {
@@ -317,7 +321,8 @@ macro_rules! newtype_index {
 
     // By not including the @derives marker in this list nor in the default args, we can force it
     // to come first if it exists. When encodable isn't custom, add serialization traits by default.
-    (@type         [$type:ident]
+    (@attrs        [$(#[$attrs:meta])*]
+     @type         [$type:ident]
      @max          [$max:expr]
      @vis          [$v:vis]
      @debug_format [$debug_format:tt]
@@ -325,6 +330,7 @@ macro_rules! newtype_index {
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [$($derives,)+ RustcEncodable,]
+            @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
@@ -335,7 +341,8 @@ macro_rules! newtype_index {
 
     // The case where no derives are added, but encodable is overridden. Don't
     // derive serialization traits
-    (@type         [$type:ident]
+    (@attrs        [$(#[$attrs:meta])*]
+     @type         [$type:ident]
      @max          [$max:expr]
      @vis          [$v:vis]
      @debug_format [$debug_format:tt]
@@ -343,6 +350,7 @@ macro_rules! newtype_index {
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      []
+            @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
@@ -351,13 +359,15 @@ macro_rules! newtype_index {
     );
 
     // The case where no derives are added, add serialization derives by default
-    (@type         [$type:ident]
+    (@attrs        [$(#[$attrs:meta])*]
+     @type         [$type:ident]
      @max          [$max:expr]
      @vis          [$v:vis]
      @debug_format [$debug_format:tt]
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [RustcEncodable,]
+            @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
@@ -384,6 +394,7 @@ macro_rules! newtype_index {
 
     // Rewrite final without comma to one that includes comma
     (@derives      [$($derives:ident,)*]
+     @attrs        [$(#[$attrs:meta])*]
      @type         [$type:ident]
      @max          [$max:expr]
      @vis          [$v:vis]
@@ -391,6 +402,7 @@ macro_rules! newtype_index {
                    $name:ident = $constant:expr) => (
         newtype_index!(
             @derives      [$($derives,)*]
+            @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
@@ -400,6 +412,7 @@ macro_rules! newtype_index {
 
     // Rewrite final const without comma to one that includes comma
     (@derives      [$($derives:ident,)*]
+     @attrs        [$(#[$attrs:meta])*]
      @type         [$type:ident]
      @max          [$_max:expr]
      @vis          [$v:vis]
@@ -408,6 +421,7 @@ macro_rules! newtype_index {
                    const $name:ident = $constant:expr) => (
         newtype_index!(
             @derives      [$($derives,)*]
+            @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
@@ -417,6 +431,7 @@ macro_rules! newtype_index {
 
     // Replace existing default for max
     (@derives      [$($derives:ident,)*]
+     @attrs        [$(#[$attrs:meta])*]
      @type         [$type:ident]
      @max          [$_max:expr]
      @vis          [$v:vis]
@@ -425,6 +440,7 @@ macro_rules! newtype_index {
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [$($derives,)*]
+            @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
@@ -434,6 +450,7 @@ macro_rules! newtype_index {
 
     // Replace existing default for debug_format
     (@derives      [$($derives:ident,)*]
+     @attrs        [$(#[$attrs:meta])*]
      @type         [$type:ident]
      @max          [$max:expr]
      @vis          [$v:vis]
@@ -442,6 +459,7 @@ macro_rules! newtype_index {
                    $($tokens:tt)*) => (
         newtype_index!(
             @derives      [$($derives,)*]
+            @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
@@ -451,6 +469,7 @@ macro_rules! newtype_index {
 
     // Assign a user-defined constant
     (@derives      [$($derives:ident,)*]
+     @attrs        [$(#[$attrs:meta])*]
      @type         [$type:ident]
      @max          [$max:expr]
      @vis          [$v:vis]
@@ -462,6 +481,7 @@ macro_rules! newtype_index {
         pub const $name: $type = $type::from_u32_const($constant);
         newtype_index!(
             @derives      [$($derives,)*]
+            @attrs        [$(#[$attrs])*]
             @type         [$type]
             @max          [$max]
             @vis          [$v]
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index ef7be4d0b1848..531ec83e6c7d5 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -36,7 +36,7 @@ use syntax::tokenstream::{TokenTree, TokenStream};
 use syntax::ast;
 use syntax::ptr::P;
 use syntax::ast::Expr;
-use syntax::attr;
+use syntax::attr::{self, HasAttrs};
 use syntax::source_map::Spanned;
 use syntax::edition::Edition;
 use syntax::feature_gate::{AttributeGate, AttributeTemplate, AttributeType};
@@ -799,7 +799,14 @@ impl LintPass for UnusedDocComment {
 }
 
 impl UnusedDocComment {
-    fn warn_if_doc(&self, cx: &EarlyContext<'_>, attrs: &[ast::Attribute]) {
+    fn warn_if_doc(
+        &self,
+        cx: &EarlyContext<'_>,
+        node_span: Span,
+        node_kind: &str,
+        is_macro_expansion: bool,
+        attrs: &[ast::Attribute]
+    ) {
         let mut attrs = attrs.into_iter().peekable();
 
         // Accumulate a single span for sugared doc comments.
@@ -822,27 +829,51 @@ impl UnusedDocComment {
             let span = sugared_span.take().unwrap_or_else(|| attr.span);
 
             if attr.name() == "doc" {
-                cx.struct_span_lint(
-                    UNUSED_DOC_COMMENTS,
-                    span,
-                    "doc comment not used by rustdoc",
-                ).emit();
+                let mut err = cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, "unused doc comment");
+
+                err.span_label(
+                    node_span,
+                    format!("rustdoc does not generate documentation for {}", node_kind)
+                );
+
+                if is_macro_expansion {
+                    err.help("to document an item produced by a macro, \
+                              the macro must produce the documentation as part of its expansion");
+                }
+
+                err.emit();
             }
         }
     }
 }
 
 impl EarlyLintPass for UnusedDocComment {
-    fn check_local(&mut self, cx: &EarlyContext<'_>, decl: &ast::Local) {
-        self.warn_if_doc(cx, &decl.attrs);
+    fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
+        if let ast::ItemKind::Mac(..) = item.node {
+            self.warn_if_doc(cx, item.span, "macro expansions", true, &item.attrs);
+        }
+    }
+
+    fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
+        let (kind, is_macro_expansion) = match stmt.node {
+            ast::StmtKind::Local(..) => ("statements", false),
+            ast::StmtKind::Item(..) => ("inner items", false),
+            ast::StmtKind::Mac(..) => ("macro expansions", true),
+            // expressions will be reported by `check_expr`.
+            ast::StmtKind::Semi(..) |
+            ast::StmtKind::Expr(..) => return,
+        };
+
+        self.warn_if_doc(cx, stmt.span, kind, is_macro_expansion, stmt.node.attrs());
     }
 
     fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) {
-        self.warn_if_doc(cx, &arm.attrs);
+        let arm_span = arm.pats[0].span.with_hi(arm.body.span.hi());
+        self.warn_if_doc(cx, arm_span, "match arms", false, &arm.attrs);
     }
 
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
-        self.warn_if_doc(cx, &expr.attrs);
+        self.warn_if_doc(cx, expr.span, "expressions", false, &expr.attrs);
     }
 }
 
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 5c243e1389073..5e375dcaa0681 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -66,6 +66,7 @@ macro_rules! pre_expansion_lint_passes {
     ($macro:path, $args:tt) => (
         $macro!($args, [
             KeywordIdents: KeywordIdents,
+            UnusedDocComment: UnusedDocComment,
         ]);
     )
 }
@@ -77,7 +78,6 @@ macro_rules! early_lint_passes {
             UnusedImportBraces: UnusedImportBraces,
             UnsafeCode: UnsafeCode,
             AnonymousParameters: AnonymousParameters,
-            UnusedDocComment: UnusedDocComment,
             EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns,
             NonCamelCaseTypes: NonCamelCaseTypes,
             DeprecatedAttr: DeprecatedAttr::new(),
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
index ef27fdbde387f..49b83315ce6e6 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
@@ -116,14 +116,14 @@ impl RegionValueElements {
     }
 }
 
-/// A single integer representing a `Location` in the MIR control-flow
-/// graph. Constructed efficiently from `RegionValueElements`.
 newtype_index! {
+    /// A single integer representing a `Location` in the MIR control-flow
+    /// graph. Constructed efficiently from `RegionValueElements`.
     pub struct PointIndex { DEBUG_FORMAT = "PointIndex({})" }
 }
 
-/// A single integer representing a `ty::Placeholder`.
 newtype_index! {
+    /// A single integer representing a `ty::Placeholder`.
     pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" }
 }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs
index b9f9d83161b79..fe60f8471629f 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness/liveness_map.rs
@@ -85,10 +85,10 @@ impl NllLivenessMap {
     }
 }
 
-/// Index given to each local variable for which we need to
-/// compute liveness information. For many locals, we are able to
-/// skip liveness information: for example, those variables whose
-/// types contain no regions.
 newtype_index! {
+    /// Index given to each local variable for which we need to
+    /// compute liveness information. For many locals, we are able to
+    /// skip liveness information: for example, those variables whose
+    /// types contain no regions.
     pub struct LiveVar { .. }
 }
diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs
index efd979a7da4fb..07b93161e7218 100644
--- a/src/librustc_mir/dataflow/move_paths/mod.rs
+++ b/src/librustc_mir/dataflow/move_paths/mod.rs
@@ -23,7 +23,7 @@ pub(crate) mod indexes {
     use rustc_data_structures::indexed_vec::Idx;
 
     macro_rules! new_index {
-        ($Index:ident, $debug_name:expr) => {
+        ($(#[$attrs:meta])* $Index:ident, $debug_name:expr) => {
             #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
             pub struct $Index(NonZeroUsize);
 
@@ -44,17 +44,29 @@ pub(crate) mod indexes {
         }
     }
 
-    /// Index into MovePathData.move_paths
-    new_index!(MovePathIndex, "mp");
-
-    /// Index into MoveData.moves.
-    new_index!(MoveOutIndex, "mo");
-
-    /// Index into MoveData.inits.
-    new_index!(InitIndex, "in");
-
-    /// Index into Borrows.locations
-    new_index!(BorrowIndex, "bw");
+    new_index!(
+        /// Index into MovePathData.move_paths
+        MovePathIndex,
+        "mp"
+    );
+
+    new_index!(
+        /// Index into MoveData.moves.
+        MoveOutIndex,
+        "mo"
+    );
+
+    new_index!(
+        /// Index into MoveData.inits.
+        InitIndex,
+        "in"
+    );
+
+    new_index!(
+        /// Index into Borrows.locations
+        BorrowIndex,
+        "bw"
+    );
 }
 
 pub use self::indexes::MovePathIndex;
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index 4068c0f9c7de5..2ffaf4d8899ba 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -9,8 +9,8 @@ use sys::stdio;
 use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
 use thread::LocalKey;
 
-/// Stdout used by print! and println! macros
 thread_local! {
+    /// Stdout used by print! and println! macros
     static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = {
         RefCell::new(None)
     }
diff --git a/src/test/ui/useless_comment.rs b/src/test/ui/useless_comment.rs
index e8a0e3c10d222..7d2e5ab6f2b7f 100644
--- a/src/test/ui/useless_comment.rs
+++ b/src/test/ui/useless_comment.rs
@@ -1,24 +1,43 @@
+#![feature(stmt_expr_attributes)]
+
 #![deny(unused_doc_comments)]
 
+macro_rules! mac {
+    () => {}
+}
+
+/// foo //~ ERROR unused doc comment
+mac!();
+
 fn foo() {
-    /// a //~ ERROR doc comment not used by rustdoc
+    /// a //~ ERROR unused doc comment
     let x = 12;
 
-    /// multi-line //~ doc comment not used by rustdoc
+    /// multi-line //~ unused doc comment
     /// doc comment
     /// that is unused
     match x {
-        /// c //~ ERROR doc comment not used by rustdoc
+        /// c //~ ERROR unused doc comment
         1 => {},
         _ => {}
     }
 
-    /// foo //~ ERROR doc comment not used by rustdoc
+    /// foo //~ ERROR unused doc comment
     unsafe {}
 
-    #[doc = "foo"] //~ ERROR doc comment not used by rustdoc
-    #[doc = "bar"] //~ ERROR doc comment not used by rustdoc
+    #[doc = "foo"] //~ ERROR unused doc comment
+    #[doc = "bar"] //~ ERROR unused doc comment
     3;
+
+    /// bar //~ ERROR unused doc comment
+    mac!();
+
+    let x = /** comment */ 47; //~ ERROR unused doc comment
+
+    /// dox //~ ERROR unused doc comment
+    {
+
+    }
 }
 
 fn main() {
diff --git a/src/test/ui/useless_comment.stderr b/src/test/ui/useless_comment.stderr
index a284c08f47ace..0742a844b7f40 100644
--- a/src/test/ui/useless_comment.stderr
+++ b/src/test/ui/useless_comment.stderr
@@ -1,46 +1,98 @@
-error: doc comment not used by rustdoc
-  --> $DIR/useless_comment.rs:4:5
+error: unused doc comment
+  --> $DIR/useless_comment.rs:9:1
    |
-LL |     /// a //~ ERROR doc comment not used by rustdoc
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | /// foo //~ ERROR unused doc comment
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | mac!();
+   | ------- rustdoc does not generate documentation for macro expansions
    |
 note: lint level defined here
-  --> $DIR/useless_comment.rs:1:9
+  --> $DIR/useless_comment.rs:3:9
    |
 LL | #![deny(unused_doc_comments)]
    |         ^^^^^^^^^^^^^^^^^^^
+   = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
 
-error: doc comment not used by rustdoc
-  --> $DIR/useless_comment.rs:7:5
+error: unused doc comment
+  --> $DIR/useless_comment.rs:13:5
    |
-LL | /     /// multi-line //~ doc comment not used by rustdoc
+LL |     /// a //~ ERROR unused doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     let x = 12;
+   |     ----------- rustdoc does not generate documentation for statements
+
+error: unused doc comment
+  --> $DIR/useless_comment.rs:16:5
+   |
+LL | /     /// multi-line //~ unused doc comment
 LL | |     /// doc comment
 LL | |     /// that is unused
    | |______________________^
+LL | /     match x {
+LL | |         /// c //~ ERROR unused doc comment
+LL | |         1 => {},
+LL | |         _ => {}
+LL | |     }
+   | |_____- rustdoc does not generate documentation for expressions
 
-error: doc comment not used by rustdoc
-  --> $DIR/useless_comment.rs:11:9
+error: unused doc comment
+  --> $DIR/useless_comment.rs:20:9
    |
-LL |         /// c //~ ERROR doc comment not used by rustdoc
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         /// c //~ ERROR unused doc comment
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         1 => {},
+   |         ------- rustdoc does not generate documentation for match arms
 
-error: doc comment not used by rustdoc
-  --> $DIR/useless_comment.rs:16:5
+error: unused doc comment
+  --> $DIR/useless_comment.rs:25:5
    |
-LL |     /// foo //~ ERROR doc comment not used by rustdoc
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     /// foo //~ ERROR unused doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     unsafe {}
+   |     --------- rustdoc does not generate documentation for expressions
 
-error: doc comment not used by rustdoc
-  --> $DIR/useless_comment.rs:19:5
+error: unused doc comment
+  --> $DIR/useless_comment.rs:28:5
    |
-LL |     #[doc = "foo"] //~ ERROR doc comment not used by rustdoc
+LL |     #[doc = "foo"] //~ ERROR unused doc comment
    |     ^^^^^^^^^^^^^^
+LL |     #[doc = "bar"] //~ ERROR unused doc comment
+LL |     3;
+   |     - rustdoc does not generate documentation for expressions
 
-error: doc comment not used by rustdoc
-  --> $DIR/useless_comment.rs:20:5
+error: unused doc comment
+  --> $DIR/useless_comment.rs:29:5
    |
-LL |     #[doc = "bar"] //~ ERROR doc comment not used by rustdoc
+LL |     #[doc = "bar"] //~ ERROR unused doc comment
    |     ^^^^^^^^^^^^^^
+LL |     3;
+   |     - rustdoc does not generate documentation for expressions
+
+error: unused doc comment
+  --> $DIR/useless_comment.rs:32:5
+   |
+LL |     /// bar //~ ERROR unused doc comment
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     mac!();
+   |     ------- rustdoc does not generate documentation for macro expansions
+   |
+   = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
+
+error: unused doc comment
+  --> $DIR/useless_comment.rs:35:13
+   |
+LL |     let x = /** comment */ 47; //~ ERROR unused doc comment
+   |             ^^^^^^^^^^^^^^ -- rustdoc does not generate documentation for expressions
+
+error: unused doc comment
+  --> $DIR/useless_comment.rs:37:5
+   |
+LL |       /// dox //~ ERROR unused doc comment
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | /     {
+LL | |
+LL | |     }
+   | |_____- rustdoc does not generate documentation for expressions
 
-error: aborting due to 6 previous errors
+error: aborting due to 10 previous errors
 

From 890ef48eb93c42e8a6c5535a6aefa02291b93b2d Mon Sep 17 00:00:00 2001
From: varkor <github@varkor.com>
Date: Sat, 23 Feb 2019 18:57:25 +0000
Subject: [PATCH 03/25] Fix an indexing error when using `x.py help`

---
 src/bootstrap/bootstrap.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 119b38bcc99dc..c98d8b8ecf437 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -830,7 +830,7 @@ def main():
 
     # x.py help <cmd> ...
     if len(sys.argv) > 1 and sys.argv[1] == 'help':
-        sys.argv = sys.argv[:1] + [sys.argv[2], '-h'] + sys.argv[3:]
+        sys.argv = [sys.argv[0], '-h'] + sys.argv[2:]
 
     help_triggered = (
         '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)

From 906ec8acce8126172df758e7e7f400429c3489dc Mon Sep 17 00:00:00 2001
From: Andy Russell <arussell123@gmail.com>
Date: Wed, 20 Feb 2019 16:20:01 -0500
Subject: [PATCH 04/25] move collapse and unindent docs passes earlier

---
 src/librustdoc/passes/collapse_docs.rs        |  5 +++--
 src/librustdoc/passes/mod.rs                  | 20 +++++++++----------
 src/librustdoc/passes/unindent_comments.rs    |  5 +++--
 .../rustdoc-ui/intra-links-warning.stderr     |  4 ++--
 src/test/rustdoc-ui/issue-58473-2.rs          | 12 +++++++++++
 src/test/rustdoc-ui/issue-58473.rs            | 10 ++++++++++
 6 files changed, 40 insertions(+), 16 deletions(-)
 create mode 100644 src/test/rustdoc-ui/issue-58473-2.rs
 create mode 100644 src/test/rustdoc-ui/issue-58473.rs

diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs
index e5e60cbe71700..399f8261d21ec 100644
--- a/src/librustdoc/passes/collapse_docs.rs
+++ b/src/librustdoc/passes/collapse_docs.rs
@@ -1,4 +1,5 @@
 use crate::clean::{self, DocFragment, Item};
+use crate::core::DocContext;
 use crate::fold;
 use crate::fold::{DocFolder};
 use crate::passes::Pass;
@@ -6,7 +7,7 @@ use crate::passes::Pass;
 use std::mem::replace;
 
 pub const COLLAPSE_DOCS: Pass =
-    Pass::late("collapse-docs", collapse_docs,
+    Pass::early("collapse-docs", collapse_docs,
         "concatenates all document attributes into one document attribute");
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -26,7 +27,7 @@ impl DocFragment {
     }
 }
 
-pub fn collapse_docs(krate: clean::Crate) -> clean::Crate {
+pub fn collapse_docs(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
     Collapser.fold_crate(krate)
 }
 
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 4d7fef7a76a9f..db2bb89843848 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -141,27 +141,27 @@ pub const PASSES: &'static [Pass] = &[
 ];
 
 /// The list of passes run by default.
-pub const DEFAULT_PASSES: &'static [&'static str] = &[
+pub const DEFAULT_PASSES: &[&str] = &[
     "collect-trait-impls",
+    "collapse-docs",
+    "unindent-comments",
     "check-private-items-doc-tests",
     "strip-hidden",
     "strip-private",
     "collect-intra-doc-links",
     "check-code-block-syntax",
-    "collapse-docs",
-    "unindent-comments",
     "propagate-doc-cfg",
 ];
 
 /// The list of default passes run with `--document-private-items` is passed to rustdoc.
-pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[
+pub const DEFAULT_PRIVATE_PASSES: &[&str] = &[
     "collect-trait-impls",
+    "collapse-docs",
+    "unindent-comments",
     "check-private-items-doc-tests",
     "strip-priv-imports",
     "collect-intra-doc-links",
     "check-code-block-syntax",
-    "collapse-docs",
-    "unindent-comments",
     "propagate-doc-cfg",
 ];
 
@@ -438,11 +438,11 @@ crate fn source_span_for_markdown_range(
         .span_to_snippet(span_of_attrs(attrs))
         .ok()?;
 
-    let starting_line = markdown[..md_range.start].lines().count() - 1;
-    let ending_line = markdown[..md_range.end].lines().count() - 1;
+    let starting_line = markdown[..md_range.start].matches('\n').count();
+    let ending_line = starting_line + markdown[md_range.start..md_range.end].matches('\n').count();
 
-    // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we only
-    // we can treat CRLF and LF line endings the same way.
+    // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we treat
+    // CRLF and LF line endings the same way.
     let mut src_lines = snippet.split_terminator('\n');
     let md_lines = markdown.split_terminator('\n');
 
diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs
index 269e4cbe65f8b..c32c3556a5728 100644
--- a/src/librustdoc/passes/unindent_comments.rs
+++ b/src/librustdoc/passes/unindent_comments.rs
@@ -3,14 +3,15 @@ use std::string::String;
 use std::usize;
 
 use crate::clean::{self, DocFragment, Item};
+use crate::core::DocContext;
 use crate::fold::{self, DocFolder};
 use crate::passes::Pass;
 
 pub const UNINDENT_COMMENTS: Pass =
-    Pass::late("unindent-comments", unindent_comments,
+    Pass::early("unindent-comments", unindent_comments,
         "removes excess indentation on comments in order for markdown to like it");
 
-pub fn unindent_comments(krate: clean::Crate) -> clean::Crate {
+pub fn unindent_comments(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
     CommentCleaner.fold_crate(krate)
 }
 
diff --git a/src/test/rustdoc-ui/intra-links-warning.stderr b/src/test/rustdoc-ui/intra-links-warning.stderr
index e5409c042056c..60fc131dbda17 100644
--- a/src/test/rustdoc-ui/intra-links-warning.stderr
+++ b/src/test/rustdoc-ui/intra-links-warning.stderr
@@ -105,8 +105,8 @@ LL | | /// [error]
    |
    = note: the link appears in this line:
            
-            [error]
-             ^^^^^
+           [error]
+            ^^^^^
    = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
 
 warning: `[error1]` cannot be resolved, ignoring it...
diff --git a/src/test/rustdoc-ui/issue-58473-2.rs b/src/test/rustdoc-ui/issue-58473-2.rs
new file mode 100644
index 0000000000000..5e5ddebe10884
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-58473-2.rs
@@ -0,0 +1,12 @@
+// compile-pass
+
+#![deny(private_doc_tests)]
+
+mod foo {
+    /**
+    Does nothing, returns `()`
+
+    yadda-yadda-yadda
+    */
+    fn foo() {}
+}
diff --git a/src/test/rustdoc-ui/issue-58473.rs b/src/test/rustdoc-ui/issue-58473.rs
new file mode 100644
index 0000000000000..0e5be3292c053
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-58473.rs
@@ -0,0 +1,10 @@
+// compile-pass
+
+pub trait Foo {
+    /**
+    Does nothing, returns `()`
+
+    yadda-yadda-yadda
+    */
+    fn foo() {}
+}

From 1536852b428b56a13a3026354db72e0b83c83652 Mon Sep 17 00:00:00 2001
From: Andy Russell <arussell123@gmail.com>
Date: Sat, 23 Feb 2019 15:10:56 -0500
Subject: [PATCH 05/25] merge early and late passes into single struct

---
 src/librustdoc/config.rs                      |  2 +-
 src/librustdoc/core.rs                        |  8 +-
 src/librustdoc/lib.rs                         | 22 -----
 .../passes/check_code_block_syntax.rs         |  8 +-
 src/librustdoc/passes/collapse_docs.rs        |  8 +-
 .../passes/collect_intra_doc_links.rs         |  8 +-
 src/librustdoc/passes/collect_trait_impls.rs  |  8 +-
 src/librustdoc/passes/mod.rs                  | 89 ++-----------------
 .../passes/private_items_doc_tests.rs         |  9 +-
 src/librustdoc/passes/propagate_doc_cfg.rs    | 11 ++-
 src/librustdoc/passes/strip_hidden.rs         |  8 +-
 src/librustdoc/passes/strip_priv_imports.rs   |  7 +-
 src/librustdoc/passes/strip_private.rs        | 10 ++-
 src/librustdoc/passes/unindent_comments.rs    |  8 +-
 14 files changed, 68 insertions(+), 138 deletions(-)

diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index e5caf7fdfa235..b1c53ea92b300 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -214,7 +214,7 @@ impl Options {
         if matches.opt_strs("passes") == ["list"] {
             println!("Available passes for running rustdoc:");
             for pass in passes::PASSES {
-                println!("{:>20} - {}", pass.name(), pass.description());
+                println!("{:>20} - {}", pass.name, pass.description);
             }
             println!("\nDefault passes for rustdoc:");
             for &name in passes::DEFAULT_PASSES {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 4f70751c90537..bf95cde163fc3 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -606,10 +606,12 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt
                 passes::defaults(default_passes).iter().map(|p| p.to_string()).collect();
             passes.extend(manual_passes);
 
+            info!("Executing passes");
+
             for pass in &passes {
-                // the "unknown pass" error will be reported when late passes are run
-                if let Some(pass) = passes::find_pass(pass).and_then(|p| p.early_fn()) {
-                    krate = pass(krate, &ctxt);
+                match passes::find_pass(pass).map(|p| p.pass) {
+                    Some(pass) => krate = pass(krate, &ctxt),
+                    None => error!("unknown pass {}, skipping", *pass),
                 }
             }
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 5e9f9ee9f80af..39e504951d1c6 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -441,28 +441,6 @@ where R: 'static + Send,
 
         krate.version = crate_version;
 
-        info!("Executing passes");
-
-        for pass in &passes {
-            // determine if we know about this pass
-            let pass = match passes::find_pass(pass) {
-                Some(pass) => if let Some(pass) = pass.late_fn() {
-                    pass
-                } else {
-                    // not a late pass, but still valid so don't report the error
-                    continue
-                }
-                None => {
-                    error!("unknown pass {}, skipping", *pass);
-
-                    continue
-                },
-            };
-
-            // run it
-            krate = pass(krate);
-        }
-
         tx.send(f(Output {
             krate: krate,
             renderinfo: renderinfo,
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index f960374370e04..88d9c87c52898 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -10,9 +10,11 @@ use crate::fold::DocFolder;
 use crate::html::markdown::{self, RustCodeBlock};
 use crate::passes::Pass;
 
-pub const CHECK_CODE_BLOCK_SYNTAX: Pass =
-    Pass::early("check-code-block-syntax", check_code_block_syntax,
-                "validates syntax inside Rust code blocks");
+pub const CHECK_CODE_BLOCK_SYNTAX: Pass = Pass {
+    name: "check-code-block-syntax",
+    pass: check_code_block_syntax,
+    description: "validates syntax inside Rust code blocks",
+};
 
 pub fn check_code_block_syntax(krate: clean::Crate, cx: &DocContext<'_, '_, '_>) -> clean::Crate {
     SyntaxChecker { cx }.fold_crate(krate)
diff --git a/src/librustdoc/passes/collapse_docs.rs b/src/librustdoc/passes/collapse_docs.rs
index 399f8261d21ec..088a6ea77c73f 100644
--- a/src/librustdoc/passes/collapse_docs.rs
+++ b/src/librustdoc/passes/collapse_docs.rs
@@ -6,9 +6,11 @@ use crate::passes::Pass;
 
 use std::mem::replace;
 
-pub const COLLAPSE_DOCS: Pass =
-    Pass::early("collapse-docs", collapse_docs,
-        "concatenates all document attributes into one document attribute");
+pub const COLLAPSE_DOCS: Pass = Pass {
+    name: "collapse-docs",
+    pass: collapse_docs,
+    description: "concatenates all document attributes into one document attribute",
+};
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum DocFragmentKind {
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index cf2c3aa484600..532bb96445105 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -18,9 +18,11 @@ use crate::passes::{look_for_tests, Pass};
 
 use super::span_of_attrs;
 
-pub const COLLECT_INTRA_DOC_LINKS: Pass =
-    Pass::early("collect-intra-doc-links", collect_intra_doc_links,
-                "reads a crate's documentation to resolve intra-doc-links");
+pub const COLLECT_INTRA_DOC_LINKS: Pass = Pass {
+    name: "collect-intra-doc-links",
+    pass: collect_intra_doc_links,
+    description: "reads a crate's documentation to resolve intra-doc-links",
+};
 
 pub fn collect_intra_doc_links(krate: Crate, cx: &DocContext<'_, '_, '_>) -> Crate {
     if !UnstableFeatures::from_environment().is_nightly_build() {
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 903cce3bc032a..4c90540871d2e 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -6,9 +6,11 @@ use super::Pass;
 use rustc::util::nodemap::FxHashSet;
 use rustc::hir::def_id::DefId;
 
-pub const COLLECT_TRAIT_IMPLS: Pass =
-    Pass::early("collect-trait-impls", collect_trait_impls,
-                "retrieves trait impls for items in the crate");
+pub const COLLECT_TRAIT_IMPLS: Pass = Pass {
+    name: "collect-trait-impls",
+    pass: collect_trait_impls,
+    description: "retrieves trait impls for items in the crate",
+};
 
 pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_, '_, '_>) -> Crate {
     let mut synth = SyntheticImplCollector::new(cx);
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index db2bb89843848..3a9d8ef20ce84 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -6,7 +6,6 @@ use rustc::lint as lint;
 use rustc::middle::privacy::AccessLevels;
 use rustc::util::nodemap::DefIdSet;
 use std::mem;
-use std::fmt;
 use syntax::ast::NodeId;
 use syntax_pos::{DUMMY_SP, Span};
 use std::ops::Range;
@@ -46,84 +45,14 @@ pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
 mod check_code_block_syntax;
 pub use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX;
 
-/// Represents a single pass.
+/// A single pass over the cleaned documentation.
+///
+/// Runs in the compiler context, so it has access to types and traits and the like.
 #[derive(Copy, Clone)]
-pub enum Pass {
-    /// An "early pass" is run in the compiler context, and can gather information about types and
-    /// traits and the like.
-    EarlyPass {
-        name: &'static str,
-        pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
-        description: &'static str,
-    },
-    /// A "late pass" is run between crate cleaning and page generation.
-    LatePass {
-        name: &'static str,
-        pass: fn(clean::Crate) -> clean::Crate,
-        description: &'static str,
-    },
-}
-
-impl fmt::Debug for Pass {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut dbg = match *self {
-            Pass::EarlyPass { .. } => f.debug_struct("EarlyPass"),
-            Pass::LatePass { .. } => f.debug_struct("LatePass"),
-        };
-
-        dbg.field("name", &self.name())
-           .field("pass", &"...")
-           .field("description", &self.description())
-           .finish()
-    }
-}
-
-impl Pass {
-    /// Constructs a new early pass.
-    pub const fn early(name: &'static str,
-                       pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
-                       description: &'static str) -> Pass {
-        Pass::EarlyPass { name, pass, description }
-    }
-
-    /// Constructs a new late pass.
-    pub const fn late(name: &'static str,
-                      pass: fn(clean::Crate) -> clean::Crate,
-                      description: &'static str) -> Pass {
-        Pass::LatePass { name, pass, description }
-    }
-
-    /// Returns the name of this pass.
-    pub fn name(self) -> &'static str {
-        match self {
-            Pass::EarlyPass { name, .. } |
-                Pass::LatePass { name, .. } => name,
-        }
-    }
-
-    /// Returns the description of this pass.
-    pub fn description(self) -> &'static str {
-        match self {
-            Pass::EarlyPass { description, .. } |
-                Pass::LatePass { description, .. } => description,
-        }
-    }
-
-    /// If this pass is an early pass, returns the pointer to its function.
-    pub fn early_fn(self) -> Option<fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate> {
-        match self {
-            Pass::EarlyPass { pass, .. } => Some(pass),
-            _ => None,
-        }
-    }
-
-    /// If this pass is a late pass, returns the pointer to its function.
-    pub fn late_fn(self) -> Option<fn(clean::Crate) -> clean::Crate> {
-        match self {
-            Pass::LatePass { pass, .. } => Some(pass),
-            _ => None,
-        }
-    }
+pub struct Pass {
+    pub name: &'static str,
+    pub pass: fn(clean::Crate, &DocContext<'_, '_, '_>) -> clean::Crate,
+    pub description: &'static str,
 }
 
 /// The full list of passes.
@@ -184,8 +113,8 @@ pub fn defaults(default_set: DefaultPassOption) -> &'static [&'static str] {
 }
 
 /// If the given name matches a known pass, returns its information.
-pub fn find_pass(pass_name: &str) -> Option<Pass> {
-    PASSES.iter().find(|p| p.name() == pass_name).cloned()
+pub fn find_pass(pass_name: &str) -> Option<&'static Pass> {
+    PASSES.iter().find(|p| p.name == pass_name)
 }
 
 struct Stripper<'a> {
diff --git a/src/librustdoc/passes/private_items_doc_tests.rs b/src/librustdoc/passes/private_items_doc_tests.rs
index 819d15f65e8ef..1c3977c4f85cd 100644
--- a/src/librustdoc/passes/private_items_doc_tests.rs
+++ b/src/librustdoc/passes/private_items_doc_tests.rs
@@ -3,10 +3,11 @@ use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::passes::{look_for_tests, Pass};
 
-
-pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass =
-    Pass::early("check-private-items-doc-tests", check_private_items_doc_tests,
-                "check private items doc tests");
+pub const CHECK_PRIVATE_ITEMS_DOC_TESTS: Pass = Pass {
+    name: "check-private-items-doc-tests",
+    pass: check_private_items_doc_tests,
+    description: "check private items doc tests",
+};
 
 struct PrivateItemDocTestLinter<'a, 'tcx: 'a, 'rcx: 'a> {
     cx: &'a DocContext<'a, 'tcx, 'rcx>,
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 9ba0b22728691..aed80b5ba86fd 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -2,14 +2,17 @@ use std::sync::Arc;
 
 use crate::clean::{Crate, Item};
 use crate::clean::cfg::Cfg;
+use crate::core::DocContext;
 use crate::fold::DocFolder;
 use crate::passes::Pass;
 
-pub const PROPAGATE_DOC_CFG: Pass =
-    Pass::late("propagate-doc-cfg", propagate_doc_cfg,
-        "propagates `#[doc(cfg(...))]` to child items");
+pub const PROPAGATE_DOC_CFG: Pass = Pass {
+    name: "propagate-doc-cfg",
+    pass: propagate_doc_cfg,
+    description: "propagates `#[doc(cfg(...))]` to child items",
+};
 
-pub fn propagate_doc_cfg(cr: Crate) -> Crate {
+pub fn propagate_doc_cfg(cr: Crate, _: &DocContext<'_, '_, '_>) -> Crate {
     CfgPropagator { parent_cfg: None }.fold_crate(cr)
 }
 
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index b3d50e06816c5..330057e53843b 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -7,9 +7,11 @@ use crate::core::DocContext;
 use crate::fold::{DocFolder, StripItem};
 use crate::passes::{ImplStripper, Pass};
 
-pub const STRIP_HIDDEN: Pass =
-    Pass::early("strip-hidden", strip_hidden,
-                "strips all doc(hidden) items from the output");
+pub const STRIP_HIDDEN: Pass = Pass {
+    name: "strip-hidden",
+    pass: strip_hidden,
+    description: "strips all doc(hidden) items from the output",
+};
 
 /// Strip items marked `#[doc(hidden)]`
 pub fn strip_hidden(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
diff --git a/src/librustdoc/passes/strip_priv_imports.rs b/src/librustdoc/passes/strip_priv_imports.rs
index 3af1403e8749c..479f0877bd7d2 100644
--- a/src/librustdoc/passes/strip_priv_imports.rs
+++ b/src/librustdoc/passes/strip_priv_imports.rs
@@ -3,8 +3,11 @@ use crate::fold::{DocFolder};
 use crate::core::DocContext;
 use crate::passes::{ImportStripper, Pass};
 
-pub const STRIP_PRIV_IMPORTS: Pass = Pass::early("strip-priv-imports", strip_priv_imports,
-     "strips all private import statements (`use`, `extern crate`) from a crate");
+pub const STRIP_PRIV_IMPORTS: Pass = Pass {
+    name: "strip-priv-imports",
+    pass: strip_priv_imports,
+    description: "strips all private import statements (`use`, `extern crate`) from a crate",
+};
 
 pub fn strip_priv_imports(krate: clean::Crate, _: &DocContext<'_, '_, '_>)  -> clean::Crate {
     ImportStripper.fold_crate(krate)
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index e553d792eb697..1ac3a90f38d35 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -5,10 +5,12 @@ use crate::fold::{DocFolder};
 use crate::core::DocContext;
 use crate::passes::{ImplStripper, ImportStripper, Stripper, Pass};
 
-pub const STRIP_PRIVATE: Pass =
-    Pass::early("strip-private", strip_private,
-        "strips all private items from a crate which cannot be seen externally, \
-         implies strip-priv-imports");
+pub const STRIP_PRIVATE: Pass = Pass {
+    name: "strip-private",
+    pass: strip_private,
+    description: "strips all private items from a crate which cannot be seen externally, \
+        implies strip-priv-imports",
+};
 
 /// Strip private items from the point of view of a crate or externally from a
 /// crate, specified by the `xcrate` flag.
diff --git a/src/librustdoc/passes/unindent_comments.rs b/src/librustdoc/passes/unindent_comments.rs
index c32c3556a5728..b77cf68d7c63f 100644
--- a/src/librustdoc/passes/unindent_comments.rs
+++ b/src/librustdoc/passes/unindent_comments.rs
@@ -7,9 +7,11 @@ use crate::core::DocContext;
 use crate::fold::{self, DocFolder};
 use crate::passes::Pass;
 
-pub const UNINDENT_COMMENTS: Pass =
-    Pass::early("unindent-comments", unindent_comments,
-        "removes excess indentation on comments in order for markdown to like it");
+pub const UNINDENT_COMMENTS: Pass = Pass {
+    name: "unindent-comments",
+    pass: unindent_comments,
+    description: "removes excess indentation on comments in order for markdown to like it",
+};
 
 pub fn unindent_comments(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
     CommentCleaner.fold_crate(krate)

From 8300f51936149ec43eb063205e4d03c54a308f3c Mon Sep 17 00:00:00 2001
From: Nathan Corbyn <me@nathancorbyn.com>
Date: Sat, 23 Feb 2019 18:39:27 +0000
Subject: [PATCH 06/25] Deny `async fn` in 2015 edition

Fix style issues and update diagnostic messages

Update src/librustc_passes/diagnostics.rs

Co-Authored-By: doctorn <me@nathancorbyn.com>

Deny nested `async fn` in Rust 2015 edition

Deny nested `async fn` in Rust 2015 edition

Deny nested `async fn` in Rust 2015 edition
---
 src/librustc/hir/lowering.rs                  | 10 ++--
 src/librustc/hir/map/def_collector.rs         | 10 ++--
 src/librustc_passes/ast_validation.rs         | 14 ++++-
 src/librustc_passes/diagnostics.rs            | 12 ++++
 src/librustc_resolve/lib.rs                   |  4 +-
 src/librustc_save_analysis/sig.rs             |  4 +-
 src/libsyntax/ast.rs                          |  4 +-
 src/libsyntax/ext/build.rs                    |  2 +-
 src/libsyntax/feature_gate.rs                 |  2 +-
 src/libsyntax/mut_visit.rs                    |  2 +-
 src/libsyntax/parse/parser.rs                 | 39 +++++++++----
 src/libsyntax/print/pprust.rs                 |  4 +-
 src/libsyntax/visit.rs                        | 15 +++--
 src/libsyntax_ext/test.rs                     |  2 +-
 .../editions/edition-deny-async-fns-2015.rs   | 34 +++++++++++
 .../edition-deny-async-fns-2015.stderr        | 58 +++++++++++++++++++
 .../feature-gate-async-await-2015-edition.rs  |  3 +-
 ...ature-gate-async-await-2015-edition.stderr | 16 +++--
 .../recursive-async-impl-trait-type.rs        | 11 ++++
 .../recursive-async-impl-trait-type.stderr    | 11 ++++
 .../impl-trait/recursive-impl-trait-type.rs   |  6 +-
 .../recursive-impl-trait-type.stderr          | 14 +----
 22 files changed, 215 insertions(+), 62 deletions(-)
 create mode 100644 src/test/ui/editions/edition-deny-async-fns-2015.rs
 create mode 100644 src/test/ui/editions/edition-deny-async-fns-2015.stderr
 create mode 100644 src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
 create mode 100644 src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr

diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index f6b68682886e7..f65bd255ba66e 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -2906,7 +2906,7 @@ impl<'a> LoweringContext<'a> {
                     // `impl Future<Output = T>` here because lower_body
                     // only cares about the input argument patterns in the function
                     // declaration (decl), not the return types.
-                    let body_id = this.lower_async_body(decl, header.asyncness, body);
+                    let body_id = this.lower_async_body(decl, header.asyncness.node, body);
 
                     let (generics, fn_decl) = this.add_in_band_defs(
                         generics,
@@ -2916,7 +2916,7 @@ impl<'a> LoweringContext<'a> {
                             decl,
                             Some((fn_def_id, idty)),
                             true,
-                            header.asyncness.opt_return_id()
+                            header.asyncness.node.opt_return_id()
                         ),
                     );
 
@@ -3410,14 +3410,14 @@ impl<'a> LoweringContext<'a> {
                 )
             }
             ImplItemKind::Method(ref sig, ref body) => {
-                let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness, body);
+                let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness.node, body);
                 let impl_trait_return_allow = !self.is_in_trait_impl;
                 let (generics, sig) = self.lower_method_sig(
                     &i.generics,
                     sig,
                     impl_item_def_id,
                     impl_trait_return_allow,
-                    sig.header.asyncness.opt_return_id(),
+                    sig.header.asyncness.node.opt_return_id(),
                 );
                 (generics, hir::ImplItemKind::Method(sig, body_id))
             }
@@ -3637,7 +3637,7 @@ impl<'a> LoweringContext<'a> {
     fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
         hir::FnHeader {
             unsafety: self.lower_unsafety(h.unsafety),
-            asyncness: self.lower_asyncness(h.asyncness),
+            asyncness: self.lower_asyncness(h.asyncness.node),
             constness: self.lower_constness(h.constness),
             abi: h.abi,
         }
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index 72aa9570cc2ff..12760f8b9828b 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -73,7 +73,7 @@ impl<'a> DefCollector<'a> {
         decl: &'a FnDecl,
         body: &'a Block,
     ) {
-        let (closure_id, return_impl_trait_id) = match header.asyncness {
+        let (closure_id, return_impl_trait_id) = match header.asyncness.node {
             IsAsync::Async {
                 closure_id,
                 return_impl_trait_id,
@@ -129,10 +129,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             }
             ItemKind::Fn(
                 ref decl,
-                ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
+                ref header,
                 ref generics,
                 ref body,
-            ) => {
+            ) if header.asyncness.node.is_async() => {
                 return self.visit_async_fn(
                     i.id,
                     i.ident.name,
@@ -242,9 +242,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
     fn visit_impl_item(&mut self, ii: &'a ImplItem) {
         let def_data = match ii.node {
             ImplItemKind::Method(MethodSig {
-                header: ref header @ FnHeader { asyncness: IsAsync::Async { .. }, .. },
+                ref header,
                 ref decl,
-            }, ref body) => {
+            }, ref body) if header.asyncness.node.is_async() => {
                 return self.visit_async_fn(
                     ii.id,
                     ii.ident.name,
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index 606ae27412832..f96fc3b897f80 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -463,7 +463,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     self.invalid_visibility(&impl_item.vis, None);
                     if let ImplItemKind::Method(ref sig, _) = impl_item.node {
                         self.check_trait_fn_not_const(sig.header.constness);
-                        self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness);
+                        self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
                     }
                 }
             }
@@ -482,9 +482,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         .note("only trait implementations may be annotated with default").emit();
                 }
             }
-            ItemKind::Fn(_, header, ref generics, _) => {
+            ItemKind::Fn(_, ref header, ref generics, _) => {
                 // We currently do not permit const generics in `const fn`, as
                 // this is tantamount to allowing compile-time dependent typing.
+                self.visit_fn_header(header);
                 if header.constness.node == Constness::Const {
                     // Look for const generics and error if we find any.
                     for param in &generics.params {
@@ -535,7 +536,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self.no_questions_in_bounds(bounds, "supertraits", true);
                 for trait_item in trait_items {
                     if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
-                        self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness);
+                        self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
                         self.check_trait_fn_not_const(sig.header.constness);
                         if block.is_none() {
                             self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
@@ -702,6 +703,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             .span_bug(mac.span, "macro invocation missed in expansion; did you forget to override \
                                  the relevant `fold_*()` method in `PlaceholderExpander`?");
     }
+
+    fn visit_fn_header(&mut self, header: &'a FnHeader) {
+        if header.asyncness.node.is_async() && self.session.rust_2015() {
+            struct_span_err!(self.session, header.asyncness.span, E0670,
+                             "`async fn` is not permitted in the 2015 edition").emit();
+        }
+    }
 }
 
 pub fn check_crate(session: &Session, krate: &Crate) -> (bool, bool) {
diff --git a/src/librustc_passes/diagnostics.rs b/src/librustc_passes/diagnostics.rs
index 19d4d3aeb0f65..e3c6b16703a4a 100644
--- a/src/librustc_passes/diagnostics.rs
+++ b/src/librustc_passes/diagnostics.rs
@@ -310,6 +310,18 @@ loop {
     break;
 }
 ```
+"##,
+
+E0670: r##"
+Rust 2015 does not permit the use of `async fn`.
+
+Example of erroneous code:
+
+```compile_fail,E0670
+async fn foo() {}
+```
+
+Switch to the Rust 2018 edition to use `async fn`.
 "##
 }
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 1a7744786d80e..3993964bd9db9 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -806,9 +806,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
         debug!("(resolving function) entering function");
         let (rib_kind, asyncness) = match function_kind {
             FnKind::ItemFn(_, ref header, ..) =>
-                (ItemRibKind, header.asyncness),
+                (ItemRibKind, header.asyncness.node),
             FnKind::Method(_, ref sig, _, _) =>
-                (TraitOrImplItemRibKind, sig.header.asyncness),
+                (TraitOrImplItemRibKind, sig.header.asyncness.node),
             FnKind::Closure(_) =>
                 // Async closures aren't resolved through `visit_fn`-- they're
                 // processed separately
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 50a335bf90877..52f3a20777021 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -378,7 +378,7 @@ impl Sig for ast::Item {
                 if header.constness.node == ast::Constness::Const {
                     text.push_str("const ");
                 }
-                if header.asyncness.is_async() {
+                if header.asyncness.node.is_async() {
                     text.push_str("async ");
                 }
                 if header.unsafety == ast::Unsafety::Unsafe {
@@ -936,7 +936,7 @@ fn make_method_signature(
     if m.header.constness.node == ast::Constness::Const {
         text.push_str("const ");
     }
-    if m.header.asyncness.is_async() {
+    if m.header.asyncness.node.is_async() {
         text.push_str("async ");
     }
     if m.header.unsafety == ast::Unsafety::Unsafe {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 9c4945d74dbfe..b6f9ae36da70c 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2216,7 +2216,7 @@ impl Item {
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
 pub struct FnHeader {
     pub unsafety: Unsafety,
-    pub asyncness: IsAsync,
+    pub asyncness: Spanned<IsAsync>,
     pub constness: Spanned<Constness>,
     pub abi: Abi,
 }
@@ -2225,7 +2225,7 @@ impl Default for FnHeader {
     fn default() -> FnHeader {
         FnHeader {
             unsafety: Unsafety::Normal,
-            asyncness: IsAsync::NotAsync,
+            asyncness: dummy_spanned(IsAsync::NotAsync),
             constness: dummy_spanned(Constness::NotConst),
             abi: Abi::Rust,
         }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 27b0cfb163077..2f88749ace85e 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -1017,7 +1017,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                   ast::ItemKind::Fn(self.fn_decl(inputs, ast::FunctionRetTy::Ty(output)),
                               ast::FnHeader {
                                   unsafety: ast::Unsafety::Normal,
-                                  asyncness: ast::IsAsync::NotAsync,
+                                  asyncness: dummy_spanned(ast::IsAsync::NotAsync),
                                   constness: dummy_spanned(ast::Constness::NotConst),
                                   abi: Abi::Rust,
                               },
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index d574b410ccc06..0f7ba041f9c08 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1894,7 +1894,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         match fn_kind {
             FnKind::ItemFn(_, header, _, _) => {
                 // Check for const fn and async fn declarations.
-                if header.asyncness.is_async() {
+                if header.asyncness.node.is_async() {
                     gate_feature_post!(&self, async_await, span, "async fn is unstable");
                 }
                 // Stability of const fn methods are covered in
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 86849f580d081..935142e8a2def 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -926,7 +926,7 @@ pub fn noop_flat_map_impl_item<T: MutVisitor>(mut item: ImplItem, visitor: &mut
 
 pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
     let FnHeader { unsafety: _, asyncness, constness: _, abi: _ } = header;
-    vis.visit_asyncness(asyncness);
+    vis.visit_asyncness(&mut asyncness.node);
 }
 
 pub fn noop_visit_mod<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5a753e1f8c8a5..c257f05ae468e 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5001,6 +5001,11 @@ impl<'a> Parser<'a> {
         )
     }
 
+    fn is_async_fn(&mut self) -> bool {
+        self.token.is_keyword(keywords::Async) &&
+            self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
+    }
+
     fn is_do_catch_block(&mut self) -> bool {
         self.token.is_keyword(keywords::Do) &&
         self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
@@ -5133,7 +5138,8 @@ impl<'a> Parser<'a> {
                   !self.is_union_item() &&
                   !self.is_crate_vis() &&
                   !self.is_existential_type_decl() &&
-                  !self.is_auto_trait_item() {
+                  !self.is_auto_trait_item() &&
+                  !self.is_async_fn() {
             let pth = self.parse_path(PathStyle::Expr)?;
 
             if !self.eat(&token::Not) {
@@ -6346,7 +6352,7 @@ impl<'a> Parser<'a> {
     /// Parses an item-position function declaration.
     fn parse_item_fn(&mut self,
                      unsafety: Unsafety,
-                     asyncness: IsAsync,
+                     asyncness: Spanned<IsAsync>,
                      constness: Spanned<Constness>,
                      abi: Abi)
                      -> PResult<'a, ItemInfo> {
@@ -6378,7 +6384,7 @@ impl<'a> Parser<'a> {
         -> PResult<'a, (
             Spanned<Constness>,
             Unsafety,
-            IsAsync,
+            Spanned<IsAsync>,
             Abi
         )>
     {
@@ -6386,6 +6392,7 @@ impl<'a> Parser<'a> {
         let const_span = self.prev_span;
         let unsafety = self.parse_unsafety();
         let asyncness = self.parse_asyncness();
+        let asyncness = respan(self.prev_span, asyncness);
         let (constness, unsafety, abi) = if is_const_fn {
             (respan(const_span, Constness::Const), unsafety, Abi::Rust)
         } else {
@@ -7796,7 +7803,7 @@ impl<'a> Parser<'a> {
                 let abi = opt_abi.unwrap_or(Abi::C);
                 let (ident, item_, extra_attrs) =
                     self.parse_item_fn(Unsafety::Normal,
-                                       IsAsync::NotAsync,
+                                       respan(fn_span, IsAsync::NotAsync),
                                        respan(fn_span, Constness::NotConst),
                                        abi)?;
                 let prev_span = self.prev_span;
@@ -7840,7 +7847,7 @@ impl<'a> Parser<'a> {
                 self.bump();
                 let (ident, item_, extra_attrs) =
                     self.parse_item_fn(unsafety,
-                                       IsAsync::NotAsync,
+                                       respan(const_span, IsAsync::NotAsync),
                                        respan(const_span, Constness::Const),
                                        Abi::Rust)?;
                 let prev_span = self.prev_span;
@@ -7888,14 +7895,15 @@ impl<'a> Parser<'a> {
             // ASYNC FUNCTION ITEM
             let unsafety = self.parse_unsafety();
             self.expect_keyword(keywords::Async)?;
+            let async_span = self.prev_span;
             self.expect_keyword(keywords::Fn)?;
             let fn_span = self.prev_span;
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(unsafety,
-                                   IsAsync::Async {
+                                   respan(async_span, IsAsync::Async {
                                        closure_id: ast::DUMMY_NODE_ID,
                                        return_impl_trait_id: ast::DUMMY_NODE_ID,
-                                   },
+                                   }),
                                    respan(fn_span, Constness::NotConst),
                                    Abi::Rust)?;
             let prev_span = self.prev_span;
@@ -7904,6 +7912,13 @@ impl<'a> Parser<'a> {
                                     item_,
                                     visibility,
                                     maybe_append(attrs, extra_attrs));
+            if self.span.rust_2015() {
+                self.diagnostic().struct_span_err_with_code(
+                    async_span,
+                    "`async fn` is not permitted in the 2015 edition",
+                    DiagnosticId::Error("E0670".into())
+                ).emit();
+            }
             return Ok(Some(item));
         }
         if self.check_keyword(keywords::Unsafe) &&
@@ -7951,7 +7966,7 @@ impl<'a> Parser<'a> {
             let fn_span = self.prev_span;
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(Unsafety::Normal,
-                                   IsAsync::NotAsync,
+                                   respan(fn_span, IsAsync::NotAsync),
                                    respan(fn_span, Constness::NotConst),
                                    Abi::Rust)?;
             let prev_span = self.prev_span;
@@ -7977,7 +7992,7 @@ impl<'a> Parser<'a> {
             let fn_span = self.prev_span;
             let (ident, item_, extra_attrs) =
                 self.parse_item_fn(Unsafety::Unsafe,
-                                   IsAsync::NotAsync,
+                                   respan(fn_span, IsAsync::NotAsync),
                                    respan(fn_span, Constness::NotConst),
                                    abi)?;
             let prev_span = self.prev_span;
@@ -8244,7 +8259,8 @@ impl<'a> Parser<'a> {
         lo: Span,
         visibility: Visibility
     ) -> PResult<'a, Option<P<Item>>> {
-        if macros_allowed && self.token.is_path_start() {
+        if macros_allowed && self.token.is_path_start() &&
+                !(self.is_async_fn() && self.span.rust_2015()) {
             // MACRO INVOCATION ITEM
 
             let prev_span = self.prev_span;
@@ -8299,7 +8315,8 @@ impl<'a> Parser<'a> {
     fn parse_assoc_macro_invoc(&mut self, item_kind: &str, vis: Option<&Visibility>,
                                at_end: &mut bool) -> PResult<'a, Option<Mac>>
     {
-        if self.token.is_path_start() {
+        if self.token.is_path_start() &&
+                !(self.is_async_fn() && self.span.rust_2015()) {
             let prev_span = self.prev_span;
             let lo = self.span;
             let pth = self.parse_path(PathStyle::Mod)?;
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index dcf9815f6d1ba..d6265ebde1bbc 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -3195,7 +3195,7 @@ impl<'a> State<'a> {
             ast::Constness::Const => self.word_nbsp("const")?
         }
 
-        self.print_asyncness(header.asyncness)?;
+        self.print_asyncness(header.asyncness.node)?;
         self.print_unsafety(header.unsafety)?;
 
         if header.abi != Abi::Rust {
@@ -3247,7 +3247,7 @@ mod tests {
                     ast::FnHeader {
                         unsafety: ast::Unsafety::Normal,
                         constness: source_map::dummy_spanned(ast::Constness::NotConst),
-                        asyncness: ast::IsAsync::NotAsync,
+                        asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync),
                         abi: Abi::Rust,
                     },
                     abba_ident,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index a002394c710fe..46d8d772e9321 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -22,7 +22,7 @@ use syntax_pos::Span;
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
     /// fn foo() or extern "Abi" fn foo()
-    ItemFn(Ident, FnHeader, &'a Visibility, &'a Block),
+    ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
 
     /// fn foo(&self)
     Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block),
@@ -149,6 +149,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) {
         walk_fn_ret_ty(self, ret_ty)
     }
+    fn visit_fn_header(&mut self, _header: &'ast FnHeader) {
+        // Nothing to do
+    }
 }
 
 #[macro_export]
@@ -225,8 +228,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_ty(typ);
             visitor.visit_expr(expr);
         }
-        ItemKind::Fn(ref declaration, header, ref generics, ref body) => {
+        ItemKind::Fn(ref declaration, ref header, ref generics, ref body) => {
             visitor.visit_generics(generics);
+            visitor.visit_fn_header(header);
             visitor.visit_fn(FnKind::ItemFn(item.ident, header,
                                             &item.vis, body),
                              declaration,
@@ -539,11 +543,13 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl
     where V: Visitor<'a>,
 {
     match kind {
-        FnKind::ItemFn(_, _, _, body) => {
+        FnKind::ItemFn(_, header, _, body) => {
+            visitor.visit_fn_header(header);
             walk_fn_decl(visitor, declaration);
             visitor.visit_block(body);
         }
-        FnKind::Method(_, _, _, body) => {
+        FnKind::Method(_, sig, _, body) => {
+            visitor.visit_fn_header(&sig.header);
             walk_fn_decl(visitor, declaration);
             visitor.visit_block(body);
         }
@@ -564,6 +570,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai
             walk_list!(visitor, visit_expr, default);
         }
         TraitItemKind::Method(ref sig, None) => {
+            visitor.visit_fn_header(&sig.header);
             walk_fn_decl(visitor, &sig.decl);
         }
         TraitItemKind::Method(ref sig, Some(ref body)) => {
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index 371862465487b..f4b625f8ea2c8 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -257,7 +257,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool {
             );
             return false
         }
-        if header.asyncness.is_async() {
+        if header.asyncness.node.is_async() {
             sd.span_err(
                 i.span,
                 "async functions cannot be used for tests"
diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.rs b/src/test/ui/editions/edition-deny-async-fns-2015.rs
new file mode 100644
index 0000000000000..2105aa5835d0d
--- /dev/null
+++ b/src/test/ui/editions/edition-deny-async-fns-2015.rs
@@ -0,0 +1,34 @@
+// edition:2015
+
+#![feature(futures_api, async_await)]
+
+async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+
+fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition
+
+async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition
+    async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+}
+
+struct Foo {}
+
+impl Foo {
+    async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+}
+
+trait Bar {
+    async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+                      //~^ ERROR trait fns cannot be declared `async`
+}
+
+fn main() {
+    macro_rules! accept_item { ($x:item) => {} }
+
+    accept_item! {
+        async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+    }
+
+    let inside_closure = || {
+        async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+    };
+}
diff --git a/src/test/ui/editions/edition-deny-async-fns-2015.stderr b/src/test/ui/editions/edition-deny-async-fns-2015.stderr
new file mode 100644
index 0000000000000..1ad907aa7eb43
--- /dev/null
+++ b/src/test/ui/editions/edition-deny-async-fns-2015.stderr
@@ -0,0 +1,58 @@
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:5:1
+   |
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+   | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:7:12
+   |
+LL | fn baz() { async fn foo() {} } //~ ERROR `async fn` is not permitted in the 2015 edition
+   |            ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:10:5
+   |
+LL |     async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+   |     ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:9:1
+   |
+LL | async fn async_baz() { //~ ERROR `async fn` is not permitted in the 2015 edition
+   | ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:32:9
+   |
+LL |         async fn bar() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+   |         ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:28:9
+   |
+LL |         async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+   |         ^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:16:5
+   |
+LL |     async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+   |     ^^^^^
+
+error[E0706]: trait fns cannot be declared `async`
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
+   |
+LL |     async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/edition-deny-async-fns-2015.rs:20:5
+   |
+LL |     async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+   |     ^^^^^
+
+error: aborting due to 9 previous errors
+
+Some errors occurred: E0670, E0706.
+For more information about an error, try `rustc --explain E0670`.
diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
index 84dd1b9f814c2..b6ab8ae0a9bc7 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
+++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.rs
@@ -2,7 +2,8 @@
 
 #![feature(futures_api)]
 
-async fn foo() {} //~ ERROR async fn is unstable
+async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+                  //~^ ERROR async fn is unstable
 
 fn main() {
     let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
diff --git a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
index 450b2c42f119d..58051153e1f0d 100644
--- a/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
+++ b/src/test/ui/feature-gates/feature-gate-async-await-2015-edition.stderr
@@ -1,11 +1,17 @@
+error[E0670]: `async fn` is not permitted in the 2015 edition
+  --> $DIR/feature-gate-async-await-2015-edition.rs:5:1
+   |
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
+   | ^^^^^
+
 error[E0422]: cannot find struct, variant or union type `async` in this scope
-  --> $DIR/feature-gate-async-await-2015-edition.rs:8:13
+  --> $DIR/feature-gate-async-await-2015-edition.rs:9:13
    |
 LL |     let _ = async {}; //~ ERROR cannot find struct, variant or union type `async`
    |             ^^^^^ not found in this scope
 
 error[E0425]: cannot find value `async` in this scope
-  --> $DIR/feature-gate-async-await-2015-edition.rs:9:13
+  --> $DIR/feature-gate-async-await-2015-edition.rs:10:13
    |
 LL |     let _ = async || { true }; //~ ERROR cannot find value `async` in this scope
    |             ^^^^^ not found in this scope
@@ -13,12 +19,12 @@ LL |     let _ = async || { true }; //~ ERROR cannot find value `async` in this
 error[E0658]: async fn is unstable (see issue #50547)
   --> $DIR/feature-gate-async-await-2015-edition.rs:5:1
    |
-LL | async fn foo() {} //~ ERROR async fn is unstable
+LL | async fn foo() {} //~ ERROR `async fn` is not permitted in the 2015 edition
    | ^^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(async_await)] to the crate attributes to enable
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0422, E0425, E0658.
+Some errors occurred: E0422, E0425, E0658, E0670.
 For more information about an error, try `rustc --explain E0422`.
diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
new file mode 100644
index 0000000000000..40642523be255
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.rs
@@ -0,0 +1,11 @@
+// edition:2018
+// Test that impl trait does not allow creating recursive types that are
+// otherwise forbidden when using `async` and `await`.
+
+#![feature(await_macro, async_await, futures_api, generators)]
+
+async fn recursive_async_function() -> () { //~ ERROR
+    await!(recursive_async_function());
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr
new file mode 100644
index 0000000000000..acdeabb2f9892
--- /dev/null
+++ b/src/test/ui/impl-trait/recursive-async-impl-trait-type.stderr
@@ -0,0 +1,11 @@
+error[E0720]: opaque type expands to a recursive type
+  --> $DIR/recursive-async-impl-trait-type.rs:7:40
+   |
+LL | async fn recursive_async_function() -> () { //~ ERROR
+   |                                        ^^ expands to self-referential type
+   |
+   = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-async-impl-trait-type.rs:7:43: 9:2 {impl std::future::Future, ()}]>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.rs b/src/test/ui/impl-trait/recursive-impl-trait-type.rs
index facb191a37081..869876dc6a88a 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type.rs
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type.rs
@@ -1,7 +1,7 @@
 // Test that impl trait does not allow creating recursive types that are
 // otherwise forbidden.
 
-#![feature(await_macro, async_await, futures_api, generators)]
+#![feature(futures_api, generators)]
 
 fn option(i: i32) -> impl Sized { //~ ERROR
     if i < 0 {
@@ -62,10 +62,6 @@ fn generator_hold() -> impl Sized { //~ ERROR
     }
 }
 
-async fn recursive_async_function() -> () { //~ ERROR
-    await!(recursive_async_function());
-}
-
 fn use_fn_ptr() -> impl Sized { // OK, error already reported
     fn_ptr()
 }
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr
index 8a8789120577e..96494229fd339 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type.stderr
@@ -95,15 +95,7 @@ LL | fn generator_hold() -> impl Sized { //~ ERROR
    = note: expanded type is `[generator@$DIR/recursive-impl-trait-type.rs:58:5: 62:6 {impl Sized, ()}]`
 
 error[E0720]: opaque type expands to a recursive type
-  --> $DIR/recursive-impl-trait-type.rs:65:40
-   |
-LL | async fn recursive_async_function() -> () { //~ ERROR
-   |                                        ^^ expands to self-referential type
-   |
-   = note: expanded type is `std::future::GenFuture<[static generator@$DIR/recursive-impl-trait-type.rs:65:43: 67:2 {impl std::future::Future, ()}]>`
-
-error[E0720]: opaque type expands to a recursive type
-  --> $DIR/recursive-impl-trait-type.rs:73:26
+  --> $DIR/recursive-impl-trait-type.rs:69:26
    |
 LL | fn mutual_recursion() -> impl Sync { //~ ERROR
    |                          ^^^^^^^^^ expands to self-referential type
@@ -111,13 +103,13 @@ LL | fn mutual_recursion() -> impl Sync { //~ ERROR
    = note: type resolves to itself
 
 error[E0720]: opaque type expands to a recursive type
-  --> $DIR/recursive-impl-trait-type.rs:77:28
+  --> $DIR/recursive-impl-trait-type.rs:73:28
    |
 LL | fn mutual_recursion_b() -> impl Sized { //~ ERROR
    |                            ^^^^^^^^^^ expands to self-referential type
    |
    = note: type resolves to itself
 
-error: aborting due to 15 previous errors
+error: aborting due to 14 previous errors
 
 For more information about this error, try `rustc --explain E0720`.

From b7d4f96d195323cf9344a2af6720dfae3d9f299d Mon Sep 17 00:00:00 2001
From: Andy Russell <arussell123@gmail.com>
Date: Thu, 21 Feb 2019 20:21:50 -0500
Subject: [PATCH 07/25] rust-lldb: fix crash when printing empty string

---
 src/etc/lldb_rust_formatters.py    |  2 ++
 src/test/debuginfo/empty-string.rs | 33 ++++++++++++++++++++++++++++++
 2 files changed, 35 insertions(+)
 create mode 100644 src/test/debuginfo/empty-string.rs

diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py
index 2c651c90f82eb..fdc1c4fa0cc38 100644
--- a/src/etc/lldb_rust_formatters.py
+++ b/src/etc/lldb_rust_formatters.py
@@ -290,6 +290,8 @@ def render_element(i):
 
 
 def read_utf8_string(ptr_val, byte_count):
+    if byte_count == 0:
+        return '""'
     error = lldb.SBError()
     process = ptr_val.get_wrapped_value().GetProcess()
     data = process.ReadMemory(ptr_val.as_integer(), byte_count, error)
diff --git a/src/test/debuginfo/empty-string.rs b/src/test/debuginfo/empty-string.rs
new file mode 100644
index 0000000000000..43ce21908a958
--- /dev/null
+++ b/src/test/debuginfo/empty-string.rs
@@ -0,0 +1,33 @@
+// compile-flags:-g
+// min-gdb-version: 7.7
+// min-lldb-version: 310
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command: run
+
+// gdb-command: print empty_string
+// gdb-check:$1 = ""
+
+// gdb-command: print empty_str
+// gdb-check:$2 = ""
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command: run
+
+// lldb-command: fr v empty_string
+// lldb-check:[...]empty_string = ""
+
+// lldb-command: fr v empty_str
+// lldb-check:[...]empty_str = ""
+
+fn main() {
+    let empty_string = String::new();
+
+    let empty_str = "";
+
+    zzz(); // #break
+}
+
+fn zzz() {}

From f1b88abffbbfd4625d4002d1eef1275829aba29c Mon Sep 17 00:00:00 2001
From: Jake Goulding <jake.goulding@gmail.com>
Date: Sun, 24 Feb 2019 10:01:27 -0500
Subject: [PATCH 08/25] Fix copy-pasted typo for read_string return value

---
 src/libstd/io/mod.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index b634ea43e34e5..b49eea391772a 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1458,7 +1458,7 @@ pub trait BufRead: Read {
     ///
     /// If successful, this function will return the total number of bytes read.
     ///
-    /// An empty buffer returned indicates that the stream has reached EOF.
+    /// If this function returns `Ok(0)`, the stream has reached EOF.
     ///
     /// # Errors
     ///

From 6c44bbbbaaab182196f7584810046bfef4385019 Mon Sep 17 00:00:00 2001
From: Jethro Beekman <jethro@fortanix.com>
Date: Tue, 26 Feb 2019 09:18:22 +0900
Subject: [PATCH 09/25] Update dlmalloc to 0.1.3

---
 Cargo.lock | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 2b17a6acbaa69..1918b44a6eeb1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -744,7 +744,7 @@ dependencies = [
 
 [[package]]
 name = "dlmalloc"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2092,7 +2092,7 @@ name = "rand_chacha"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2114,7 +2114,7 @@ name = "rand_hc"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2139,7 +2139,7 @@ name = "rand_xorshift"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3230,7 +3230,7 @@ dependencies = [
  "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
- "dlmalloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)",
  "panic_abort 0.0.0",
@@ -4000,7 +4000,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
 "checksum directories 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72d337a64190607d4fcca2cb78982c5dd57f4916e19696b48a575fa746b6cb0f"
 "checksum dirs 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "88972de891f6118092b643d85a0b28e0678e0f948d7f879aa32f2d5aafe97d2a"
-"checksum dlmalloc 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d56ad71b31043818d0ee10a7fb9664882f8e45849c81647585e6a3124f185517"
+"checksum dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f283302e035e61c23f2b86b3093e8c6273a4c3125742d6087e96ade001ca5e63"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
 "checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455"
 "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00"

From eddd07cc8a92dd603e9884789fb58b2d3edd2e16 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <nnethercote@mozilla.com>
Date: Fri, 22 Feb 2019 13:36:04 +1100
Subject: [PATCH 10/25] Make `visit_clobber` panic-safe.

---
 src/libsyntax/mut_visit.rs | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 1e5eb0992bd1b..b7d22b3d554f3 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -21,6 +21,7 @@ use syntax_pos::Span;
 
 use rustc_data_structures::sync::Lrc;
 use std::ops::DerefMut;
+use std::{panic, process, ptr};
 
 pub trait ExpectOne<A: Array> {
     fn expect_one(self, err: &'static str) -> A::Item;
@@ -305,11 +306,18 @@ pub trait MutVisitor: Sized {
 
 /// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
 /// when using a `flat_map_*` or `filter_map_*` method within a `visit_`
-/// method.
+/// method. Abort the program if the closure panics.
 //
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
 pub fn visit_clobber<T, F>(t: &mut T, f: F) where F: FnOnce(T) -> T {
-    unsafe { std::ptr::write(t, f(std::ptr::read(t))); }
+    unsafe {
+        // Safe because `t` is used in a read-only fashion by `read()` before
+        // being overwritten by `write()`.
+        let old_t = ptr::read(t);
+        let new_t = panic::catch_unwind(panic::AssertUnwindSafe(|| f(old_t)))
+            .unwrap_or_else(|_| process::abort());
+        ptr::write(t, new_t);
+    }
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.

From abd88a9e3a6014134dac0a705eae6de7448ea514 Mon Sep 17 00:00:00 2001
From: Ivan Petkov <ivanppetkov@gmail.com>
Date: Mon, 25 Feb 2019 19:49:49 -0800
Subject: [PATCH 11/25] Disable running several Stdio doctests

* A number of `Stdio` related doc examples include running the "rev"
command to illustrate piping commands. The majority of these tests are
marked as `no_run` except for two tests which were not
* Not running these tests is unlikely to cause any negative impact, and
doing so also allows the test suite to pass in environments where the
"rev" command is unavailable
---
 src/libstd/process.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index a2ef85016d8a2..735ce61c9bc29 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1015,7 +1015,7 @@ impl From<ChildStdin> for Stdio {
     ///
     /// `ChildStdin` will be converted to `Stdio` using `Stdio::from` under the hood.
     ///
-    /// ```rust
+    /// ```rust,no_run
     /// use std::process::{Command, Stdio};
     ///
     /// let reverse = Command::new("rev")
@@ -1044,7 +1044,7 @@ impl From<ChildStdout> for Stdio {
     ///
     /// `ChildStdout` will be converted to `Stdio` using `Stdio::from` under the hood.
     ///
-    /// ```rust
+    /// ```rust,no_run
     /// use std::process::{Command, Stdio};
     ///
     /// let hello = Command::new("echo")

From 5b975162e24d3be643a05824b6132dcb968e3fa7 Mon Sep 17 00:00:00 2001
From: Marcel Hellwig <mhellwig@mut-group.com>
Date: Tue, 26 Feb 2019 09:54:45 +0100
Subject: [PATCH 12/25] update scoped_tls to 1.0

---
 src/librustc/Cargo.toml        | 2 +-
 src/librustc_driver/Cargo.toml | 2 +-
 src/libsyntax/Cargo.toml       | 2 +-
 src/libsyntax_pos/Cargo.toml   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index e83adad4e2a0e..e3557132a1252 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -17,7 +17,7 @@ graphviz = { path = "../libgraphviz" }
 jobserver = "0.1"
 lazy_static = "1.0.0"
 num_cpus = "1.0"
-scoped-tls = { version = "0.1.1", features = ["nightly"] }
+scoped-tls = "1.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
 polonius-engine = "0.6.2"
 rustc-rayon = "0.1.1"
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 8bcda409e6663..2e6e775c52610 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -14,7 +14,7 @@ graphviz = { path = "../libgraphviz" }
 log = "0.4"
 env_logger = { version = "0.5", default-features = false }
 rustc-rayon = "0.1.1"
-scoped-tls = { version = "0.1.1", features = ["nightly"] }
+scoped-tls = "1.0"
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
 rustc_target = { path = "../librustc_target" }
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index 4a0bb0302ffbc..71c2ab82f65c3 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -13,7 +13,7 @@ crate-type = ["dylib"]
 bitflags = "1.0"
 serialize = { path = "../libserialize" }
 log = "0.4"
-scoped-tls = "0.1"
+scoped-tls = "1.0"
 syntax_pos = { path = "../libsyntax_pos" }
 errors = { path = "../librustc_errors", package = "rustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml
index 5658451c54f71..691abffbbc1af 100644
--- a/src/libsyntax_pos/Cargo.toml
+++ b/src/libsyntax_pos/Cargo.toml
@@ -13,6 +13,6 @@ crate-type = ["dylib"]
 serialize = { path = "../libserialize" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 arena = { path = "../libarena" }
-scoped-tls = { version = "0.1.1", features = ["nightly"] }
+scoped-tls = "1.0"
 unicode-width = "0.1.4"
 cfg-if = "0.1.2"

From 992694ac4dcbc93ca249fbb9f148cc586f1d384d Mon Sep 17 00:00:00 2001
From: kenta7777 <k.hasegw7@gmail.com>
Date: Tue, 26 Feb 2019 17:54:57 +0900
Subject: [PATCH 13/25] reduce repetitions of (n << amt) >> amt

---
 src/librustc/ty/util.rs | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 1ba7c3bba797c..796ac372d020b 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -4,6 +4,7 @@ use crate::hir::def::Def;
 use crate::hir::def_id::DefId;
 use crate::hir::map::DefPathData;
 use crate::hir::{self, Node};
+use crate::mir::interpret::{sign_extend, truncate};
 use crate::ich::NodeIdHashingMode;
 use crate::traits::{self, ObligationCause};
 use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
@@ -32,12 +33,12 @@ impl<'tcx> fmt::Display for Discr<'tcx> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.ty.sty {
             ty::Int(ity) => {
-                let bits = ty::tls::with(|tcx| {
-                    Integer::from_attr(&tcx, SignedInt(ity)).size().bits()
+                let size = ty::tls::with(|tcx| {
+                    Integer::from_attr(&tcx, SignedInt(ity)).size()
                 });
-                let x = self.val as i128;
+                let x = self.val;
                 // sign extend the raw representation to be an i128
-                let x = (x << (128 - bits)) >> (128 - bits);
+                let x = sign_extend(x, size) as i128;
                 write!(fmt, "{}", x)
             },
             _ => write!(fmt, "{}", self.val),
@@ -57,12 +58,12 @@ impl<'tcx> Discr<'tcx> {
             _ => bug!("non integer discriminant"),
         };
 
+        let size = int.size();
         let bit_size = int.size().bits();
         let shift = 128 - bit_size;
         if signed {
             let sext = |u| {
-                let i = u as i128;
-                (i << shift) >> shift
+                sign_extend(u, size) as i128
             };
             let min = sext(1_u128 << (bit_size - 1));
             let max = i128::max_value() >> shift;
@@ -77,7 +78,7 @@ impl<'tcx> Discr<'tcx> {
             };
             // zero the upper bits
             let val = val as u128;
-            let val = (val << shift) >> shift;
+            let val = truncate(val, size);
             (Self {
                 val: val as u128,
                 ty: self.ty,

From b23fd439642a0d161d4a76d373736e3cad182339 Mon Sep 17 00:00:00 2001
From: Tim Diekmann <tim.diekmann@3dvision.de>
Date: Tue, 26 Feb 2019 10:11:41 +0100
Subject: [PATCH 14/25] Make `Unique::as_ptr`, `NonNull::dangling` and
 `NonNull::cast` const

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

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 866c8d0896b3c..6186173812cb2 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2790,7 +2790,7 @@ impl<T: ?Sized> Unique<T> {
     }
 
     /// Acquires the underlying `*mut` pointer.
-    pub fn as_ptr(self) -> *mut T {
+    pub const fn as_ptr(self) -> *mut T {
         self.pointer as *mut T
     }
 
@@ -2903,7 +2903,7 @@ impl<T: Sized> NonNull<T> {
     /// some other means.
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
-    pub fn dangling() -> Self {
+    pub const fn dangling() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
             NonNull::new_unchecked(ptr)
@@ -2966,7 +2966,7 @@ impl<T: ?Sized> NonNull<T> {
     /// Cast to a pointer of another type
     #[stable(feature = "nonnull_cast", since = "1.27.0")]
     #[inline]
-    pub fn cast<U>(self) -> NonNull<U> {
+    pub const fn cast<U>(self) -> NonNull<U> {
         unsafe {
             NonNull::new_unchecked(self.as_ptr() as *mut U)
         }

From 56fb2873fe284ef470c468f2370418aa8bebc41a Mon Sep 17 00:00:00 2001
From: Marcel Hellwig <git@cookiesoft.de>
Date: Tue, 26 Feb 2019 11:15:52 +0100
Subject: [PATCH 15/25] update Cargo.lock

---
 Cargo.lock | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 2b17a6acbaa69..735858d11eeda 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2381,7 +2381,7 @@ dependencies = [
  "rustc_errors 0.0.0",
  "rustc_fs_util 0.0.0",
  "rustc_target 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
@@ -2726,7 +2726,7 @@ dependencies = [
  "rustc_target 0.0.0",
  "rustc_traits 0.0.0",
  "rustc_typeck 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax 0.0.0",
@@ -3090,6 +3090,11 @@ name = "scoped-tls"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "scoped-tls"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "scoped_threadpool"
 version = "0.1.9"
@@ -3345,7 +3350,7 @@ dependencies = [
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntax_pos 0.0.0",
@@ -3372,7 +3377,7 @@ dependencies = [
  "arena 0.0.0",
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_data_structures 0.0.0",
- "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -4183,6 +4188,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
 "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56"
 "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
+"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
 "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"

From 2d6261904663522ee1e9ec6c9f4079e4e56ba057 Mon Sep 17 00:00:00 2001
From: Tim Diekmann <tim.diekmann@3dvision.de>
Date: Tue, 26 Feb 2019 11:58:30 +0100
Subject: [PATCH 16/25] Add `rustc_const_unstable` attribute

---
 src/libcore/ptr.rs | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 6186173812cb2..d00665d778fb6 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2892,6 +2892,17 @@ impl<T: ?Sized> !Send for NonNull<T> { }
 impl<T: ?Sized> !Sync for NonNull<T> { }
 
 impl<T: Sized> NonNull<T> {
+    /// No docs here
+    #[stable(feature = "nonnull", since = "1.25.0")]
+    #[inline]
+    #[cfg(stage0)]
+    pub fn dangling() -> Self {
+        unsafe {
+            let ptr = mem::align_of::<T>() as *mut T;
+            NonNull::new_unchecked(ptr)
+        }
+    }
+    
     /// Creates a new `NonNull` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
@@ -2903,6 +2914,8 @@ impl<T: Sized> NonNull<T> {
     /// some other means.
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
+    #[cfg(not(stage0))]
+    #[rustc_const_unstable(feature = "const_ptr_nonnull")]
     pub const fn dangling() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
@@ -2963,9 +2976,21 @@ impl<T: ?Sized> NonNull<T> {
         &mut *self.as_ptr()
     }
 
+    /// No docs here
+    #[stable(feature = "nonnull_cast", since = "1.27.0")]
+    #[inline]
+    #[cfg(stage0)]
+    pub fn cast<U>(self) -> NonNull<U> {
+        unsafe {
+            NonNull::new_unchecked(self.as_ptr() as *mut U)
+        }
+    }
+
     /// Cast to a pointer of another type
     #[stable(feature = "nonnull_cast", since = "1.27.0")]
     #[inline]
+    #[cfg(not(stage0))]
+    #[rustc_const_unstable(feature = "const_ptr_nonnull")]
     pub const fn cast<U>(self) -> NonNull<U> {
         unsafe {
             NonNull::new_unchecked(self.as_ptr() as *mut U)

From 4839d8c544232df8fa1cb55d306a936fc098ce9c Mon Sep 17 00:00:00 2001
From: Tim Diekmann <tim.diekmann@3dvision.de>
Date: Tue, 26 Feb 2019 11:58:44 +0100
Subject: [PATCH 17/25] Add tests

---
 src/test/run-pass/consts/const-ptr-nonnull.rs | 22 +++++++++++++++++
 src/test/run-pass/consts/const-ptr-unique.rs  | 15 ++++++++++++
 src/test/ui/consts/const-ptr-nonnull.rs       |  9 +++++++
 src/test/ui/consts/const-ptr-nonnull.stderr   | 24 +++++++++++++++++++
 src/test/ui/consts/const-ptr-unique.rs        |  9 +++++++
 src/test/ui/consts/const-ptr-unique.stderr    | 13 ++++++++++
 6 files changed, 92 insertions(+)
 create mode 100644 src/test/run-pass/consts/const-ptr-nonnull.rs
 create mode 100644 src/test/run-pass/consts/const-ptr-unique.rs
 create mode 100644 src/test/ui/consts/const-ptr-nonnull.rs
 create mode 100644 src/test/ui/consts/const-ptr-nonnull.stderr
 create mode 100644 src/test/ui/consts/const-ptr-unique.rs
 create mode 100644 src/test/ui/consts/const-ptr-unique.stderr

diff --git a/src/test/run-pass/consts/const-ptr-nonnull.rs b/src/test/run-pass/consts/const-ptr-nonnull.rs
new file mode 100644
index 0000000000000..62f10fb484177
--- /dev/null
+++ b/src/test/run-pass/consts/const-ptr-nonnull.rs
@@ -0,0 +1,22 @@
+// run-pass
+
+#![feature(const_ptr_nonnull)]
+
+use std::ptr::NonNull;
+
+const fn dangling() -> NonNull<u32> {
+    NonNull::dangling()
+}
+
+const fn cast<T, U>(non_null: NonNull<T>) -> NonNull<U> {
+    non_null.cast()
+}
+
+pub fn main() {
+    assert_eq!(dangling(), NonNull::dangling());
+    
+    let mut i: i32 = 10;
+    let non_null_t = NonNull::new(&mut i).unwrap();
+    let non_null_u: NonNull<u32> = cast(non_null_t);
+    assert_eq!(non_null_t.as_ptr(), non_null_u.as_ptr() as *mut i32);
+}
diff --git a/src/test/run-pass/consts/const-ptr-unique.rs b/src/test/run-pass/consts/const-ptr-unique.rs
new file mode 100644
index 0000000000000..4374bb81b4ee8
--- /dev/null
+++ b/src/test/run-pass/consts/const-ptr-unique.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(ptr_internals)]
+
+use std::ptr::Unique;
+
+const fn as_ptr<T>(ptr: Unique<T>) -> *mut T {
+    ptr.as_ptr()
+}
+
+pub fn main() {
+    let mut i: i32 = 10;
+    let unique = Unique::new(&mut i).unwrap();
+    assert_eq!(unique.as_ptr(), as_ptr(unique));
+}
diff --git a/src/test/ui/consts/const-ptr-nonnull.rs b/src/test/ui/consts/const-ptr-nonnull.rs
new file mode 100644
index 0000000000000..9502b619b6613
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-nonnull.rs
@@ -0,0 +1,9 @@
+use std::ptr::NonNull;
+
+fn main() {
+    let x: &'static NonNull<u32> = &(NonNull::dangling()); //~ ERROR borrowed value does not live long enough
+    
+    let mut i: i32 = 10;
+    let non_null = NonNull::new(&mut i).unwrap();
+    let x: &'static NonNull<u32> = &(non_null.cast()); //~ ERROR borrowed value does not live long enough
+}
diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr
new file mode 100644
index 0000000000000..e670528210849
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-nonnull.stderr
@@ -0,0 +1,24 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-nonnull.rs:4:37
+   |
+LL |     let x: &'static NonNull<u32> = &(NonNull::dangling()); //~ ERROR borrowed value does not live long enough
+   |                                     ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-nonnull.rs:8:37
+   |
+LL |     let x: &'static NonNull<u32> = &(non_null.cast()); //~ ERROR borrowed value does not live long enough
+   |                                     ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-ptr-unique.rs b/src/test/ui/consts/const-ptr-unique.rs
new file mode 100644
index 0000000000000..792d1854b7899
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-unique.rs
@@ -0,0 +1,9 @@
+#![feature(ptr_internals)]
+
+use std::ptr::Unique;
+
+fn main() {
+    let mut i: u32 = 10;
+    let unique = Unique::new(&mut i).unwrap();
+    let x: &'static *mut u32 = &(unique.as_ptr()); //~ ERROR borrowed value does not live long enough
+}
diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr
new file mode 100644
index 0000000000000..32cb862b3c3e8
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-unique.stderr
@@ -0,0 +1,13 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-unique.rs:8:33
+   |
+LL |     let x: &'static *mut u32 = &(unique.as_ptr()); //~ ERROR borrowed value does not live long enough
+   |                                 ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.

From 6375efc822eab92a42ce0382ca9597d8430c4efd Mon Sep 17 00:00:00 2001
From: Taiki Endo <te316e89@gmail.com>
Date: Tue, 26 Feb 2019 20:06:31 +0900
Subject: [PATCH 18/25] Update string_cache_codegen to 0.4.2

---
 Cargo.lock | 30 ++++++------------------------
 1 file changed, 6 insertions(+), 24 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 2b17a6acbaa69..64db279862d45 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1399,7 +1399,7 @@ dependencies = [
  "serde_derive 1.0.81 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1936,14 +1936,6 @@ dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "proc-macro2"
-version = "0.3.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "proc-macro2"
 version = "0.4.24"
@@ -2015,14 +2007,6 @@ name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "quote"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "quote"
 version = "0.6.10"
@@ -3255,19 +3239,19 @@ dependencies = [
  "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
- "string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "string_cache_codegen"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -4124,7 +4108,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
 "checksum pretty_env_logger 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61"
-"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7"
 "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
 "checksum proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "926d0604475349f463fe44130aae73f2294b5309ab2ca0310b998bd334ef191f"
 "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
@@ -4132,7 +4115,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
 "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
 "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
 "checksum racer 2.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d634483bed41bb116122b84ffe0ef8740345c2ceb2784ce86c33499700eb13a7"
 "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
@@ -4201,7 +4183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
 "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
 "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423"
-"checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191"
+"checksum string_cache_codegen 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eea1eee654ef80933142157fdad9dd8bc43cf7c74e999e369263496f04ff4da"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum strum 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c3a2071519ab6a48f465808c4c1ffdd00dfc8e93111d02b4fc5abab177676e"

From 278cb91346dcd043734ec250fbcc4b87ae93aef1 Mon Sep 17 00:00:00 2001
From: Tim Diekmann <tim.diekmann@3dvision.de>
Date: Tue, 26 Feb 2019 13:03:40 +0100
Subject: [PATCH 19/25] Satisfy tidy

---
 src/libcore/ptr.rs                            | 2 +-
 src/test/run-pass/consts/const-ptr-nonnull.rs | 2 +-
 src/test/ui/consts/const-ptr-nonnull.rs       | 8 +++++---
 src/test/ui/consts/const-ptr-nonnull.stderr   | 7 ++++---
 src/test/ui/consts/const-ptr-unique.rs        | 3 ++-
 src/test/ui/consts/const-ptr-unique.stderr    | 3 ++-
 6 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index d00665d778fb6..d817dacadca9c 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2902,7 +2902,7 @@ impl<T: Sized> NonNull<T> {
             NonNull::new_unchecked(ptr)
         }
     }
-    
+
     /// Creates a new `NonNull` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
diff --git a/src/test/run-pass/consts/const-ptr-nonnull.rs b/src/test/run-pass/consts/const-ptr-nonnull.rs
index 62f10fb484177..70d22c5e7147f 100644
--- a/src/test/run-pass/consts/const-ptr-nonnull.rs
+++ b/src/test/run-pass/consts/const-ptr-nonnull.rs
@@ -14,7 +14,7 @@ const fn cast<T, U>(non_null: NonNull<T>) -> NonNull<U> {
 
 pub fn main() {
     assert_eq!(dangling(), NonNull::dangling());
-    
+
     let mut i: i32 = 10;
     let non_null_t = NonNull::new(&mut i).unwrap();
     let non_null_u: NonNull<u32> = cast(non_null_t);
diff --git a/src/test/ui/consts/const-ptr-nonnull.rs b/src/test/ui/consts/const-ptr-nonnull.rs
index 9502b619b6613..54e743aa32e23 100644
--- a/src/test/ui/consts/const-ptr-nonnull.rs
+++ b/src/test/ui/consts/const-ptr-nonnull.rs
@@ -1,9 +1,11 @@
 use std::ptr::NonNull;
 
 fn main() {
-    let x: &'static NonNull<u32> = &(NonNull::dangling()); //~ ERROR borrowed value does not live long enough
-    
+    let x: &'static NonNull<u32> = &(NonNull::dangling());
+    //~^ ERROR borrowed value does not live long enough
+
     let mut i: i32 = 10;
     let non_null = NonNull::new(&mut i).unwrap();
-    let x: &'static NonNull<u32> = &(non_null.cast()); //~ ERROR borrowed value does not live long enough
+    let x: &'static NonNull<u32> = &(non_null.cast());
+    //~^ ERROR borrowed value does not live long enough
 }
diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr
index e670528210849..a9476dda6d320 100644
--- a/src/test/ui/consts/const-ptr-nonnull.stderr
+++ b/src/test/ui/consts/const-ptr-nonnull.stderr
@@ -1,7 +1,7 @@
 error[E0597]: borrowed value does not live long enough
   --> $DIR/const-ptr-nonnull.rs:4:37
    |
-LL |     let x: &'static NonNull<u32> = &(NonNull::dangling()); //~ ERROR borrowed value does not live long enough
+LL |     let x: &'static NonNull<u32> = &(NonNull::dangling());
    |                                     ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
 ...
 LL | }
@@ -10,10 +10,11 @@ LL | }
    = note: borrowed value must be valid for the static lifetime...
 
 error[E0597]: borrowed value does not live long enough
-  --> $DIR/const-ptr-nonnull.rs:8:37
+  --> $DIR/const-ptr-nonnull.rs:9:37
    |
-LL |     let x: &'static NonNull<u32> = &(non_null.cast()); //~ ERROR borrowed value does not live long enough
+LL |     let x: &'static NonNull<u32> = &(non_null.cast());
    |                                     ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ ERROR borrowed value does not live long enough
 LL | }
    | - temporary value only lives until here
    |
diff --git a/src/test/ui/consts/const-ptr-unique.rs b/src/test/ui/consts/const-ptr-unique.rs
index 792d1854b7899..be44a24181606 100644
--- a/src/test/ui/consts/const-ptr-unique.rs
+++ b/src/test/ui/consts/const-ptr-unique.rs
@@ -5,5 +5,6 @@ use std::ptr::Unique;
 fn main() {
     let mut i: u32 = 10;
     let unique = Unique::new(&mut i).unwrap();
-    let x: &'static *mut u32 = &(unique.as_ptr()); //~ ERROR borrowed value does not live long enough
+    let x: &'static *mut u32 = &(unique.as_ptr());
+    //~^ ERROR borrowed value does not live long enough
 }
diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr
index 32cb862b3c3e8..141465bf184d0 100644
--- a/src/test/ui/consts/const-ptr-unique.stderr
+++ b/src/test/ui/consts/const-ptr-unique.stderr
@@ -1,8 +1,9 @@
 error[E0597]: borrowed value does not live long enough
   --> $DIR/const-ptr-unique.rs:8:33
    |
-LL |     let x: &'static *mut u32 = &(unique.as_ptr()); //~ ERROR borrowed value does not live long enough
+LL |     let x: &'static *mut u32 = &(unique.as_ptr());
    |                                 ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ ERROR borrowed value does not live long enough
 LL | }
    | - temporary value only lives until here
    |

From baea3c7ae9588adb6500acfbf418e58c8edb0a7e Mon Sep 17 00:00:00 2001
From: Tim Diekmann <tim.diekmann@3dvision.de>
Date: Tue, 26 Feb 2019 14:18:43 +0100
Subject: [PATCH 20/25] Use `cfg_attr` to prevent duplication

---
 src/libcore/ptr.rs | 27 ++-------------------------
 1 file changed, 2 insertions(+), 25 deletions(-)

diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index d817dacadca9c..3e1773ff9d25c 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2892,17 +2892,6 @@ impl<T: ?Sized> !Send for NonNull<T> { }
 impl<T: ?Sized> !Sync for NonNull<T> { }
 
 impl<T: Sized> NonNull<T> {
-    /// No docs here
-    #[stable(feature = "nonnull", since = "1.25.0")]
-    #[inline]
-    #[cfg(stage0)]
-    pub fn dangling() -> Self {
-        unsafe {
-            let ptr = mem::align_of::<T>() as *mut T;
-            NonNull::new_unchecked(ptr)
-        }
-    }
-
     /// Creates a new `NonNull` that is dangling, but well-aligned.
     ///
     /// This is useful for initializing types which lazily allocate, like
@@ -2914,8 +2903,7 @@ impl<T: Sized> NonNull<T> {
     /// some other means.
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
-    #[cfg(not(stage0))]
-    #[rustc_const_unstable(feature = "const_ptr_nonnull")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
     pub const fn dangling() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
@@ -2976,21 +2964,10 @@ impl<T: ?Sized> NonNull<T> {
         &mut *self.as_ptr()
     }
 
-    /// No docs here
-    #[stable(feature = "nonnull_cast", since = "1.27.0")]
-    #[inline]
-    #[cfg(stage0)]
-    pub fn cast<U>(self) -> NonNull<U> {
-        unsafe {
-            NonNull::new_unchecked(self.as_ptr() as *mut U)
-        }
-    }
-
     /// Cast to a pointer of another type
     #[stable(feature = "nonnull_cast", since = "1.27.0")]
     #[inline]
-    #[cfg(not(stage0))]
-    #[rustc_const_unstable(feature = "const_ptr_nonnull")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
     pub const fn cast<U>(self) -> NonNull<U> {
         unsafe {
             NonNull::new_unchecked(self.as_ptr() as *mut U)

From c5f3830e63e1a222f07234ac9ea012dee96220bb Mon Sep 17 00:00:00 2001
From: Tim Diekmann <tim.diekmann@3dvision.de>
Date: Tue, 26 Feb 2019 14:19:07 +0100
Subject: [PATCH 21/25] Use const eval instead of const fn

---
 src/test/run-pass/consts/const-ptr-nonnull.rs | 17 ++++++-----------
 src/test/run-pass/consts/const-ptr-unique.rs  | 10 +++++-----
 2 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/src/test/run-pass/consts/const-ptr-nonnull.rs b/src/test/run-pass/consts/const-ptr-nonnull.rs
index 70d22c5e7147f..91624e92fbe75 100644
--- a/src/test/run-pass/consts/const-ptr-nonnull.rs
+++ b/src/test/run-pass/consts/const-ptr-nonnull.rs
@@ -4,19 +4,14 @@
 
 use std::ptr::NonNull;
 
-const fn dangling() -> NonNull<u32> {
-    NonNull::dangling()
-}
+const DANGLING: NonNull<u32> = NonNull::dangling();
+const CASTED: NonNull<u32> = NonNull::cast(NonNull::<i32>::dangling());
 
-const fn cast<T, U>(non_null: NonNull<T>) -> NonNull<U> {
-    non_null.cast()
+fn ident<T>(ident: T) -> T {
+    ident
 }
 
 pub fn main() {
-    assert_eq!(dangling(), NonNull::dangling());
-
-    let mut i: i32 = 10;
-    let non_null_t = NonNull::new(&mut i).unwrap();
-    let non_null_u: NonNull<u32> = cast(non_null_t);
-    assert_eq!(non_null_t.as_ptr(), non_null_u.as_ptr() as *mut i32);
+    assert_eq!(DANGLING, ident(NonNull::dangling()));
+    assert_eq!(CASTED, ident(NonNull::dangling()));
 }
diff --git a/src/test/run-pass/consts/const-ptr-unique.rs b/src/test/run-pass/consts/const-ptr-unique.rs
index 4374bb81b4ee8..eb371ab184166 100644
--- a/src/test/run-pass/consts/const-ptr-unique.rs
+++ b/src/test/run-pass/consts/const-ptr-unique.rs
@@ -4,12 +4,12 @@
 
 use std::ptr::Unique;
 
-const fn as_ptr<T>(ptr: Unique<T>) -> *mut T {
-    ptr.as_ptr()
+const PTR: *mut u32 = Unique::empty().as_ptr();
+
+fn ident<T>(ident: T) -> T {
+    ident
 }
 
 pub fn main() {
-    let mut i: i32 = 10;
-    let unique = Unique::new(&mut i).unwrap();
-    assert_eq!(unique.as_ptr(), as_ptr(unique));
+    assert_eq!(PTR, ident(Unique::<u32>::empty().as_ptr()));
 }

From 998896c036cca6ed984f39fe28bb867055432167 Mon Sep 17 00:00:00 2001
From: Tobias Bucher <tobiasbucher5991@gmail.com>
Date: Tue, 26 Feb 2019 16:10:28 +0100
Subject: [PATCH 22/25] Clarify `rotate_{left,right}` docs

I wondered what the `<<!` operator is although the exclamation mark was
only the end of the sentence.
---
 src/libcore/num/mod.rs      | 8 ++++----
 src/libcore/num/wrapping.rs | 6 ++++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 3ceba83afeef8..6708a195f88c5 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -346,7 +346,7 @@ $EndFeature, "
             concat!("Shifts the bits to the left by a specified amount, `n`,
 wrapping the truncated bits to the end of the resulting integer.
 
-Please note this isn't the same operation as `<<`!
+Please note this isn't the same operation as the `<<` shifting operator!
 
 # Examples
 
@@ -370,7 +370,7 @@ assert_eq!(n.rotate_left(", $rot, "), m);
 wrapping the truncated bits to the beginning of the resulting
 integer.
 
-Please note this isn't the same operation as `>>`!
+Please note this isn't the same operation as the `>>` shifting operator!
 
 # Examples
 
@@ -2300,7 +2300,7 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, "
             concat!("Shifts the bits to the left by a specified amount, `n`,
 wrapping the truncated bits to the end of the resulting integer.
 
-Please note this isn't the same operation as `<<`!
+Please note this isn't the same operation as the `<<` shifting operator!
 
 # Examples
 
@@ -2324,7 +2324,7 @@ assert_eq!(n.rotate_left(", $rot, "), m);
 wrapping the truncated bits to the beginning of the resulting
 integer.
 
-Please note this isn't the same operation as `>>`!
+Please note this isn't the same operation as the `>>` shifting operator!
 
 # Examples
 
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index 50e189c9e3640..9cd5108ade411 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -429,7 +429,8 @@ assert_eq!(n.trailing_zeros(), 3);
             /// wrapping the truncated bits to the end of the resulting
             /// integer.
             ///
-            /// Please note this isn't the same operation as `>>`!
+            /// Please note this isn't the same operation as the `>>` shifting
+            /// operator!
             ///
             /// # Examples
             ///
@@ -454,7 +455,8 @@ assert_eq!(n.trailing_zeros(), 3);
             /// wrapping the truncated bits to the beginning of the resulting
             /// integer.
             ///
-            /// Please note this isn't the same operation as `<<`!
+            /// Please note this isn't the same operation as the `<<` shifting
+            /// operator!
             ///
             /// # Examples
             ///

From 9b4055b30200caf366d387624fd5bbb03de8da13 Mon Sep 17 00:00:00 2001
From: Angelos Oikonomopoulos <a.oikonomopoulos@vu.nl>
Date: Tue, 26 Feb 2019 16:48:12 +0100
Subject: [PATCH 23/25] Normalize the type Self resolves to in an impl

This is required at the very least in order to evaluate associated
constants for arrays (see #58212).
---
 src/librustc_typeck/astconv.rs          |  3 ++-
 src/test/run-pass/issues/issue-58212.rs | 13 +++++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 src/test/run-pass/issues/issue-58212.rs

diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index db63f2aafbc24..c52ff8bf650cd 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1700,7 +1700,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 // `Self` in impl (we know the concrete type).
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(&path.segments);
-                tcx.at(span).type_of(def_id)
+                // Try to evaluate any array length constants
+                self.normalize_ty(span, tcx.at(span).type_of(def_id))
             }
             Def::SelfTy(Some(_), None) => {
                 // `Self` in trait.
diff --git a/src/test/run-pass/issues/issue-58212.rs b/src/test/run-pass/issues/issue-58212.rs
new file mode 100644
index 0000000000000..76437630309af
--- /dev/null
+++ b/src/test/run-pass/issues/issue-58212.rs
@@ -0,0 +1,13 @@
+trait FromUnchecked {
+    unsafe fn from_unchecked();
+}
+
+impl FromUnchecked for [u8; 1] {
+    unsafe fn from_unchecked() {
+        let mut array: Self = std::mem::uninitialized();
+        let _ptr = &mut array as *mut [u8] as *mut u8;
+    }
+}
+
+fn main() {
+}

From c1f3d1520efc91ec79dfafd6ab0e679872092487 Mon Sep 17 00:00:00 2001
From: Adonis <adonis.settouf@gmail.com>
Date: Sat, 2 Feb 2019 12:03:38 +0100
Subject: [PATCH 24/25] Changing error message to reflect changes with the 2018
 edition

Signed-off-by: Adonis <adonis.settouf@gmail.com>

Update src/libsyntax/ext/tt/quoted.rs

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Update src/libsyntax/ext/tt/quoted.rs

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Update src/libsyntax/ext/tt/quoted.rs

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Update src/libsyntax/ext/tt/quoted.rs

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Update src/libsyntax/ext/tt/quoted.rs

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Update src/libsyntax/ext/tt/quoted.rs

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Update src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Update src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Stabilize split_ascii_whitespace

Tracking issue FCP to merge: https://github.com/rust-lang/rust/issues/48656#issuecomment-442372750

fix stabilization order of uniform_paths.

hir: add HirId to main Hir nodes

Fix `std::os::fortanix_sgx::usercalls::raw::UsercallNrs`

Fixes https://github.com/fortanix/rust-sgx/issues/88

Update src/libsyntax/ext/tt/quoted.rs

Co-Authored-By: asettouf <adonis.settouf@gmail.com>

Revert "Merge remote-tracking branch 'upstream/master'"

This reverts commit 751f05bd155e2c55d4177fe8211df634faf3a644, reversing
changes made to 545a3e62b0cb473108869a61b271bc589afb49da.
---
 src/libsyntax/ext/tt/quoted.rs                 | 18 ++++++++++++------
 ...macro-at-most-once-rep-2015-ques-rep.stderr |  4 ++--
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs
index b56871a18857f..43d279980f6ea 100644
--- a/src/libsyntax/ext/tt/quoted.rs
+++ b/src/libsyntax/ext/tt/quoted.rs
@@ -474,11 +474,13 @@ where
                 // #1 is a separator and #2 should be a KleepeOp.
                 // (N.B. We need to advance the input iterator.)
                 match parse_kleene_op(input, span) {
-                    // #2 is `?`, which is not allowed as a Kleene op in 2015 edition.
+                    // #2 is `?`, which is not allowed as a Kleene op in 2015 edition,
+                    // but is allowed in the 2018 edition.
                     Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => {
                         sess.span_diagnostic
                             .struct_span_err(op2_span, "expected `*` or `+`")
-                            .note("`?` is not a macro repetition operator")
+                            .note("`?` is not a macro repetition operator in the 2015 edition, \
+                                 but is accepted in the 2018 edition")
                             .emit();
 
                         // Return a dummy
@@ -506,10 +508,12 @@ where
                     Err(_) => op1_span,
                 }
             } else {
-                // `?` is not allowed as a Kleene op in 2015
+                // `?` is not allowed as a Kleene op in 2015,
+                // but is allowed in the 2018 edition
                 sess.span_diagnostic
                     .struct_span_err(op1_span, "expected `*` or `+`")
-                    .note("`?` is not a macro repetition operator")
+                    .note("`?` is not a macro repetition operator in the 2015 edition, \
+                         but is accepted in the 2018 edition")
                     .emit();
 
                 // Return a dummy
@@ -519,11 +523,13 @@ where
 
         // #1 is a separator followed by #2, a KleeneOp
         Ok(Err((tok, span))) => match parse_kleene_op(input, span) {
-            // #2 is a `?`, which is not allowed as a Kleene op in 2015 edition.
+            // #2 is a `?`, which is not allowed as a Kleene op in 2015 edition,
+            // but is allowed in the 2018 edition
             Ok(Ok((op, op2_span))) if op == KleeneOp::ZeroOrOne => {
                 sess.span_diagnostic
                     .struct_span_err(op2_span, "expected `*` or `+`")
-                    .note("`?` is not a macro repetition operator")
+                    .note("`?` is not a macro repetition operator in the 2015 edition, \
+                        but is accepted in the 2018 edition")
                     .emit();
 
                 // Return a dummy
diff --git a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr
index b27b60459d633..cb0a9163b7470 100644
--- a/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr
+++ b/src/test/ui/macros/macro-at-most-once-rep-2015-ques-rep.stderr
@@ -4,7 +4,7 @@ error: expected `*` or `+`
 LL |     ($(a)?) => {} //~ERROR expected `*` or `+`
    |          ^
    |
-   = note: `?` is not a macro repetition operator
+   = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition
 
 error: expected `*` or `+`
   --> $DIR/macro-at-most-once-rep-2015-ques-rep.rs:10:11
@@ -12,7 +12,7 @@ error: expected `*` or `+`
 LL |     ($(a),?) => {} //~ERROR expected `*` or `+`
    |           ^
    |
-   = note: `?` is not a macro repetition operator
+   = note: `?` is not a macro repetition operator in the 2015 edition, but is accepted in the 2018 edition
 
 error: aborting due to 2 previous errors
 

From 5d8fd8b6cd1c8935bcc67b0763efba431e2eff73 Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Tue, 26 Feb 2019 22:42:50 +0300
Subject: [PATCH 25/25] Mention `unwind(aborts)` in diagnostics for `#[unwind]`

Simplify input validation for `#[unwind]`, add tests
---
 src/libsyntax/attr/builtin.rs                 | 48 +++++++------------
 src/libsyntax/feature_gate.rs                 |  2 +-
 src/test/ui/malformed/malformed-unwind-1.rs   | 11 +++++
 .../ui/malformed/malformed-unwind-1.stderr    | 14 ++++++
 src/test/ui/malformed/malformed-unwind-2.rs   | 11 +++++
 .../ui/malformed/malformed-unwind-2.stderr    | 15 ++++++
 6 files changed, 69 insertions(+), 32 deletions(-)
 create mode 100644 src/test/ui/malformed/malformed-unwind-1.rs
 create mode 100644 src/test/ui/malformed/malformed-unwind-1.stderr
 create mode 100644 src/test/ui/malformed/malformed-unwind-2.rs
 create mode 100644 src/test/ui/malformed/malformed-unwind-2.stderr

diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs
index e84adc01cf04a..f7a000935caf0 100644
--- a/src/libsyntax/attr/builtin.rs
+++ b/src/libsyntax/attr/builtin.rs
@@ -7,7 +7,7 @@ use crate::parse::ParseSess;
 use errors::{Applicability, Handler};
 use syntax_pos::{symbol::Symbol, Span};
 
-use super::{list_contains_name, mark_used, MetaItemKind};
+use super::{mark_used, MetaItemKind};
 
 enum AttrError {
     MultipleItem(Name),
@@ -79,40 +79,26 @@ pub enum UnwindAttr {
 
 /// Determine what `#[unwind]` attribute is present in `attrs`, if any.
 pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Option<UnwindAttr> {
-    let syntax_error = |attr: &Attribute| {
-        mark_used(attr);
-        diagnostic.map(|d| {
-            span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
-        });
-        None
-    };
-
     attrs.iter().fold(None, |ia, attr| {
-        if attr.path != "unwind" {
-            return ia;
-        }
-        let meta = match attr.meta() {
-            Some(meta) => meta.node,
-            None => return ia,
-        };
-        match meta {
-            MetaItemKind::Word => {
-                syntax_error(attr)
-            }
-            MetaItemKind::List(ref items) => {
-                mark_used(attr);
-                if items.len() != 1 {
-                    syntax_error(attr)
-                } else if list_contains_name(&items[..], "allowed") {
-                    Some(UnwindAttr::Allowed)
-                } else if list_contains_name(&items[..], "aborts") {
-                    Some(UnwindAttr::Aborts)
-                } else {
-                    syntax_error(attr)
+        if attr.check_name("unwind") {
+            if let Some(meta) = attr.meta() {
+                if let MetaItemKind::List(items) = meta.node {
+                    if items.len() == 1 {
+                        if items[0].check_name("allowed") {
+                            return Some(UnwindAttr::Allowed);
+                        } else if items[0].check_name("aborts") {
+                            return Some(UnwindAttr::Aborts);
+                        }
+                    }
+
+                    diagnostic.map(|d| {
+                        span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute");
+                    });
                 }
             }
-            _ => ia,
         }
+
+        ia
     })
 }
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index cc1953e69d4ca..93c6de274eeea 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1173,7 +1173,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu
            "dropck_eyepatch",
            "may_dangle has unstable semantics and may be removed in the future",
            cfg_fn!(dropck_eyepatch))),
-    ("unwind", Whitelisted, template!(List: "allowed"), Gated(Stability::Unstable,
+    ("unwind", Whitelisted, template!(List: "allowed|aborts"), Gated(Stability::Unstable,
                                   "unwind_attributes",
                                   "#[unwind] is experimental",
                                   cfg_fn!(unwind_attributes))),
diff --git a/src/test/ui/malformed/malformed-unwind-1.rs b/src/test/ui/malformed/malformed-unwind-1.rs
new file mode 100644
index 0000000000000..e34c288c027c2
--- /dev/null
+++ b/src/test/ui/malformed/malformed-unwind-1.rs
@@ -0,0 +1,11 @@
+#![feature(unwind_attributes)]
+
+#[unwind]
+//~^ ERROR attribute must be of the form
+extern "C" fn f1() {}
+
+#[unwind = ""]
+//~^ ERROR attribute must be of the form
+extern "C" fn f2() {}
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-unwind-1.stderr b/src/test/ui/malformed/malformed-unwind-1.stderr
new file mode 100644
index 0000000000000..852136eed91bd
--- /dev/null
+++ b/src/test/ui/malformed/malformed-unwind-1.stderr
@@ -0,0 +1,14 @@
+error: attribute must be of the form `#[unwind(allowed|aborts)]`
+  --> $DIR/malformed-unwind-1.rs:3:1
+   |
+LL | #[unwind]
+   | ^^^^^^^^^
+
+error: attribute must be of the form `#[unwind(allowed|aborts)]`
+  --> $DIR/malformed-unwind-1.rs:7:1
+   |
+LL | #[unwind = ""]
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/malformed/malformed-unwind-2.rs b/src/test/ui/malformed/malformed-unwind-2.rs
new file mode 100644
index 0000000000000..d4955b4330930
--- /dev/null
+++ b/src/test/ui/malformed/malformed-unwind-2.rs
@@ -0,0 +1,11 @@
+#![feature(unwind_attributes)]
+
+#[unwind(allowed, aborts)]
+//~^ ERROR malformed `#[unwind]` attribute
+extern "C" fn f1() {}
+
+#[unwind(unsupported)]
+//~^ ERROR malformed `#[unwind]` attribute
+extern "C" fn f2() {}
+
+fn main() {}
diff --git a/src/test/ui/malformed/malformed-unwind-2.stderr b/src/test/ui/malformed/malformed-unwind-2.stderr
new file mode 100644
index 0000000000000..88fc4e00a2fd3
--- /dev/null
+++ b/src/test/ui/malformed/malformed-unwind-2.stderr
@@ -0,0 +1,15 @@
+error[E0633]: malformed `#[unwind]` attribute
+  --> $DIR/malformed-unwind-2.rs:3:1
+   |
+LL | #[unwind(allowed, aborts)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0633]: malformed `#[unwind]` attribute
+  --> $DIR/malformed-unwind-2.rs:7:1
+   |
+LL | #[unwind(unsupported)]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0633`.