From 14999dd74b38ca79b80772f4f33425574faff89a Mon Sep 17 00:00:00 2001
From: Andreas Molzer <andreas.molzer@gmx.de>
Date: Wed, 29 Jan 2020 21:26:16 +0100
Subject: [PATCH 01/18] Add methods to leak RefCell borrows to references

Usually, references to the interior are only created by the `Deref` and
`DerefMut` impl of the guards `Ref` and `RefMut`. Note that `RefCell`
already has to cope with leaks of such guards which, when it occurs,
effectively makes it impossible to ever acquire a mutable guard or any
guard for `Ref` and `RefMut` respectively. It is already safe to use
this to create a reference to the inner of the ref cell that lives as
long as the reference to the `RefCell` itself, e.g.

```rust
fn leak(r: &RefCell<usize>) -> Option<&usize> {
    let guard = r.try_borrow().ok()?;
    let leaked = Box::leak(Box::new(guard));
    Some(&*leaked)
}
```

The newly added methods allow the same reference conversion without an
indirection over a leaked allocation and composing with both borrow and
try_borrow without additional method combinations.
---
 src/libcore/cell.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index e7eecf7540ad7..b1d799953e710 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1245,6 +1245,38 @@ impl<'b, T: ?Sized> Ref<'b, T> {
         let borrow = orig.borrow.clone();
         (Ref { value: a, borrow }, Ref { value: b, borrow: orig.borrow })
     }
+
+    /// Convert into a reference to the underlying data.
+    ///
+    /// The underlying `RefCell` can never be mutably borrowed from again and will always appear
+    /// already immutably borrowed. It can still be immutably borrowed until more than `isize::MAX`
+    /// `Ref`s of this `RefCell` have been leaked, through this function or another leak, in total.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `Ref::leak(...)`. A method would interfere with methods of the
+    /// same name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_leak)]
+    /// use std::cell::{RefCell, Ref};
+    /// let cell = RefCell::new(0);
+    ///
+    /// let value = Ref::leak(cell.borrow());
+    /// assert_eq!(*value, 0);
+    ///
+    /// assert!(cell.try_borrow().is_ok());
+    /// assert!(cell.try_borrow_mut().is_err());
+    /// ```
+    #[unstable(feature = "cell_leak", issue = "none")]
+    pub fn leak(orig: Ref<'b, T>) -> &'b T {
+        // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never
+        // goes back to UNUSED again. No further references can be created from the original cell,
+        // making the current borrow the only reference for the remaining lifetime.
+        mem::forget(orig.borrow);
+        orig.value
+    }
 }
 
 #[unstable(feature = "coerce_unsized", issue = "27732")]
@@ -1330,6 +1362,37 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
         let borrow = orig.borrow.clone();
         (RefMut { value: a, borrow }, RefMut { value: b, borrow: orig.borrow })
     }
+
+    /// Convert into a mutable reference to the underlying data.
+    ///
+    /// The underlying `RefCell` can not be borrowed from again and will always appear already
+    /// mutably borrowed, making the returned reference the only to the interior.
+    ///
+    /// This is an associated function that needs to be used as
+    /// `RefMut::leak(...)`. A method would interfere with methods of the
+    /// same name on the contents of a `RefCell` used through `Deref`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(cell_leak)]
+    /// use std::cell::{RefCell, RefMut};
+    /// let cell = RefCell::new(0);
+    ///
+    /// let value = RefMut::leak(cell.borrow_mut());
+    /// assert_eq!(*value, 0);
+    /// *value = 1;
+    ///
+    /// assert!(cell.try_borrow_mut().is_err());
+    /// ```
+    #[unstable(feature = "cell_leak", issue = "none")]
+    pub fn leak(orig: RefMut<'b, T>) -> &'b mut T {
+        // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never
+        // goes back to UNUSED again. No further references can be created from the original cell,
+        // making the current borrow the only reference for the remaining lifetime.
+        mem::forget(orig.borrow);
+        orig.value
+    }
 }
 
 struct BorrowRefMut<'b> {

From 178de46116b4fc8c1d9b30007f5e5ed24c809881 Mon Sep 17 00:00:00 2001
From: Mark Rousskov <mark.simulacrum@gmail.com>
Date: Thu, 26 Dec 2019 12:55:13 -0500
Subject: [PATCH 02/18] Add primitive module to libcore/std

This re-exports the primitive types from libcore at `core::primitive` to allow
macro authors to have a reliable location to use them from.
---
 src/libcore/lib.rs                            |  3 +
 src/libcore/primitive.rs                      | 67 +++++++++++++++++++
 src/libstd/lib.rs                             |  5 +-
 .../resolve/resolve-primitive-fallback.stderr |  5 ++
 src/test/ui/shadow-bool.rs                    | 18 +++++
 5 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100644 src/libcore/primitive.rs
 create mode 100644 src/test/ui/shadow-bool.rs

diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 1fd70e1a1b049..257a6d371b730 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -262,6 +262,9 @@ mod bool;
 mod tuple;
 mod unit;
 
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub mod primitive;
+
 // Pull in the `core_arch` crate directly into libcore. The contents of
 // `core_arch` are in a different repository: rust-lang/stdarch.
 //
diff --git a/src/libcore/primitive.rs b/src/libcore/primitive.rs
new file mode 100644
index 0000000000000..d37bbfaf5dfd4
--- /dev/null
+++ b/src/libcore/primitive.rs
@@ -0,0 +1,67 @@
+//! This module reexports the primitive types to allow usage that is not
+//! possibly shadowed by other declared types.
+//!
+//! This is normally only useful in macro generated code.
+//!
+//! An example of this is when generating a new struct and an impl for it:
+//!
+//! ```rust,compile_fail
+//! pub struct bool;
+//!
+//! impl QueryId for bool {
+//!     const SOME_PROPERTY: bool = true;
+//! }
+//!
+//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
+//! ```
+//!
+//! Note that the `SOME_PROPERTY` associated constant would not compile, as its
+//! type `bool` refers to the struct, rather than to the primitive bool type.
+//!
+//! A correct implementation could look like:
+//!
+//! ```rust
+//! # #[allow(non_camel_case_types)]
+//! pub struct bool;
+//!
+//! impl QueryId for bool {
+//!     const SOME_PROPERTY: core::primitive::bool = true;
+//! }
+//!
+//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
+//! ```
+
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use bool;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use char;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use f32;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use f64;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use i128;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use i16;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use i32;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use i64;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use i8;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use isize;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use str;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use u128;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use u16;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use u32;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use u64;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use u8;
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use usize;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index f9c9f224730da..2b54481ab5670 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -233,12 +233,12 @@
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 #![feature(allow_internal_unstable)]
-#![feature(atomic_mut_ptr)]
 #![feature(arbitrary_self_types)]
 #![feature(array_error_internals)]
 #![feature(asm)]
 #![feature(assoc_int_consts)]
 #![feature(associated_type_bounds)]
+#![feature(atomic_mut_ptr)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
 #![feature(cfg_target_has_atomic)]
@@ -550,6 +550,9 @@ pub use core::{
     trace_macros,
 };
 
+#[stable(feature = "core_primitive", since = "1.42.0")]
+pub use core::primitive;
+
 // Include a number of private modules that exist solely to provide
 // the rustdoc documentation for primitive types. Using `include!`
 // because rustdoc only looks for these modules at the crate level.
diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr
index 92c2a03298381..72a854346fad0 100644
--- a/src/test/ui/resolve/resolve-primitive-fallback.stderr
+++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr
@@ -9,6 +9,11 @@ error[E0412]: cannot find type `u8` in the crate root
    |
 LL |     let _: ::u8;
    |              ^^ not found in the crate root
+   |
+help: possible candidate is found in another module, you can import it into scope
+   |
+LL | use std::primitive::u8;
+   |
 
 error[E0061]: this function takes 0 parameters but 1 parameter was supplied
   --> $DIR/resolve-primitive-fallback.rs:3:5
diff --git a/src/test/ui/shadow-bool.rs b/src/test/ui/shadow-bool.rs
new file mode 100644
index 0000000000000..f290a329eaac2
--- /dev/null
+++ b/src/test/ui/shadow-bool.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+mod bar {
+    pub trait QueryId {
+        const SOME_PROPERTY: bool;
+    }
+}
+
+use bar::QueryId;
+
+#[allow(non_camel_case_types)]
+pub struct bool;
+
+impl QueryId for bool {
+    const SOME_PROPERTY: core::primitive::bool = true;
+}
+
+fn main() {}

From 99b4357f1763f7d98b9b78221207e09d075513b1 Mon Sep 17 00:00:00 2001
From: Andreas Molzer <andreas.molzer@gmx.de>
Date: Wed, 12 Feb 2020 16:56:09 +0100
Subject: [PATCH 03/18] Add tracking number, adjust documentation wording

---
 src/libcore/cell.rs | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index b1d799953e710..17222b27b2d70 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1249,8 +1249,9 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// Convert into a reference to the underlying data.
     ///
     /// The underlying `RefCell` can never be mutably borrowed from again and will always appear
-    /// already immutably borrowed. It can still be immutably borrowed until more than `isize::MAX`
-    /// `Ref`s of this `RefCell` have been leaked, through this function or another leak, in total.
+    /// already immutably borrowed. It is not a good idea to leak more than a constant number of
+    /// references. The `RefCell` can be immutably borrowed again if only a smaller number of leaks
+    /// have occurred in total.
     ///
     /// This is an associated function that needs to be used as
     /// `Ref::leak(...)`. A method would interfere with methods of the
@@ -1269,7 +1270,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// assert!(cell.try_borrow().is_ok());
     /// assert!(cell.try_borrow_mut().is_err());
     /// ```
-    #[unstable(feature = "cell_leak", issue = "none")]
+    #[unstable(feature = "cell_leak", issue = "69099")]
     pub fn leak(orig: Ref<'b, T>) -> &'b T {
         // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never
         // goes back to UNUSED again. No further references can be created from the original cell,
@@ -1385,7 +1386,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     ///
     /// assert!(cell.try_borrow_mut().is_err());
     /// ```
-    #[unstable(feature = "cell_leak", issue = "none")]
+    #[unstable(feature = "cell_leak", issue = "69099")]
     pub fn leak(orig: RefMut<'b, T>) -> &'b mut T {
         // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never
         // goes back to UNUSED again. No further references can be created from the original cell,

From bec5d37ee19c33bec96ed235f0197317d3728e0a Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 16 Feb 2020 14:44:16 +0100
Subject: [PATCH 04/18] debug_assert a few more raw pointer methods

---
 src/libcore/intrinsics.rs |  9 +++++----
 src/libcore/ptr/mod.rs    | 12 +++++++++++-
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 2cee23a5c752c..9a23b54dfa0a5 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1423,13 +1423,14 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
 }
 
 /// Checks whether the regions of memory starting at `src` and `dst` of size
-/// `count * size_of::<T>()` overlap.
-fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
+/// `count * size_of::<T>()` do *not* overlap.
+pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
     let src_usize = src as usize;
     let dst_usize = dst as usize;
     let size = mem::size_of::<T>().checked_mul(count).unwrap();
     let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
-    size > diff
+    let overlaps = size > diff;
+    !overlaps
 }
 
 /// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
@@ -1524,7 +1525,7 @@ pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
 
     debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer");
     debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer");
-    debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory");
+    debug_assert!(is_nonoverlapping(src, dst, count), "attempt to copy to overlapping memory");
     copy_nonoverlapping(src, dst, count)
 }
 
diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs
index 0ee50966f968c..ce21773165a6a 100644
--- a/src/libcore/ptr/mod.rs
+++ b/src/libcore/ptr/mod.rs
@@ -72,7 +72,7 @@
 use crate::cmp::Ordering;
 use crate::fmt;
 use crate::hash;
-use crate::intrinsics;
+use crate::intrinsics::{self, is_aligned_and_not_null, is_nonoverlapping};
 use crate::mem::{self, MaybeUninit};
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -389,6 +389,10 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
 #[inline]
 #[stable(feature = "swap_nonoverlapping", since = "1.27.0")]
 pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
+    debug_assert!(is_aligned_and_not_null(x), "attempt to swap unaligned or null pointer");
+    debug_assert!(is_aligned_and_not_null(y), "attempt to swap unaligned or null pointer");
+    debug_assert!(is_nonoverlapping(x, y, count), "attempt to swap overlapping memory");
+
     let x = x as *mut u8;
     let y = y as *mut u8;
     let len = mem::size_of::<T>() * count;
@@ -612,6 +616,7 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn read<T>(src: *const T) -> T {
+    // `copy_nonoverlapping` takes care of debug_assert.
     let mut tmp = MaybeUninit::<T>::uninit();
     copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
     tmp.assume_init()
@@ -703,6 +708,7 @@ pub unsafe fn read<T>(src: *const T) -> T {
 #[inline]
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
 pub unsafe fn read_unaligned<T>(src: *const T) -> T {
+    // `copy_nonoverlapping` takes care of debug_assert.
     let mut tmp = MaybeUninit::<T>::uninit();
     copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::<T>());
     tmp.assume_init()
@@ -795,6 +801,7 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn write<T>(dst: *mut T, src: T) {
+    debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
     intrinsics::move_val_init(&mut *dst, src)
 }
 
@@ -887,6 +894,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 #[inline]
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
 pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
+    // `copy_nonoverlapping` takes care of debug_assert.
     copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::<T>());
     mem::forget(src);
 }
@@ -956,6 +964,7 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
 #[inline]
 #[stable(feature = "volatile", since = "1.9.0")]
 pub unsafe fn read_volatile<T>(src: *const T) -> T {
+    debug_assert!(is_aligned_and_not_null(src), "attempt to read from unaligned or null pointer");
     intrinsics::volatile_load(src)
 }
 
@@ -1024,6 +1033,7 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 #[inline]
 #[stable(feature = "volatile", since = "1.9.0")]
 pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
+    debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer");
     intrinsics::volatile_store(dst, src);
 }
 

From 7a6b451984fffee4eb4c8161989aaa3d20cb6855 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 17 Feb 2020 21:43:51 +0100
Subject: [PATCH 05/18] increase slack for stack size test

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

diff --git a/src/test/ui/issues/issue-40883.rs b/src/test/ui/issues/issue-40883.rs
index 37e61b1b0e603..5a51acc73e85c 100644
--- a/src/test/ui/issues/issue-40883.rs
+++ b/src/test/ui/issues/issue-40883.rs
@@ -78,8 +78,8 @@ fn verify_stack_usage(before_ptr: *mut Vec<Big>) {
     let stack_usage = isize::abs(
         (&mut stack_var as *mut _ as isize) -
             (before_ptr as isize)) as usize;
-    // give space for 2 copies of `Big` + 128 "misc" bytes.
-    if stack_usage > mem::size_of::<Big>() * 2 + 128 {
+    // give space for 2 copies of `Big` + 256 "misc" bytes.
+    if stack_usage > mem::size_of::<Big>() * 2 + 256 {
         panic!("used {} bytes of stack, but `struct Big` is only {} bytes",
                stack_usage, mem::size_of::<Big>());
     }

From e355a330772a7b605649651f7e670ea636e73a6e Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Sun, 23 Feb 2020 01:29:36 +0300
Subject: [PATCH 06/18] Deduplicate identifier printing a bit

---
 src/librustc_ast_pretty/pprust.rs | 42 ++-----------------
 src/librustc_hir/print.rs         |  6 +--
 src/librustc_span/symbol.rs       | 67 +++++++++++++++++++++++++++----
 3 files changed, 66 insertions(+), 49 deletions(-)

diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 27cef8502a1d1..4e69253c34bf6 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -3,7 +3,7 @@ use crate::pp::{self, Breaks};
 
 use rustc_span::edition::Edition;
 use rustc_span::source_map::{SourceMap, Spanned};
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, IdentPrinter};
 use rustc_span::{BytePos, FileName, Span};
 use syntax::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
 use syntax::ast::{Attribute, GenericArg, MacArgs};
@@ -196,40 +196,6 @@ pub fn literal_to_string(lit: token::Lit) -> String {
     out
 }
 
-/// Print an ident from AST, `$crate` is converted into its respective crate name.
-pub fn ast_ident_to_string(ident: ast::Ident, is_raw: bool) -> String {
-    ident_to_string(ident.name, is_raw, Some(ident.span))
-}
-
-// AST pretty-printer is used as a fallback for turning AST structures into token streams for
-// proc macros. Additionally, proc macros may stringify their input and expect it survive the
-// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
-// So we need to somehow pretty-print `$crate` in a way preserving at least some of its
-// hygiene data, most importantly name of the crate it refers to.
-// As a result we print `$crate` as `crate` if it refers to the local crate
-// and as `::other_crate_name` if it refers to some other crate.
-// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing,
-// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
-// so we should not perform this lossy conversion if the top level call to the pretty-printer was
-// done for a token stream or a single token.
-fn ident_to_string(name: ast::Name, is_raw: bool, convert_dollar_crate: Option<Span>) -> String {
-    if is_raw {
-        format!("r#{}", name)
-    } else {
-        if name == kw::DollarCrate {
-            if let Some(span) = convert_dollar_crate {
-                let converted = span.ctxt().dollar_crate_name();
-                return if converted.is_path_segment_keyword() {
-                    converted.to_string()
-                } else {
-                    format!("::{}", converted)
-                };
-            }
-        }
-        name.to_string()
-    }
-}
-
 /// Print the token kind precisely, without converting `$crate` into its respective crate name.
 pub fn token_kind_to_string(tok: &TokenKind) -> String {
     token_kind_to_string_ext(tok, None)
@@ -280,7 +246,7 @@ fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option<Span>)
         token::Literal(lit) => literal_to_string(lit),
 
         /* Name components */
-        token::Ident(s, is_raw) => ident_to_string(s, is_raw, convert_dollar_crate),
+        token::Ident(s, is_raw) => IdentPrinter::new(s, is_raw, convert_dollar_crate).to_string(),
         token::Lifetime(s) => s.to_string(),
 
         /* Other */
@@ -315,7 +281,7 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
         token::NtBlock(ref e) => block_to_string(e),
         token::NtStmt(ref e) => stmt_to_string(e),
         token::NtPat(ref e) => pat_to_string(e),
-        token::NtIdent(e, is_raw) => ast_ident_to_string(e, is_raw),
+        token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(),
         token::NtLifetime(e) => e.to_string(),
         token::NtLiteral(ref e) => expr_to_string(e),
         token::NtTT(ref tree) => tt_to_string(tree.clone()),
@@ -819,7 +785,7 @@ impl<'a> PrintState<'a> for State<'a> {
     }
 
     fn print_ident(&mut self, ident: ast::Ident) {
-        self.s.word(ast_ident_to_string(ident, ident.is_raw_guess()));
+        self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
         self.ann.post(self, AnnNode::Ident(&ident))
     }
 
diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs
index e49f99fb717a3..92bd8b1ba5f84 100644
--- a/src/librustc_hir/print.rs
+++ b/src/librustc_hir/print.rs
@@ -1,8 +1,8 @@
 use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
 use rustc_ast_pretty::pp::{self, Breaks};
-use rustc_ast_pretty::pprust::{self, Comments, PrintState};
+use rustc_ast_pretty::pprust::{Comments, PrintState};
 use rustc_span::source_map::{SourceMap, Spanned};
-use rustc_span::symbol::kw;
+use rustc_span::symbol::{kw, IdentPrinter};
 use rustc_span::{self, BytePos, FileName};
 use rustc_target::spec::abi::Abi;
 use syntax::ast;
@@ -126,7 +126,7 @@ impl<'a> PrintState<'a> for State<'a> {
     }
 
     fn print_ident(&mut self, ident: ast::Ident) {
-        self.s.word(pprust::ast_ident_to_string(ident, ident.is_raw_guess()));
+        self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string());
         self.ann.post(self, AnnNode::Name(&ident.name))
     }
 
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 97708d91d7e2a..b8e5ea97f4e47 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -893,19 +893,17 @@ impl Hash for Ident {
 
 impl fmt::Debug for Ident {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.is_raw_guess() {
-            write!(f, "r#")?;
-        }
-        write!(f, "{}{:?}", self.name, self.span.ctxt())
+        fmt::Display::fmt(self, f)?;
+        fmt::Debug::fmt(&self.span.ctxt(), f)
     }
 }
 
+/// This implementation is supposed to be used in error messages, so it's expected to be identical
+/// to printing the original identifier token written in source code (`token_to_string`),
+/// except that AST identifiers don't keep the rawness flag, so we have to guess it.
 impl fmt::Display for Ident {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.is_raw_guess() {
-            write!(f, "r#")?;
-        }
-        fmt::Display::fmt(&self.name, f)
+        fmt::Display::fmt(&IdentPrinter::new(self.name, self.is_raw_guess(), None), f)
     }
 }
 
@@ -929,6 +927,59 @@ impl UseSpecializedDecodable for Ident {
     }
 }
 
+/// This is the most general way to print identifiers.
+/// AST pretty-printer is used as a fallback for turning AST structures into token streams for
+/// proc macros. Additionally, proc macros may stringify their input and expect it survive the
+/// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
+/// So we need to somehow pretty-print `$crate` in a way preserving at least some of its
+/// hygiene data, most importantly name of the crate it refers to.
+/// As a result we print `$crate` as `crate` if it refers to the local crate
+/// and as `::other_crate_name` if it refers to some other crate.
+/// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing,
+/// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
+/// so we should not perform this lossy conversion if the top level call to the pretty-printer was
+/// done for a token stream or a single token.
+pub struct IdentPrinter {
+    symbol: Symbol,
+    is_raw: bool,
+    /// Span used for retrieving the crate name to which `$crate` refers to,
+    /// if this field is `None` then the `$crate` conversion doesn't happen.
+    convert_dollar_crate: Option<Span>,
+}
+
+impl IdentPrinter {
+    /// The most general `IdentPrinter` constructor. Do not use this.
+    pub fn new(symbol: Symbol, is_raw: bool, convert_dollar_crate: Option<Span>) -> IdentPrinter {
+        IdentPrinter { symbol, is_raw, convert_dollar_crate }
+    }
+
+    /// This implementation is supposed to be used when printing identifiers
+    /// as a part of pretty-printing for larger AST pieces.
+    /// Do not use this either.
+    pub fn for_ast_ident(ident: Ident, is_raw: bool) -> IdentPrinter {
+        IdentPrinter::new(ident.name, is_raw, Some(ident.span))
+    }
+}
+
+impl fmt::Display for IdentPrinter {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.is_raw {
+            f.write_str("r#")?;
+        } else {
+            if self.symbol == kw::DollarCrate {
+                if let Some(span) = self.convert_dollar_crate {
+                    let converted = span.ctxt().dollar_crate_name();
+                    if !converted.is_path_segment_keyword() {
+                        f.write_str("::")?;
+                    }
+                    return fmt::Display::fmt(&converted, f);
+                }
+            }
+        }
+        fmt::Display::fmt(&self.symbol, f)
+    }
+}
+
 /// An interned string.
 ///
 /// Internally, a `Symbol` is implemented as an index, and all operations

From 9c3ee1bc351fcfabcfd47947dc44b0c020427181 Mon Sep 17 00:00:00 2001
From: David Tolnay <dtolnay@gmail.com>
Date: Sun, 23 Feb 2020 23:59:39 -0800
Subject: [PATCH 07/18] Bump core::primitive to 1.43

---
 src/libcore/lib.rs       |  2 +-
 src/libcore/primitive.rs | 34 +++++++++++++++++-----------------
 src/libstd/lib.rs        |  2 +-
 3 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 257a6d371b730..b939462afc767 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -262,7 +262,7 @@ mod bool;
 mod tuple;
 mod unit;
 
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub mod primitive;
 
 // Pull in the `core_arch` crate directly into libcore. The contents of
diff --git a/src/libcore/primitive.rs b/src/libcore/primitive.rs
index d37bbfaf5dfd4..e20b2c5c9382a 100644
--- a/src/libcore/primitive.rs
+++ b/src/libcore/primitive.rs
@@ -31,37 +31,37 @@
 //! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; }
 //! ```
 
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use bool;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use char;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use f32;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use f64;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use i128;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use i16;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use i32;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use i64;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use i8;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use isize;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use str;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use u128;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use u16;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use u32;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use u64;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use u8;
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use usize;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 2b54481ab5670..a495d29cc47c5 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -550,7 +550,7 @@ pub use core::{
     trace_macros,
 };
 
-#[stable(feature = "core_primitive", since = "1.42.0")]
+#[stable(feature = "core_primitive", since = "1.43.0")]
 pub use core::primitive;
 
 // Include a number of private modules that exist solely to provide

From 329022dfad7199053cbe225e8d7d13ebbd5eb230 Mon Sep 17 00:00:00 2001
From: Andreas Molzer <andreas.molzer@gmx.de>
Date: Mon, 24 Feb 2020 11:23:47 +0100
Subject: [PATCH 08/18] Address method comments

---
 src/libcore/cell.rs | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 17222b27b2d70..b6d5c6ae27db7 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -1272,9 +1272,8 @@ impl<'b, T: ?Sized> Ref<'b, T> {
     /// ```
     #[unstable(feature = "cell_leak", issue = "69099")]
     pub fn leak(orig: Ref<'b, T>) -> &'b T {
-        // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never
-        // goes back to UNUSED again. No further references can be created from the original cell,
-        // making the current borrow the only reference for the remaining lifetime.
+        // By forgetting this Ref we ensure that the borrow counter in the RefCell never goes back
+        // to UNUSED again. No further mutable references can be created from the original cell.
         mem::forget(orig.borrow);
         orig.value
     }

From 5ae4500eff740b5935fc24b23e3c4be9789caf37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Mon, 24 Feb 2020 14:42:14 +0100
Subject: [PATCH 09/18] remove redundant clones in librustc_mir_build and
 librustc_data_structures

---
 src/librustc_data_structures/obligation_forest/mod.rs | 4 ++--
 src/librustc_mir_build/build/matches/mod.rs           | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 334daddba8820..6711a49b2b7c1 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -314,7 +314,7 @@ impl<O: ForestObligation> ObligationForest<O> {
             return Ok(());
         }
 
-        match self.active_cache.entry(obligation.as_cache_key().clone()) {
+        match self.active_cache.entry(obligation.as_cache_key()) {
             Entry::Occupied(o) => {
                 let node = &mut self.nodes[*o.get()];
                 if let Some(parent_index) = parent {
@@ -385,7 +385,7 @@ impl<O: ForestObligation> ObligationForest<O> {
         self.error_cache
             .entry(node.obligation_tree_id)
             .or_default()
-            .insert(node.obligation.as_cache_key().clone());
+            .insert(node.obligation.as_cache_key());
     }
 
     /// Performs a pass through the obligation list. This must
diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs
index f900ae45b94d6..7995125524314 100644
--- a/src/librustc_mir_build/build/matches/mod.rs
+++ b/src/librustc_mir_build/build/matches/mod.rs
@@ -649,7 +649,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
             }
             PatKind::Or { ref pats } => {
-                self.visit_bindings(&pats[0], pattern_user_ty.clone(), f);
+                self.visit_bindings(&pats[0], pattern_user_ty, f);
             }
         }
     }

From d4a005bd03dd2ef229bb809d128f9b31c159c18e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Mon, 24 Feb 2020 14:48:40 +0100
Subject: [PATCH 10/18] librustc{, codegen_ssa,infer,mir_build}: don't clone
 types that are copy

---
 src/librustc/ty/context.rs                             | 2 +-
 src/librustc/ty/mod.rs                                 | 2 +-
 src/librustc/ty/query/job.rs                           | 2 +-
 src/librustc_codegen_ssa/mir/constant.rs               | 2 +-
 src/librustc_infer/infer/lexical_region_resolve/mod.rs | 2 +-
 src/librustc_mir_build/build/expr/into.rs              | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index e59738d888608..c027d6f61b01f 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1526,7 +1526,7 @@ impl<'tcx> GlobalCtxt<'tcx> {
         ty::tls::with_related_context(tcx, |icx| {
             let new_icx = ty::tls::ImplicitCtxt {
                 tcx,
-                query: icx.query.clone(),
+                query: icx.query,
                 diagnostics: icx.diagnostics,
                 layout_depth: icx.layout_depth,
                 task_deps: icx.task_deps,
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index a195c944ff28d..d17ef3a6c9a8c 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1447,7 +1447,7 @@ impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> {
 impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&TraitRef<'tcx>> {
     fn to_predicate(&self) -> Predicate<'tcx> {
         ty::Predicate::Trait(
-            ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }),
+            ty::Binder::dummy(ty::TraitPredicate { trait_ref: *self.value }),
             self.constness,
         )
     }
diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs
index 8aae57e72cd52..3394fed840222 100644
--- a/src/librustc/ty/query/job.rs
+++ b/src/librustc/ty/query/job.rs
@@ -173,7 +173,7 @@ impl<'tcx> QueryLatch<'tcx> {
                 return CycleError { usage, cycle };
             }
 
-            current_job = info.job.parent.clone();
+            current_job = info.job.parent;
         }
 
         panic!("did not find a cycle")
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index 9ceb75a603bc4..4248627dccaf2 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -31,7 +31,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             _ => {
                 let val = self.eval_mir_constant(constant)?;
                 let ty = self.monomorphize(&constant.literal.ty);
-                Ok(OperandRef::from_const(bx, val.clone(), ty))
+                Ok(OperandRef::from_const(bx, val, ty))
             }
         }
     }
diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs
index 0b5536219e566..fc9f3bb076745 100644
--- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs
@@ -848,7 +848,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> {
         for upper_bound in &upper_bounds {
             if let ty::RePlaceholder(p) = upper_bound.region {
                 if node_universe.cannot_name(p.universe) {
-                    let origin = self.var_infos[node_idx].origin.clone();
+                    let origin = self.var_infos[node_idx].origin;
                     errors.push(RegionResolutionError::UpperBoundUniverseConflict(
                         node_idx,
                         origin,
diff --git a/src/librustc_mir_build/build/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
index 51b0b5bc7cb0b..4583e244f493d 100644
--- a/src/librustc_mir_build/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -376,7 +376,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     TerminatorKind::Yield {
                         value,
                         resume,
-                        resume_arg: destination.clone(),
+                        resume_arg: *destination,
                         drop: cleanup,
                     },
                 );

From 1892ff7aa6f7d82cbe18a531da3566fbd1939e23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= <matthias.krueger@famsik.de>
Date: Mon, 24 Feb 2020 14:53:55 +0100
Subject: [PATCH 11/18] librustc_macros: remove redundant single component path
 import

---
 src/librustc_macros/src/hash_stable.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/librustc_macros/src/hash_stable.rs b/src/librustc_macros/src/hash_stable.rs
index e6f457dd663c2..dc6ae961e5a6e 100644
--- a/src/librustc_macros/src/hash_stable.rs
+++ b/src/librustc_macros/src/hash_stable.rs
@@ -1,7 +1,6 @@
 use proc_macro2::{self, Ident};
 use quote::quote;
 use syn::{self, parse_quote, Meta, NestedMeta};
-use synstructure;
 
 struct Attributes {
     ignore: bool,

From d134385823525255546deaa930af2d5b1eada0df Mon Sep 17 00:00:00 2001
From: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Date: Mon, 24 Feb 2020 12:06:45 +0300
Subject: [PATCH 12/18] syntax: Remove `Nt(Impl,Trait,Foreign)Item`

---
 src/librustc_ast_pretty/pprust.rs            | 11 ----------
 src/librustc_expand/expand.rs                | 11 +++++++---
 src/librustc_parse/lib.rs                    |  3 ---
 src/librustc_parse/parser/item.rs            |  8 -------
 src/libsyntax/ast.rs                         | 23 ++++++++++++++++++++
 src/libsyntax/mut_visit.rs                   | 13 -----------
 src/libsyntax/token.rs                       |  9 --------
 src/test/ui/proc-macro/trait-fn-args-2015.rs | 14 ++++++++++++
 8 files changed, 45 insertions(+), 47 deletions(-)
 create mode 100644 src/test/ui/proc-macro/trait-fn-args-2015.rs

diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs
index 2b223d92ff198..802d5cfbfc442 100644
--- a/src/librustc_ast_pretty/pprust.rs
+++ b/src/librustc_ast_pretty/pprust.rs
@@ -319,10 +319,7 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String {
         token::NtLifetime(e) => e.to_string(),
         token::NtLiteral(ref e) => expr_to_string(e),
         token::NtTT(ref tree) => tt_to_string(tree.clone()),
-        // FIXME(Centril): merge these variants.
-        token::NtImplItem(ref e) | token::NtTraitItem(ref e) => assoc_item_to_string(e),
         token::NtVis(ref e) => vis_to_string(e),
-        token::NtForeignItem(ref e) => foreign_item_to_string(e),
     }
 }
 
@@ -358,10 +355,6 @@ pub fn item_to_string(i: &ast::Item) -> String {
     to_string(|s| s.print_item(i))
 }
 
-fn assoc_item_to_string(i: &ast::AssocItem) -> String {
-    to_string(|s| s.print_assoc_item(i))
-}
-
 pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String {
     to_string(|s| s.print_generic_params(generic_params))
 }
@@ -404,10 +397,6 @@ pub fn param_to_string(arg: &ast::Param) -> String {
     to_string(|s| s.print_param(arg, false))
 }
 
-fn foreign_item_to_string(arg: &ast::ForeignItem) -> String {
-    to_string(|s| s.print_foreign_item(arg))
-}
-
 fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
     format!("{}{}", to_string(|s| s.print_visibility(vis)), s)
 }
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index bbea066b048d2..8ed7bbf6e1276 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -669,12 +669,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 SyntaxExtensionKind::Attr(expander) => {
                     self.gate_proc_macro_input(&item);
                     self.gate_proc_macro_attr_item(span, &item);
+                    // `Annotatable` can be converted into tokens directly, but we are packing it
+                    // into a nonterminal as a piece of AST to make the produced token stream
+                    // look nicer in pretty-printed form. This may be no longer necessary.
                     let item_tok = TokenTree::token(
                         token::Interpolated(Lrc::new(match item {
                             Annotatable::Item(item) => token::NtItem(item),
-                            Annotatable::TraitItem(item) => token::NtTraitItem(item),
-                            Annotatable::ImplItem(item) => token::NtImplItem(item),
-                            Annotatable::ForeignItem(item) => token::NtForeignItem(item),
+                            Annotatable::TraitItem(item)
+                            | Annotatable::ImplItem(item)
+                            | Annotatable::ForeignItem(item) => {
+                                token::NtItem(P(item.and_then(ast::AssocItem::into_item)))
+                            }
                             Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
                             Annotatable::Expr(expr) => token::NtExpr(expr),
                             Annotatable::Arm(..)
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index a0b8415b3e17e..bd0b189d4fd4d 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -314,9 +314,6 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
         Nonterminal::NtItem(ref item) => {
             prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
         }
-        Nonterminal::NtTraitItem(ref item) | Nonterminal::NtImplItem(ref item) => {
-            prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span)
-        }
         Nonterminal::NtIdent(ident, is_raw) => {
             Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into())
         }
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index d6da627054196..d9e28716c84c7 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -632,16 +632,10 @@ impl<'a> Parser<'a> {
     }
 
     pub fn parse_impl_item(&mut self) -> PResult<'a, Option<Option<P<AssocItem>>>> {
-        maybe_whole!(self, NtImplItem, |x| Some(Some(x)));
         self.parse_assoc_item(|_| true)
     }
 
     pub fn parse_trait_item(&mut self) -> PResult<'a, Option<Option<P<AssocItem>>>> {
-        maybe_whole!(self, NtTraitItem, |x| Some(Some(x)));
-        // This is somewhat dubious; We don't want to allow
-        // param names to be left off if there is a definition...
-        //
-        // We don't allow param names to be left off in edition 2018.
         self.parse_assoc_item(|t| t.span.rust_2018())
     }
 
@@ -834,8 +828,6 @@ impl<'a> Parser<'a> {
 
     /// Parses a foreign item (one in an `extern { ... }` block).
     pub fn parse_foreign_item(&mut self) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
-        maybe_whole!(self, NtForeignItem, |item| Some(Some(item)));
-
         Ok(self.parse_item_(|_| true)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| {
             let kind = match kind {
                 ItemKind::Mac(a) => ForeignItemKind::Macro(a),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 19c705fa99753..62ff4f5183a70 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2441,6 +2441,13 @@ impl Item {
     }
 }
 
+impl<K: IntoItemKind> Item<K> {
+    pub fn into_item(self) -> Item {
+        let Item { attrs, id, span, vis, ident, kind, tokens } = self;
+        Item { attrs, id, span, vis, ident, kind: kind.into_item_kind(), tokens }
+    }
+}
+
 /// `extern` qualifier on a function item or function type.
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
 pub enum Extern {
@@ -2617,6 +2624,10 @@ impl ItemKind {
     }
 }
 
+pub trait IntoItemKind {
+    fn into_item_kind(self) -> ItemKind;
+}
+
 // FIXME(Centril): These definitions should be unmerged;
 // see https://github.com/rust-lang/rust/pull/69194#discussion_r379899975
 pub type ForeignItem = Item<AssocItemKind>;
@@ -2656,3 +2667,15 @@ impl AssocItemKind {
         }
     }
 }
+
+impl IntoItemKind for AssocItemKind {
+    fn into_item_kind(self) -> ItemKind {
+        match self {
+            AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
+            AssocItemKind::Static(a, b, c) => ItemKind::Static(a, b, c),
+            AssocItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d),
+            AssocItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d),
+            AssocItemKind::Macro(a) => ItemKind::Mac(a),
+        }
+    }
+}
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 05bb07cd4b90a..b3abd4fc755e4 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -711,20 +711,7 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
         }
         token::NtPath(path) => vis.visit_path(path),
         token::NtTT(tt) => vis.visit_tt(tt),
-        token::NtImplItem(item) => visit_clobber(item, |item| {
-            // See reasoning above.
-            vis.flat_map_impl_item(item).expect_one("expected visitor to produce exactly one item")
-        }),
-        token::NtTraitItem(item) => visit_clobber(item, |item| {
-            // See reasoning above.
-            vis.flat_map_trait_item(item).expect_one("expected visitor to produce exactly one item")
-        }),
         token::NtVis(visib) => vis.visit_vis(visib),
-        token::NtForeignItem(item) => visit_clobber(item, |item| {
-            // See reasoning above.
-            vis.flat_map_foreign_item(item)
-                .expect_one("expected visitor to produce exactly one item")
-        }),
     }
 }
 
diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs
index 6eeee49881579..52bf50604fb30 100644
--- a/src/libsyntax/token.rs
+++ b/src/libsyntax/token.rs
@@ -712,12 +712,6 @@ pub enum Nonterminal {
     NtPath(ast::Path),
     NtVis(ast::Visibility),
     NtTT(TokenTree),
-    // Used only for passing items to proc macro attributes (they are not
-    // strictly necessary for that, `Annotatable` can be converted into
-    // tokens directly, but doing that naively regresses pretty-printing).
-    NtTraitItem(P<ast::AssocItem>),
-    NtImplItem(P<ast::AssocItem>),
-    NtForeignItem(P<ast::ForeignItem>),
 }
 
 // `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -755,9 +749,6 @@ impl fmt::Debug for Nonterminal {
             NtMeta(..) => f.pad("NtMeta(..)"),
             NtPath(..) => f.pad("NtPath(..)"),
             NtTT(..) => f.pad("NtTT(..)"),
-            NtImplItem(..) => f.pad("NtImplItem(..)"),
-            NtTraitItem(..) => f.pad("NtTraitItem(..)"),
-            NtForeignItem(..) => f.pad("NtForeignItem(..)"),
             NtVis(..) => f.pad("NtVis(..)"),
             NtLifetime(..) => f.pad("NtLifetime(..)"),
         }
diff --git a/src/test/ui/proc-macro/trait-fn-args-2015.rs b/src/test/ui/proc-macro/trait-fn-args-2015.rs
new file mode 100644
index 0000000000000..3a448d4b2201d
--- /dev/null
+++ b/src/test/ui/proc-macro/trait-fn-args-2015.rs
@@ -0,0 +1,14 @@
+// Unnamed arguments in trait functions can be passed through proc macros on 2015 edition.
+
+// check-pass
+// aux-build:test-macros.rs
+
+#[macro_use]
+extern crate test_macros;
+
+trait Tr {
+    #[identity_attr]
+    fn method(u8);
+}
+
+fn main() {}

From 245e15b4ac07e1e780921e3512ae2b9fb2a4a718 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 13:49:19 +0100
Subject: [PATCH 13/18] parse: extract `parse_stmt_item` &
 `parse_stmt_path_start`.

---
 src/librustc_parse/parser/stmt.rs | 65 ++++++++++++++++---------------
 1 file changed, 33 insertions(+), 32 deletions(-)

diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index bbfbe9c20df94..4d86836ff900a 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -58,33 +58,11 @@ impl<'a> Parser<'a> {
         // (1 token), but it fact not a path. Also, we avoid stealing syntax from `parse_item_`.
         if self.token.is_path_start() && !self.token.is_qpath_start() && !self.is_path_start_item()
         {
-            let path = self.parse_path(PathStyle::Expr)?;
-
-            if self.eat(&token::Not) {
-                return self.parse_stmt_mac(lo, attrs.into(), path);
-            }
-
-            let expr = if self.check(&token::OpenDelim(token::Brace)) {
-                self.parse_struct_expr(lo, path, AttrVec::new())?
-            } else {
-                let hi = self.prev_span;
-                self.mk_expr(lo.to(hi), ExprKind::Path(None, path), AttrVec::new())
-            };
-
-            let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
-                let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
-                this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
-            })?;
-            return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Expr(expr))));
+            return self.parse_stmt_path_start(lo, attrs).map(Some);
         }
 
-        // FIXME: Bad copy of attrs
-        let old_directory_ownership =
-            mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
-        let item = self.parse_item_common(attrs.clone(), false, true, |_| true)?;
-        self.directory.ownership = old_directory_ownership;
-
-        if let Some(item) = item {
+        if let Some(item) = self.parse_stmt_item(attrs.clone())? {
+            // FIXME: Bad copy of attrs
             return Ok(Some(self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))));
         }
 
@@ -117,14 +95,37 @@ impl<'a> Parser<'a> {
         Ok(Some(self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))))
     }
 
+    fn parse_stmt_item(&mut self, attrs: Vec<Attribute>) -> PResult<'a, Option<ast::Item>> {
+        let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock);
+        let item = self.parse_item_common(attrs.clone(), false, true, |_| true)?;
+        self.directory.ownership = old;
+        Ok(item)
+    }
+
+    fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, Stmt> {
+        let path = self.parse_path(PathStyle::Expr)?;
+
+        if self.eat(&token::Not) {
+            return self.parse_stmt_mac(lo, attrs.into(), path);
+        }
+
+        let expr = if self.check(&token::OpenDelim(token::Brace)) {
+            self.parse_struct_expr(lo, path, AttrVec::new())?
+        } else {
+            let hi = self.prev_span;
+            self.mk_expr(lo.to(hi), ExprKind::Path(None, path), AttrVec::new())
+        };
+
+        let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
+            let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
+            this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
+        })?;
+        Ok(self.mk_stmt(lo.to(self.prev_span), StmtKind::Expr(expr)))
+    }
+
     /// Parses a statement macro `mac!(args)` provided a `path` representing `mac`.
     /// At this point, the `!` token after the path has already been eaten.
-    fn parse_stmt_mac(
-        &mut self,
-        lo: Span,
-        attrs: AttrVec,
-        path: ast::Path,
-    ) -> PResult<'a, Option<Stmt>> {
+    fn parse_stmt_mac(&mut self, lo: Span, attrs: AttrVec, path: ast::Path) -> PResult<'a, Stmt> {
         let args = self.parse_mac_args()?;
         let delim = args.delim();
         let hi = self.prev_span;
@@ -145,7 +146,7 @@ impl<'a> Parser<'a> {
             let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
             StmtKind::Expr(e)
         };
-        Ok(Some(self.mk_stmt(lo.to(hi), kind)))
+        Ok(self.mk_stmt(lo.to(hi), kind))
     }
 
     /// Error on outer attributes in this context.

From 32295aee6ef45e1602d8df6033be47e06225a319 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Sun, 23 Feb 2020 14:10:03 +0100
Subject: [PATCH 14/18] parse: simplify `parse_stmt_without_recovery`.

---
 src/librustc_parse/parser/stmt.rs | 65 ++++++++++++++-----------------
 1 file changed, 29 insertions(+), 36 deletions(-)

diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index 4d86836ff900a..a1078a59239c7 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -35,39 +35,33 @@ impl<'a> Parser<'a> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
 
-        if self.eat_keyword(kw::Let) {
-            return self.parse_local_mk(lo, attrs.into()).map(Some);
-        }
-        if self.is_kw_followed_by_ident(kw::Mut) {
-            return self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut");
-        }
-        if self.is_kw_followed_by_ident(kw::Auto) {
+        let stmt = if self.eat_keyword(kw::Let) {
+            self.parse_local_mk(lo, attrs.into())?
+        } else if self.is_kw_followed_by_ident(kw::Mut) {
+            self.recover_stmt_local(lo, attrs.into(), "missing keyword", "let mut")?
+        } else if self.is_kw_followed_by_ident(kw::Auto) {
             self.bump(); // `auto`
             let msg = "write `let` instead of `auto` to introduce a new variable";
-            return self.recover_stmt_local(lo, attrs.into(), msg, "let");
-        }
-        if self.is_kw_followed_by_ident(sym::var) {
+            self.recover_stmt_local(lo, attrs.into(), msg, "let")?
+        } else if self.is_kw_followed_by_ident(sym::var) {
             self.bump(); // `var`
             let msg = "write `let` instead of `var` to introduce a new variable";
-            return self.recover_stmt_local(lo, attrs.into(), msg, "let");
-        }
-
-        // Starts like a simple path, being careful to avoid contextual keywords,
-        // e.g., `union`, items with `crate` visibility, or `auto trait` items.
-        // We aim to parse an arbitrary path `a::b` but not something that starts like a path
-        // (1 token), but it fact not a path. Also, we avoid stealing syntax from `parse_item_`.
-        if self.token.is_path_start() && !self.token.is_qpath_start() && !self.is_path_start_item()
+            self.recover_stmt_local(lo, attrs.into(), msg, "let")?
+        } else if self.token.is_path_start()
+            && !self.token.is_qpath_start()
+            && !self.is_path_start_item()
         {
-            return self.parse_stmt_path_start(lo, attrs).map(Some);
-        }
-
-        if let Some(item) = self.parse_stmt_item(attrs.clone())? {
+            // We have avoided contextual keywords like `union`, items with `crate` visibility,
+            // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
+            // that starts like a path (1 token), but it fact not a path.
+            // Also, we avoid stealing syntax from `parse_item_`.
+            self.parse_stmt_path_start(lo, attrs)?
+        } else if let Some(item) = self.parse_stmt_item(attrs.clone())? {
             // FIXME: Bad copy of attrs
-            return Ok(Some(self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))));
+            self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
         }
-
         // Do not attempt to parse an expression if we're done here.
-        if self.token == token::Semi {
+        else if self.token == token::Semi {
             self.error_outer_attrs(&attrs);
             self.bump();
             let mut last_semi = lo;
@@ -82,17 +76,16 @@ impl<'a> Parser<'a> {
                 ExprKind::Tup(Vec::new()),
                 AttrVec::new(),
             ));
-            return Ok(Some(self.mk_stmt(lo.to(last_semi), kind)));
-        }
-
-        if self.token == token::CloseDelim(token::Brace) {
+            self.mk_stmt(lo.to(last_semi), kind)
+        } else if self.token != token::CloseDelim(token::Brace) {
+            // Remainder are line-expr stmts.
+            let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?;
+            self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
+        } else {
             self.error_outer_attrs(&attrs);
             return Ok(None);
-        }
-
-        // Remainder are line-expr stmts.
-        let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?;
-        Ok(Some(self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))))
+        };
+        Ok(Some(stmt))
     }
 
     fn parse_stmt_item(&mut self, attrs: Vec<Attribute>) -> PResult<'a, Option<ast::Item>> {
@@ -168,12 +161,12 @@ impl<'a> Parser<'a> {
         attrs: AttrVec,
         msg: &str,
         sugg: &str,
-    ) -> PResult<'a, Option<Stmt>> {
+    ) -> PResult<'a, Stmt> {
         let stmt = self.parse_local_mk(lo, attrs)?;
         self.struct_span_err(lo, "invalid variable declaration")
             .span_suggestion(lo, msg, sugg.to_string(), Applicability::MachineApplicable)
             .emit();
-        Ok(Some(stmt))
+        Ok(stmt)
     }
 
     fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> {

From 1eb0844f5d4321a7769238af740e6d93d3e966e4 Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Tue, 25 Feb 2020 00:59:39 +0100
Subject: [PATCH 15/18] parse: move condition into guard

---
 src/librustc_parse/parser/stmt.rs | 56 +++++++++++++++----------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index a1078a59239c7..b7bf99e6e1603 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -366,36 +366,36 @@ impl<'a> Parser<'a> {
 
         let mut eat_semi = true;
         match stmt.kind {
-            StmtKind::Expr(ref expr) if self.token != token::Eof => {
-                // expression without semicolon
-                if classify::expr_requires_semi_to_be_stmt(expr) {
-                    // Just check for errors and recover; do not eat semicolon yet.
-                    if let Err(mut e) =
-                        self.expect_one_of(&[], &[token::Semi, token::CloseDelim(token::Brace)])
-                    {
-                        if let TokenKind::DocComment(..) = self.token.kind {
-                            if let Ok(snippet) = self.span_to_snippet(self.token.span) {
-                                let sp = self.token.span;
-                                let marker = &snippet[..3];
-                                let (comment_marker, doc_comment_marker) = marker.split_at(2);
-
-                                e.span_suggestion(
-                                    sp.with_hi(sp.lo() + BytePos(marker.len() as u32)),
-                                    &format!(
-                                        "add a space before `{}` to use a regular comment",
-                                        doc_comment_marker,
-                                    ),
-                                    format!("{} {}", comment_marker, doc_comment_marker),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
+            // Expression without semicolon.
+            StmtKind::Expr(ref expr)
+                if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) =>
+            {
+                // Just check for errors and recover; do not eat semicolon yet.
+                if let Err(mut e) =
+                    self.expect_one_of(&[], &[token::Semi, token::CloseDelim(token::Brace)])
+                {
+                    if let TokenKind::DocComment(..) = self.token.kind {
+                        if let Ok(snippet) = self.span_to_snippet(self.token.span) {
+                            let sp = self.token.span;
+                            let marker = &snippet[..3];
+                            let (comment_marker, doc_comment_marker) = marker.split_at(2);
+
+                            e.span_suggestion(
+                                sp.with_hi(sp.lo() + BytePos(marker.len() as u32)),
+                                &format!(
+                                    "add a space before `{}` to use a regular comment",
+                                    doc_comment_marker,
+                                ),
+                                format!("{} {}", comment_marker, doc_comment_marker),
+                                Applicability::MaybeIncorrect,
+                            );
                         }
-                        e.emit();
-                        self.recover_stmt();
-                        // Don't complain about type errors in body tail after parse error (#57383).
-                        let sp = expr.span.to(self.prev_span);
-                        stmt.kind = StmtKind::Expr(self.mk_expr_err(sp));
                     }
+                    e.emit();
+                    self.recover_stmt();
+                    // Don't complain about type errors in body tail after parse error (#57383).
+                    let sp = expr.span.to(self.prev_span);
+                    stmt.kind = StmtKind::Expr(self.mk_expr_err(sp));
                 }
             }
             StmtKind::Local(..) => {

From 7876711b9be1673631c4aaea63c289a984afbb0b Mon Sep 17 00:00:00 2001
From: Mazdak Farrokhzad <twingoow@gmail.com>
Date: Tue, 25 Feb 2020 06:00:47 +0100
Subject: [PATCH 16/18] parse: address nitpick

---
 src/librustc_parse/parser/stmt.rs | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs
index b7bf99e6e1603..d2a6f0b7fcf0c 100644
--- a/src/librustc_parse/parser/stmt.rs
+++ b/src/librustc_parse/parser/stmt.rs
@@ -59,9 +59,8 @@ impl<'a> Parser<'a> {
         } else if let Some(item) = self.parse_stmt_item(attrs.clone())? {
             // FIXME: Bad copy of attrs
             self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))
-        }
-        // Do not attempt to parse an expression if we're done here.
-        else if self.token == token::Semi {
+        } else if self.token == token::Semi {
+            // Do not attempt to parse an expression if we're done here.
             self.error_outer_attrs(&attrs);
             self.bump();
             let mut last_semi = lo;

From f56042fb3c9821309fc4e8f311a8396bea83d137 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 25 Feb 2020 13:28:40 +0100
Subject: [PATCH 17/18] Clean up E0370 explanation

---
 src/librustc_error_codes/error_codes/E0370.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/librustc_error_codes/error_codes/E0370.md b/src/librustc_error_codes/error_codes/E0370.md
index a3d280fc6dccc..14e954722a250 100644
--- a/src/librustc_error_codes/error_codes/E0370.md
+++ b/src/librustc_error_codes/error_codes/E0370.md
@@ -1,5 +1,7 @@
 The maximum value of an enum was reached, so it cannot be automatically
-set in the next enum value. Erroneous code example:
+set in the next enum value.
+
+Erroneous code example:
 
 ```compile_fail,E0370
 #[repr(i64)]

From d6f83c541d3bfc6116971249e907889e22129514 Mon Sep 17 00:00:00 2001
From: Guillaume Gomez <guillaume1.gomez@gmail.com>
Date: Tue, 25 Feb 2020 13:28:47 +0100
Subject: [PATCH 18/18] Clean up E0371 explanation

---
 src/librustc_error_codes/error_codes/E0371.md | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/librustc_error_codes/error_codes/E0371.md b/src/librustc_error_codes/error_codes/E0371.md
index 9363cddb1dd47..a44721346e20d 100644
--- a/src/librustc_error_codes/error_codes/E0371.md
+++ b/src/librustc_error_codes/error_codes/E0371.md
@@ -1,9 +1,6 @@
-When `Trait2` is a subtrait of `Trait1` (for example, when `Trait2` has a
-definition like `trait Trait2: Trait1 { ... }`), it is not allowed to implement
-`Trait1` for `Trait2`. This is because `Trait2` already implements `Trait1` by
-definition, so it is not useful to do this.
+A trait was implemented on another which already automatically implemented it.
 
-Example:
+Erroneous code examples:
 
 ```compile_fail,E0371
 trait Foo { fn foo(&self) { } }
@@ -15,3 +12,8 @@ impl Foo for Baz { } // error, `Baz` implements `Bar` which implements `Foo`
 impl Baz for Baz { } // error, `Baz` (trivially) implements `Baz`
 impl Baz for Bar { } // Note: This is OK
 ```
+
+When `Trait2` is a subtrait of `Trait1` (for example, when `Trait2` has a
+definition like `trait Trait2: Trait1 { ... }`), it is not allowed to implement
+`Trait1` for `Trait2`. This is because `Trait2` already implements `Trait1` by
+definition, so it is not useful to do this.