From faf80ad3979e58d238f41c22e7be06ff1276a359 Mon Sep 17 00:00:00 2001
From: Matthew Jasper <mjjasper1@gmail.com>
Date: Mon, 3 Sep 2018 21:50:03 +0100
Subject: [PATCH 01/30] remove base_place

---
 src/librustc_mir/borrow_check/mod.rs          | 50 ++-----------------
 .../borrowck-box-insensitivity.nll.stderr     | 35 +++++--------
 .../ui/borrowck/borrowck-box-insensitivity.rs |  3 +-
 3 files changed, 18 insertions(+), 70 deletions(-)

diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 3536947b25ebf..fd5ca0780e290 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1602,10 +1602,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         place_span: (&Place<'tcx>, Span),
         flow_state: &Flows<'cx, 'gcx, 'tcx>,
     ) {
-        // FIXME: analogous code in check_loans first maps `place` to
-        // its base_path ... but is that what we want here?
-        let place = self.base_path(place_span.0);
-
         let maybe_uninits = &flow_state.uninits;
 
         // Bad scenarios:
@@ -1643,8 +1639,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         //
         // This code covers scenarios 1, 2, and 3.
 
-        debug!("check_if_full_path_is_moved place: {:?}", place);
-        match self.move_path_closest_to(place) {
+        debug!("check_if_full_path_is_moved place: {:?}", place_span.0);
+        match self.move_path_closest_to(place_span.0) {
             Ok(mpi) => {
                 if maybe_uninits.contains(&mpi) {
                     self.report_use_of_moved_or_uninitialized(
@@ -1674,10 +1670,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         place_span: (&Place<'tcx>, Span),
         flow_state: &Flows<'cx, 'gcx, 'tcx>,
     ) {
-        // FIXME: analogous code in check_loans first maps `place` to
-        // its base_path ... but is that what we want here?
-        let place = self.base_path(place_span.0);
-
         let maybe_uninits = &flow_state.uninits;
 
         // Bad scenarios:
@@ -1706,8 +1698,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         //
         // This code covers scenario 1.
 
-        debug!("check_if_path_or_subpath_is_moved place: {:?}", place);
-        if let Some(mpi) = self.move_path_for_place(place) {
+        debug!("check_if_path_or_subpath_is_moved place: {:?}", place_span.0);
+        if let Some(mpi) = self.move_path_for_place(place_span.0) {
             if let Some(child_mpi) = maybe_uninits.has_any_child_of(mpi) {
                 self.report_use_of_moved_or_uninitialized(
                     context,
@@ -1810,11 +1802,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                             let tcx = self.tcx;
                             match base.ty(self.mir, tcx).to_ty(tcx).sty {
                                 ty::Adt(def, _) if def.has_dtor(tcx) => {
-
-                                    // FIXME: analogous code in
-                                    // check_loans.rs first maps
-                                    // `base` to its base_path.
-
                                     self.check_if_path_or_subpath_is_moved(
                                         context, InitializationRequiringAction::Assignment,
                                         (base, span), flow_state);
@@ -2187,35 +2174,6 @@ enum Overlap {
     Disjoint,
 }
 
-impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
-    // FIXME (#16118): function intended to allow the borrow checker
-    // to be less precise in its handling of Box while still allowing
-    // moves out of a Box. They should be removed when/if we stop
-    // treating Box specially (e.g. when/if DerefMove is added...)
-
-    fn base_path<'d>(&self, place: &'d Place<'tcx>) -> &'d Place<'tcx> {
-        //! Returns the base of the leftmost (deepest) dereference of an
-        //! Box in `place`. If there is no dereference of an Box
-        //! in `place`, then it just returns `place` itself.
-
-        let mut cursor = place;
-        let mut deepest = place;
-        loop {
-            let proj = match *cursor {
-                Place::Promoted(_) |
-                Place::Local(..) | Place::Static(..) => return deepest,
-                Place::Projection(ref proj) => proj,
-            };
-            if proj.elem == ProjectionElem::Deref
-                && place.ty(self.mir, self.tcx).to_ty(self.tcx).is_box()
-            {
-                deepest = &proj.base;
-            }
-            cursor = &proj.base;
-        }
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 struct Context {
     kind: ContextKind,
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr
index 601f05b499c75..0e380e90e7591 100644
--- a/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.nll.stderr
@@ -1,25 +1,14 @@
-error[E0382]: use of moved value: `a.y`
-  --> $DIR/borrowck-box-insensitivity.rs:46:14
-   |
-LL |     let _x = a.x;
-   |              --- value moved here
-LL |     //~^ value moved here
-LL |     let _y = a.y; //~ ERROR use of moved
-   |              ^^^ value used here after move
-   |
-   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
-
-error[E0382]: use of moved value: `a.y`
-  --> $DIR/borrowck-box-insensitivity.rs:108:14
-   |
-LL |     let _x = a.x.x;
-   |              ----- value moved here
-LL |     //~^ value moved here
-LL |     let _y = a.y; //~ ERROR use of collaterally moved
-   |              ^^^ value used here after move
-   |
-   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+error: compilation successful
+  --> $DIR/borrowck-box-insensitivity.rs:160:1
+   |
+LL | / fn main() {
+LL | |     copy_after_move();
+LL | |     move_after_move();
+LL | |     borrow_after_move();
+...  |
+LL | |     mut_borrow_after_borrow_nested();
+LL | | }
+   | |_^
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.rs b/src/test/ui/borrowck/borrowck-box-insensitivity.rs
index 75bf6bce04b39..eabb8d7bca3fa 100644
--- a/src/test/ui/borrowck/borrowck-box-insensitivity.rs
+++ b/src/test/ui/borrowck/borrowck-box-insensitivity.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(box_syntax)]
+#![feature(box_syntax, rustc_attrs)]
 
 struct A {
     x: Box<isize>,
@@ -156,6 +156,7 @@ fn mut_borrow_after_borrow_nested() {
     //~^ mutable borrow occurs here
 }
 
+#[rustc_error]
 fn main() {
     copy_after_move();
     move_after_move();

From d7a74be09b3c3d5ad015be31c51208260aa85007 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Tue, 4 Sep 2018 10:41:33 -0700
Subject: [PATCH 02/30] Fix incorrect outer function type parameter message

---
 src/librustc_resolve/lib.rs             |  9 ++++++++-
 src/test/ui/error-codes/E0401.stderr    |  7 ++++---
 src/test/ui/issues/issue-12796.stderr   |  7 ++++---
 src/test/ui/use-self-in-inner-fn.rs     | 24 ++++++++++++++++++++++++
 src/test/ui/use-self-in-inner-fn.stderr | 15 +++++++++++++++
 5 files changed, 55 insertions(+), 7 deletions(-)
 create mode 100644 src/test/ui/use-self-in-inner-fn.rs
 create mode 100644 src/test/ui/use-self-in-inner-fn.stderr

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 0f6a974230917..19a4fdae48596 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -197,6 +197,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             err.span_label(span, "use of type variable from outer function");
 
             let cm = resolver.session.source_map();
+            let mut is_self = false;
             match outer_def {
                 Def::SelfTy(_, maybe_impl_defid) => {
                     if let Some(impl_span) = maybe_impl_defid.map_or(None,
@@ -204,6 +205,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                         err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span),
                                     "`Self` type implicitly declared here, on the `impl`");
                     }
+                    is_self = true;
                 },
                 Def::TyParam(typaram_defid) => {
                     if let Some(typaram_span) = resolver.definitions.opt_span(typaram_defid) {
@@ -219,7 +221,12 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             // Try to retrieve the span of the function signature and generate a new message with
             // a local type parameter
             let sugg_msg = "try using a local type parameter instead";
-            if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
+            if is_self {
+                // Suggest using the actual type
+                err.span_label(span, "use a materialized type here instead");
+            } else if let Some(
+                (sugg_span, new_snippet),
+            ) = cm.generate_local_type_param_snippet(span) {
                 // Suggest the modification to the user
                 err.span_suggestion_with_applicability(
                     sugg_span,
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
index b088e8330e998..90e8d2d2479da 100644
--- a/src/test/ui/error-codes/E0401.stderr
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -27,9 +27,10 @@ LL | impl<T> Iterator for A<T> {
    | ---- `Self` type implicitly declared here, on the `impl`
 ...
 LL |         fn helper(sel: &Self) -> u8 { //~ ERROR E0401
-   |            ------       ^^^^ use of type variable from outer function
-   |            |
-   |            help: try using a local type parameter instead: `helper<Self>`
+   |                         ^^^^
+   |                         |
+   |                         use of type variable from outer function
+   |                         use a materialized type here instead
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-12796.stderr b/src/test/ui/issues/issue-12796.stderr
index c8bedd3853c68..078c1db5de594 100644
--- a/src/test/ui/issues/issue-12796.stderr
+++ b/src/test/ui/issues/issue-12796.stderr
@@ -2,9 +2,10 @@ error[E0401]: can't use type parameters from outer function
   --> $DIR/issue-12796.rs:13:22
    |
 LL |         fn inner(_: &Self) {
-   |            -----     ^^^^ use of type variable from outer function
-   |            |
-   |            help: try using a local type parameter instead: `inner<Self>`
+   |                      ^^^^
+   |                      |
+   |                      use of type variable from outer function
+   |                      use a materialized type here instead
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/use-self-in-inner-fn.rs b/src/test/ui/use-self-in-inner-fn.rs
new file mode 100644
index 0000000000000..a1183854eb50a
--- /dev/null
+++ b/src/test/ui/use-self-in-inner-fn.rs
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct A;
+
+impl A {
+//~^ NOTE `Self` type implicitly declared here, on the `impl`
+    fn banana(&mut self) {
+        fn peach(this: &Self) {
+        //~^ ERROR can't use type parameters from outer function
+        //~| NOTE use of type variable from outer function
+        //~| NOTE use a materialized type here instead
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/use-self-in-inner-fn.stderr b/src/test/ui/use-self-in-inner-fn.stderr
new file mode 100644
index 0000000000000..c14e4895d9930
--- /dev/null
+++ b/src/test/ui/use-self-in-inner-fn.stderr
@@ -0,0 +1,15 @@
+error[E0401]: can't use type parameters from outer function
+  --> $DIR/use-self-in-inner-fn.rs:16:25
+   |
+LL | impl A {
+   | ---- `Self` type implicitly declared here, on the `impl`
+...
+LL |         fn peach(this: &Self) {
+   |                         ^^^^
+   |                         |
+   |                         use of type variable from outer function
+   |                         use a materialized type here instead
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0401`.

From 941b2e32ade695f7987c229eb1344c35119d6354 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 5 Sep 2018 08:39:50 -0700
Subject: [PATCH 03/30] slight rewording of labels

---
 src/librustc_resolve/lib.rs             | 32 +++++++++++++++----------
 src/test/ui/error-codes/E0401.stderr    |  2 +-
 src/test/ui/issues/issue-12796.stderr   |  2 +-
 src/test/ui/use-self-in-inner-fn.rs     |  2 +-
 src/test/ui/use-self-in-inner-fn.stderr |  2 +-
 5 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 19a4fdae48596..449b395c00401 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -197,15 +197,26 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             err.span_label(span, "use of type variable from outer function");
 
             let cm = resolver.session.source_map();
-            let mut is_self = false;
             match outer_def {
-                Def::SelfTy(_, maybe_impl_defid) => {
-                    if let Some(impl_span) = maybe_impl_defid.map_or(None,
-                            |def_id| resolver.definitions.opt_span(def_id)) {
-                        err.span_label(reduce_impl_span_to_impl_keyword(cm, impl_span),
-                                    "`Self` type implicitly declared here, on the `impl`");
+                Def::SelfTy(maybe_trait_defid, maybe_impl_defid) => {
+                    if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| {
+                        resolver.definitions.opt_span(def_id)
+                    }) {
+                        err.span_label(
+                            reduce_impl_span_to_impl_keyword(cm, impl_span),
+                            "`Self` type implicitly declared here, on the `impl`",
+                        );
+                    }
+                    match (maybe_trait_defid, maybe_impl_defid) {
+                        (Some(_), None) => {
+                            err.span_label(span, "can't use `Self` here");
+                        }
+                        (_, Some(_)) => {
+                            err.span_label(span, "use a type here instead");
+                        }
+                        (None, None) => bug!("`impl` without trait nor type?"),
                     }
-                    is_self = true;
+                    return err;
                 },
                 Def::TyParam(typaram_defid) => {
                     if let Some(typaram_span) = resolver.definitions.opt_span(typaram_defid) {
@@ -221,12 +232,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
             // Try to retrieve the span of the function signature and generate a new message with
             // a local type parameter
             let sugg_msg = "try using a local type parameter instead";
-            if is_self {
-                // Suggest using the actual type
-                err.span_label(span, "use a materialized type here instead");
-            } else if let Some(
-                (sugg_span, new_snippet),
-            ) = cm.generate_local_type_param_snippet(span) {
+            if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
                 // Suggest the modification to the user
                 err.span_suggestion_with_applicability(
                     sugg_span,
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
index 90e8d2d2479da..66cc8795fba20 100644
--- a/src/test/ui/error-codes/E0401.stderr
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -30,7 +30,7 @@ LL |         fn helper(sel: &Self) -> u8 { //~ ERROR E0401
    |                         ^^^^
    |                         |
    |                         use of type variable from outer function
-   |                         use a materialized type here instead
+   |                         use a type here instead
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-12796.stderr b/src/test/ui/issues/issue-12796.stderr
index 078c1db5de594..0c369c6ab9717 100644
--- a/src/test/ui/issues/issue-12796.stderr
+++ b/src/test/ui/issues/issue-12796.stderr
@@ -5,7 +5,7 @@ LL |         fn inner(_: &Self) {
    |                      ^^^^
    |                      |
    |                      use of type variable from outer function
-   |                      use a materialized type here instead
+   |                      can't use `Self` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/use-self-in-inner-fn.rs b/src/test/ui/use-self-in-inner-fn.rs
index a1183854eb50a..380cb7a2aa270 100644
--- a/src/test/ui/use-self-in-inner-fn.rs
+++ b/src/test/ui/use-self-in-inner-fn.rs
@@ -16,7 +16,7 @@ impl A {
         fn peach(this: &Self) {
         //~^ ERROR can't use type parameters from outer function
         //~| NOTE use of type variable from outer function
-        //~| NOTE use a materialized type here instead
+        //~| NOTE use a type here instead
         }
     }
 }
diff --git a/src/test/ui/use-self-in-inner-fn.stderr b/src/test/ui/use-self-in-inner-fn.stderr
index c14e4895d9930..26082e5e01b22 100644
--- a/src/test/ui/use-self-in-inner-fn.stderr
+++ b/src/test/ui/use-self-in-inner-fn.stderr
@@ -8,7 +8,7 @@ LL |         fn peach(this: &Self) {
    |                         ^^^^
    |                         |
    |                         use of type variable from outer function
-   |                         use a materialized type here instead
+   |                         use a type here instead
 
 error: aborting due to previous error
 

From bebecf850ab2a8c9df298bd3ab3b12ca8ea83c41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar>
Date: Wed, 5 Sep 2018 09:56:01 -0700
Subject: [PATCH 04/30] reword label as per review

---
 src/librustc_resolve/lib.rs             | 2 +-
 src/test/ui/error-codes/E0401.stderr    | 2 +-
 src/test/ui/use-self-in-inner-fn.rs     | 2 +-
 src/test/ui/use-self-in-inner-fn.stderr | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 449b395c00401..f5ac0a6647bda 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -204,7 +204,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                     }) {
                         err.span_label(
                             reduce_impl_span_to_impl_keyword(cm, impl_span),
-                            "`Self` type implicitly declared here, on the `impl`",
+                            "`Self` type implicitly declared here, by this `impl`",
                         );
                     }
                     match (maybe_trait_defid, maybe_impl_defid) {
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
index 66cc8795fba20..53eeb3e9c1337 100644
--- a/src/test/ui/error-codes/E0401.stderr
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -24,7 +24,7 @@ error[E0401]: can't use type parameters from outer function
   --> $DIR/E0401.rs:32:25
    |
 LL | impl<T> Iterator for A<T> {
-   | ---- `Self` type implicitly declared here, on the `impl`
+   | ---- `Self` type implicitly declared here, by this `impl`
 ...
 LL |         fn helper(sel: &Self) -> u8 { //~ ERROR E0401
    |                         ^^^^
diff --git a/src/test/ui/use-self-in-inner-fn.rs b/src/test/ui/use-self-in-inner-fn.rs
index 380cb7a2aa270..fea6958d7eb09 100644
--- a/src/test/ui/use-self-in-inner-fn.rs
+++ b/src/test/ui/use-self-in-inner-fn.rs
@@ -11,7 +11,7 @@
 struct A;
 
 impl A {
-//~^ NOTE `Self` type implicitly declared here, on the `impl`
+//~^ NOTE `Self` type implicitly declared here, by this `impl`
     fn banana(&mut self) {
         fn peach(this: &Self) {
         //~^ ERROR can't use type parameters from outer function
diff --git a/src/test/ui/use-self-in-inner-fn.stderr b/src/test/ui/use-self-in-inner-fn.stderr
index 26082e5e01b22..cef030aec460c 100644
--- a/src/test/ui/use-self-in-inner-fn.stderr
+++ b/src/test/ui/use-self-in-inner-fn.stderr
@@ -2,7 +2,7 @@ error[E0401]: can't use type parameters from outer function
   --> $DIR/use-self-in-inner-fn.rs:16:25
    |
 LL | impl A {
-   | ---- `Self` type implicitly declared here, on the `impl`
+   | ---- `Self` type implicitly declared here, by this `impl`
 ...
 LL |         fn peach(this: &Self) {
    |                         ^^^^

From 6c14360c327a2513560fd8a238bc42ded011bb51 Mon Sep 17 00:00:00 2001
From: ms2300 <matt.sewall@gmail.com>
Date: Thu, 23 Aug 2018 13:51:32 -0600
Subject: [PATCH 05/30] Changing TyAnon -> TyOpaque and relevant functions

---
 src/librustc/ich/impls_ty.rs                  |   2 +-
 src/librustc/infer/canonical/canonicalizer.rs |   2 +-
 src/librustc/infer/freshen.rs                 |   2 +-
 src/librustc/infer/mod.rs                     |   2 +-
 .../infer/{anon_types => opaque_types}/mod.rs | 171 +++++++++---------
 src/librustc/traits/coherence.rs              |   2 +-
 src/librustc/traits/error_reporting.rs        |   2 +-
 src/librustc/traits/project.rs                |   6 +-
 src/librustc/traits/query/dropck_outlives.rs  |   2 +-
 src/librustc/traits/query/normalize.rs        |   2 +-
 src/librustc/traits/select.rs                 |  10 +-
 src/librustc/ty/context.rs                    |   6 +-
 src/librustc/ty/error.rs                      |   2 +-
 src/librustc/ty/fast_reject.rs                |  10 +-
 src/librustc/ty/flags.rs                      |   2 +-
 src/librustc/ty/fold.rs                       |   2 +-
 src/librustc/ty/item_path.rs                  |   2 +-
 src/librustc/ty/layout.rs                     |   6 +-
 src/librustc/ty/mod.rs                        |   4 +-
 src/librustc/ty/outlives.rs                   |   2 +-
 src/librustc/ty/relate.rs                     |   4 +-
 src/librustc/ty/structural_impls.rs           |   4 +-
 src/librustc/ty/sty.rs                        |  10 +-
 src/librustc/ty/util.rs                       |   2 +-
 src/librustc/ty/walk.rs                       |   2 +-
 src/librustc/ty/wf.rs                         |   2 +-
 src/librustc/util/ppaux.rs                    |   6 +-
 .../debuginfo/type_names.rs                   |   2 +-
 src/librustc_lint/types.rs                    |   2 +-
 .../nll/type_check/input_output.rs            |  37 ++--
 src/librustc_mir/monomorphize/item.rs         |   2 +-
 src/librustc_privacy/lib.rs                   |  14 +-
 src/librustc_traits/dropck_outlives.rs        |   4 +-
 src/librustc_typeck/astconv.rs                |   4 +-
 src/librustc_typeck/check/cast.rs             |   6 +-
 src/librustc_typeck/check/mod.rs              |  32 ++--
 src/librustc_typeck/check/regionck.rs         |   4 +-
 src/librustc_typeck/check/wfcheck.rs          |  12 +-
 src/librustc_typeck/check/writeback.rs        |  26 +--
 src/librustc_typeck/collect.rs                |  22 ++-
 .../constrained_type_params.rs                |   4 +-
 src/librustc_typeck/variance/constraints.rs   |   2 +-
 src/librustdoc/clean/mod.rs                   |   4 +-
 43 files changed, 229 insertions(+), 217 deletions(-)
 rename src/librustc/infer/{anon_types => opaque_types}/mod.rs (85%)

diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 6250e12f43043..e5ab1dcceea9b 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -881,7 +881,7 @@ for ty::TyKind<'gcx>
             Projection(ref projection_ty) => {
                 projection_ty.hash_stable(hcx, hasher);
             }
-            Anon(def_id, substs) => {
+            Opaque(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs
index fbe9165ae97fa..b30ccb5976c98 100644
--- a/src/librustc/infer/canonical/canonicalizer.rs
+++ b/src/librustc/infer/canonical/canonicalizer.rs
@@ -285,7 +285,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
             | ty::Projection(..)
             | ty::Foreign(..)
             | ty::Param(..)
-            | ty::Anon(..) => {
+            | ty::Opaque(..) => {
                 if t.flags.intersects(self.needs_canonical_flags) {
                     t.super_fold_with(self)
                 } else {
diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs
index 4673aac1872ff..1cb813c39e68c 100644
--- a/src/librustc/infer/freshen.rs
+++ b/src/librustc/infer/freshen.rs
@@ -197,7 +197,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
             ty::Param(..) |
             ty::Closure(..) |
             ty::GeneratorWitness(..) |
-            ty::Anon(..) => {
+            ty::Opaque(..) => {
                 t.super_fold_with(self)
             }
         }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index a379438275d89..a092bac51878d 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -48,7 +48,7 @@ use self::outlives::env::OutlivesEnvironment;
 use self::type_variable::TypeVariableOrigin;
 use self::unify_key::ToType;
 
-pub mod anon_types;
+pub mod opaque_types;
 pub mod at;
 pub mod canonical;
 mod combine;
diff --git a/src/librustc/infer/anon_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs
similarity index 85%
rename from src/librustc/infer/anon_types/mod.rs
rename to src/librustc/infer/opaque_types/mod.rs
index 8eab07ece05ef..9d65c3950626c 100644
--- a/src/librustc/infer/anon_types/mod.rs
+++ b/src/librustc/infer/opaque_types/mod.rs
@@ -22,13 +22,13 @@ use ty::outlives::Component;
 use ty::subst::{Kind, Substs, UnpackedKind};
 use util::nodemap::DefIdMap;
 
-pub type AnonTypeMap<'tcx> = DefIdMap<AnonTypeDecl<'tcx>>;
+pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>;
 
-/// Information about the anonymous, abstract types whose values we
+/// Information about the opaque, abstract types whose values we
 /// are inferring in this function (these are the `impl Trait` that
 /// appear in the return type).
 #[derive(Copy, Clone, Debug)]
-pub struct AnonTypeDecl<'tcx> {
+pub struct OpaqueTypeDecl<'tcx> {
     /// The substitutions that we apply to the abstract that that this
     /// `impl Trait` desugars to. e.g., if:
     ///
@@ -81,7 +81,7 @@ pub struct AnonTypeDecl<'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    /// Replace all anonymized types in `value` with fresh inference variables
+    /// Replace all opaque types in `value` with fresh inference variables
     /// and creates appropriate obligations. For example, given the input:
     ///
     ///     impl Iterator<Item = impl Debug>
@@ -92,29 +92,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     ///     ?0: Iterator<Item = ?1>
     ///     ?1: Debug
     ///
-    /// Moreover, it returns a `AnonTypeMap` that would map `?0` to
+    /// Moreover, it returns a `OpaqueTypeMap` that would map `?0` to
     /// info about the `impl Iterator<..>` type and `?1` to info about
     /// the `impl Debug` type.
     ///
     /// # Parameters
     ///
-    /// - `parent_def_id` -- we will only instantiate anonymous types
+    /// - `parent_def_id` -- we will only instantiate opaque types
     ///   with this parent. This is typically the def-id of the function
-    ///   in whose return type anon types are being instantiated.
+    ///   in whose return type opaque types are being instantiated.
     /// - `body_id` -- the body-id with which the resulting obligations should
     ///   be associated
     /// - `param_env` -- the in-scope parameter environment to be used for
     ///   obligations
-    /// - `value` -- the value within which we are instantiating anon types
-    pub fn instantiate_anon_types<T: TypeFoldable<'tcx>>(
+    /// - `value` -- the value within which we are instantiating opaque types
+    pub fn instantiate_opaque_types<T: TypeFoldable<'tcx>>(
         &self,
         parent_def_id: DefId,
         body_id: ast::NodeId,
         param_env: ty::ParamEnv<'tcx>,
         value: &T,
-    ) -> InferOk<'tcx, (T, AnonTypeMap<'tcx>)> {
+    ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
         debug!(
-            "instantiate_anon_types(value={:?}, parent_def_id={:?}, body_id={:?}, param_env={:?})",
+            "instantiate_opaque_types(value={:?},
+            parent_def_id={:?}, body_id={:?},
+            param_env={:?})",
             value, parent_def_id, body_id, param_env,
         );
         let mut instantiator = Instantiator {
@@ -122,17 +124,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             parent_def_id,
             body_id,
             param_env,
-            anon_types: DefIdMap(),
+            opaque_types: DefIdMap(),
             obligations: vec![],
         };
-        let value = instantiator.instantiate_anon_types_in_map(value);
+        let value = instantiator.instantiate_opaque_types_in_map(value);
         InferOk {
-            value: (value, instantiator.anon_types),
+            value: (value, instantiator.opaque_types),
             obligations: instantiator.obligations,
         }
     }
 
-    /// Given the map `anon_types` containing the existential `impl
+    /// Given the map `opaque_types` containing the existential `impl
     /// Trait` types whose underlying, hidden types are being
     /// inferred, this method adds constraints to the regions
     /// appearing in those underlying hidden types to ensure that they
@@ -267,34 +269,34 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     ///
     /// # Parameters
     ///
-    /// - `anon_types` -- the map produced by `instantiate_anon_types`
+    /// - `opaque_types` -- the map produced by `instantiate_opaque_types`
     /// - `free_region_relations` -- something that can be used to relate
     ///   the free regions (`'a`) that appear in the impl trait.
-    pub fn constrain_anon_types<FRR: FreeRegionRelations<'tcx>>(
+    pub fn constrain_opaque_types<FRR: FreeRegionRelations<'tcx>>(
         &self,
-        anon_types: &AnonTypeMap<'tcx>,
+        opaque_types: &OpaqueTypeMap<'tcx>,
         free_region_relations: &FRR,
     ) {
-        debug!("constrain_anon_types()");
+        debug!("constrain_opaque_types()");
 
-        for (&def_id, anon_defn) in anon_types {
-            self.constrain_anon_type(def_id, anon_defn, free_region_relations);
+        for (&def_id, opaque_defn) in opaque_types {
+            self.constrain_opaque_type(def_id, opaque_defn, free_region_relations);
         }
     }
 
-    fn constrain_anon_type<FRR: FreeRegionRelations<'tcx>>(
+    fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         &self,
         def_id: DefId,
-        anon_defn: &AnonTypeDecl<'tcx>,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
         free_region_relations: &FRR,
     ) {
-        debug!("constrain_anon_type()");
-        debug!("constrain_anon_type: def_id={:?}", def_id);
-        debug!("constrain_anon_type: anon_defn={:#?}", anon_defn);
+        debug!("constrain_opaque_type()");
+        debug!("constrain_opaque_type: def_id={:?}", def_id);
+        debug!("constrain_opaque_type: opaque_defn={:#?}", opaque_defn);
 
-        let concrete_ty = self.resolve_type_vars_if_possible(&anon_defn.concrete_ty);
+        let concrete_ty = self.resolve_type_vars_if_possible(&opaque_defn.concrete_ty);
 
-        debug!("constrain_anon_type: concrete_ty={:?}", concrete_ty);
+        debug!("constrain_opaque_type: concrete_ty={:?}", concrete_ty);
 
         let abstract_type_generics = self.tcx.generics_of(def_id);
 
@@ -303,7 +305,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         // If there are required region bounds, we can just skip
         // ahead.  There will already be a registered region
         // obligation related `concrete_ty` to those regions.
-        if anon_defn.has_required_region_bounds {
+        if opaque_defn.has_required_region_bounds {
             return;
         }
 
@@ -321,11 +323,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 _ => continue
             }
             // Get the value supplied for this region from the substs.
-            let subst_arg = anon_defn.substs.region_at(param.index as usize);
+            let subst_arg = opaque_defn.substs.region_at(param.index as usize);
 
             // Compute the least upper bound of it with the other regions.
-            debug!("constrain_anon_types: least_region={:?}", least_region);
-            debug!("constrain_anon_types: subst_arg={:?}", subst_arg);
+            debug!("constrain_opaque_types: least_region={:?}", least_region);
+            debug!("constrain_opaque_types: subst_arg={:?}", subst_arg);
             match least_region {
                 None => least_region = Some(subst_arg),
                 Some(lr) => {
@@ -355,7 +357,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
 
         let least_region = least_region.unwrap_or(self.tcx.types.re_static);
-        debug!("constrain_anon_types: least_region={:?}", least_region);
+        debug!("constrain_opaque_types: least_region={:?}", least_region);
 
         // Require that the type `concrete_ty` outlives
         // `least_region`, modulo any type parameters that appear
@@ -384,7 +386,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                         // annotations are needed in this case
                         self.tcx
                             .sess
-                            .delay_span_bug(span, "unresolved inf var in anon");
+                            .delay_span_bug(span, "unresolved inf var in opaque");
                     }
 
                     Component::Projection(ty::ProjectionTy {
@@ -405,7 +407,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    /// Given the fully resolved, instantiated type for an anonymous
+    /// Given the fully resolved, instantiated type for an opaque
     /// type, i.e., the value of an inference variable like C1 or C2
     /// (*), computes the "definition type" for an abstract type
     /// definition -- that is, the inferred value of `Foo1<'x>` or
@@ -420,22 +422,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// purpose of this function is to do that translation.
     ///
     /// (*) C1 and C2 were introduced in the comments on
-    /// `constrain_anon_types`. Read that comment for more context.
+    /// `constrain_opaque_types`. Read that comment for more context.
     ///
     /// # Parameters
     ///
     /// - `def_id`, the `impl Trait` type
-    /// - `anon_defn`, the anonymous definition created in `instantiate_anon_types`
+    /// - `opaque_defn`, the opaque definition created in `instantiate_opaque_types`
     /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of
-    ///   `anon_defn.concrete_ty`
-    pub fn infer_anon_definition_from_instantiation(
+    ///   `opaque_defn.concrete_ty`
+    pub fn infer_opaque_definition_from_instantiation(
         &self,
         def_id: DefId,
-        anon_defn: &AnonTypeDecl<'tcx>,
+        opaque_defn: &OpaqueTypeDecl<'tcx>,
         instantiated_ty: Ty<'gcx>,
     ) -> Ty<'gcx> {
         debug!(
-            "infer_anon_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
+            "infer_opaque_definition_from_instantiation(def_id={:?}, instantiated_ty={:?})",
             def_id, instantiated_ty
         );
 
@@ -448,7 +450,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         // `impl Trait` return type, resulting in the parameters
         // shifting.
         let id_substs = Substs::identity_for_item(gcx, def_id);
-        let map: FxHashMap<Kind<'tcx>, Kind<'gcx>> = anon_defn
+        let map: FxHashMap<Kind<'tcx>, Kind<'gcx>> = opaque_defn
             .substs
             .iter()
             .enumerate()
@@ -467,7 +469,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 instantiated_ty,
             ));
         debug!(
-            "infer_anon_definition_from_instantiation: definition_ty={:?}",
+            "infer_opaque_definition_from_instantiation: definition_ty={:?}",
             definition_ty
         );
 
@@ -487,7 +489,7 @@ struct ReverseMapper<'cx, 'gcx: 'tcx, 'tcx: 'cx> {
     /// our own errors because they are sometimes derivative.
     tainted_by_errors: bool,
 
-    anon_type_def_id: DefId,
+    opaque_type_def_id: DefId,
     map: FxHashMap<Kind<'tcx>, Kind<'gcx>>,
     map_missing_regions_to_empty: bool,
 
@@ -499,14 +501,14 @@ impl<'cx, 'gcx, 'tcx> ReverseMapper<'cx, 'gcx, 'tcx> {
     fn new(
         tcx: TyCtxt<'cx, 'gcx, 'tcx>,
         tainted_by_errors: bool,
-        anon_type_def_id: DefId,
+        opaque_type_def_id: DefId,
         map: FxHashMap<Kind<'tcx>, Kind<'gcx>>,
         hidden_ty: Ty<'tcx>,
     ) -> Self {
         Self {
             tcx,
             tainted_by_errors,
-            anon_type_def_id,
+            opaque_type_def_id,
             map,
             map_missing_regions_to_empty: false,
             hidden_ty: Some(hidden_ty),
@@ -554,7 +556,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx>
             None => {
                 if !self.map_missing_regions_to_empty && !self.tainted_by_errors {
                     if let Some(hidden_ty) = self.hidden_ty.take() {
-                        let span = self.tcx.def_span(self.anon_type_def_id);
+                        let span = self.tcx.def_span(self.opaque_type_def_id);
                         let mut err = struct_span_err!(
                             self.tcx.sess,
                             span,
@@ -644,19 +646,19 @@ struct Instantiator<'a, 'gcx: 'tcx, 'tcx: 'a> {
     parent_def_id: DefId,
     body_id: ast::NodeId,
     param_env: ty::ParamEnv<'tcx>,
-    anon_types: AnonTypeMap<'tcx>,
+    opaque_types: OpaqueTypeMap<'tcx>,
     obligations: Vec<PredicateObligation<'tcx>>,
 }
 
 impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
-    fn instantiate_anon_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
-        debug!("instantiate_anon_types_in_map(value={:?})", value);
+    fn instantiate_opaque_types_in_map<T: TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
+        debug!("instantiate_opaque_types_in_map(value={:?})", value);
         let tcx = self.infcx.tcx;
         value.fold_with(&mut BottomUpFolder {
             tcx,
             reg_op: |reg| reg,
             fldop: |ty| {
-                if let ty::Anon(def_id, substs) = ty.sty {
+                if let ty::Opaque(def_id, substs) = ty.sty {
                     // Check that this is `impl Trait` type is
                     // declared by `parent_def_id` -- i.e., one whose
                     // value we are inferring.  At present, this is
@@ -680,7 +682,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
                     // ```
                     //
                     // Here, the return type of `foo` references a
-                    // `Anon` indeed, but not one whose value is
+                    // `Opaque` indeed, but not one whose value is
                     // presently being inferred. You can get into a
                     // similar situation with closure return types
                     // today:
@@ -688,16 +690,16 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
                     // ```rust
                     // fn foo() -> impl Iterator { .. }
                     // fn bar() {
-                    //     let x = || foo(); // returns the Anon assoc with `foo`
+                    //     let x = || foo(); // returns the Opaque assoc with `foo`
                     // }
                     // ```
-                    if let Some(anon_node_id) = tcx.hir.as_local_node_id(def_id) {
+                    if let Some(opaque_node_id) = tcx.hir.as_local_node_id(def_id) {
                         let parent_def_id = self.parent_def_id;
                         let def_scope_default = || {
-                            let anon_parent_node_id = tcx.hir.get_parent(anon_node_id);
-                            parent_def_id == tcx.hir.local_def_id(anon_parent_node_id)
+                            let opaque_parent_node_id = tcx.hir.get_parent(opaque_node_id);
+                            parent_def_id == tcx.hir.local_def_id(opaque_parent_node_id)
                         };
-                        let in_definition_scope = match tcx.hir.find(anon_node_id) {
+                        let in_definition_scope = match tcx.hir.find(opaque_node_id) {
                             Some(Node::Item(item)) => match item.node {
                                 // impl trait
                                 hir::ItemKind::Existential(hir::ExistTy {
@@ -711,7 +713,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
                                 }) => may_define_existential_type(
                                     tcx,
                                     self.parent_def_id,
-                                    anon_node_id,
+                                    opaque_node_id,
                                 ),
                                 _ => def_scope_default(),
                             },
@@ -719,22 +721,22 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
                                 hir::ImplItemKind::Existential(_) => may_define_existential_type(
                                     tcx,
                                     self.parent_def_id,
-                                    anon_node_id,
+                                    opaque_node_id,
                                 ),
                                 _ => def_scope_default(),
                             },
                             _ => bug!(
                                 "expected (impl) item, found {}",
-                                tcx.hir.node_to_string(anon_node_id),
+                                tcx.hir.node_to_string(opaque_node_id),
                             ),
                         };
                         if in_definition_scope {
-                            return self.fold_anon_ty(ty, def_id, substs);
+                            return self.fold_opaque_ty(ty, def_id, substs);
                         }
 
                         debug!(
-                            "instantiate_anon_types_in_map: \
-                             encountered anon outside it's definition scope \
+                            "instantiate_opaque_types_in_map: \
+                             encountered opaque outside it's definition scope \
                              def_id={:?}",
                             def_id,
                         );
@@ -746,7 +748,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
         })
     }
 
-    fn fold_anon_ty(
+    fn fold_opaque_ty(
         &mut self,
         ty: Ty<'tcx>,
         def_id: DefId,
@@ -756,29 +758,29 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
         let tcx = infcx.tcx;
 
         debug!(
-            "instantiate_anon_types: Anon(def_id={:?}, substs={:?})",
+            "instantiate_opaque_types: Opaque(def_id={:?}, substs={:?})",
             def_id, substs
         );
 
-        // Use the same type variable if the exact same Anon appears more
+        // Use the same type variable if the exact same Opaque appears more
         // than once in the return type (e.g. if it's passed to a type alias).
-        if let Some(anon_defn) = self.anon_types.get(&def_id) {
-            return anon_defn.concrete_ty;
+        if let Some(opaque_defn) = self.opaque_types.get(&def_id) {
+            return opaque_defn.concrete_ty;
         }
         let span = tcx.def_span(def_id);
         let ty_var = infcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
 
         let predicates_of = tcx.predicates_of(def_id);
         debug!(
-            "instantiate_anon_types: predicates: {:#?}",
+            "instantiate_opaque_types: predicates: {:#?}",
             predicates_of,
         );
         let bounds = predicates_of.instantiate(tcx, substs);
-        debug!("instantiate_anon_types: bounds={:?}", bounds);
+        debug!("instantiate_opaque_types: bounds={:?}", bounds);
 
         let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone());
         debug!(
-            "instantiate_anon_types: required_region_bounds={:?}",
+            "instantiate_opaque_types: required_region_bounds={:?}",
             required_region_bounds
         );
 
@@ -786,34 +788,34 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
         // e.g. `existential type Foo<T: Bound>: Bar;` needs to be
         // defined by a function like `fn foo<T: Bound>() -> Foo<T>`.
         debug!(
-            "instantiate_anon_types: param_env: {:#?}",
+            "instantiate_opaque_types: param_env: {:#?}",
             self.param_env,
         );
         debug!(
-            "instantiate_anon_types: generics: {:#?}",
+            "instantiate_opaque_types: generics: {:#?}",
             tcx.generics_of(def_id),
         );
 
-        self.anon_types.insert(
+        self.opaque_types.insert(
             def_id,
-            AnonTypeDecl {
+            OpaqueTypeDecl {
                 substs,
                 concrete_ty: ty_var,
                 has_required_region_bounds: !required_region_bounds.is_empty(),
             },
         );
-        debug!("instantiate_anon_types: ty_var={:?}", ty_var);
+        debug!("instantiate_opaque_types: ty_var={:?}", ty_var);
 
         for predicate in bounds.predicates {
             // Change the predicate to refer to the type variable,
-            // which will be the concrete type, instead of the Anon.
+            // which will be the concrete type, instead of the Opaque.
             // This also instantiates nested `impl Trait`.
-            let predicate = self.instantiate_anon_types_in_map(&predicate);
+            let predicate = self.instantiate_opaque_types_in_map(&predicate);
 
             let cause = traits::ObligationCause::new(span, self.body_id, traits::SizedReturnType);
 
             // Require that the predicate holds for the concrete type.
-            debug!("instantiate_anon_types: predicate={:?}", predicate);
+            debug!("instantiate_opaque_types: predicate={:?}", predicate);
             self.obligations
                 .push(traits::Obligation::new(cause, self.param_env, predicate));
         }
@@ -822,7 +824,7 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
     }
 }
 
-/// Whether `anon_node_id` is a sibling or a child of a sibling of `def_id`
+/// Whether `opaque_node_id` is a sibling or a child of a sibling of `def_id`
 ///
 /// ```rust
 /// pub mod foo {
@@ -837,13 +839,14 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
 /// ```
 ///
 /// Here, `def_id` will be the `DefId` of the existential type `Baz`.
-/// `anon_node_id` is the `NodeId` of the reference to Baz -- so either the return type of f1 or f2.
+/// `opaque_node_id` is the `NodeId` of the reference to Baz --
+///  so either the return type of f1 or f2.
 /// We will return true if the reference is within the same module as the existential type
 /// So true for f1, false for f2.
 pub fn may_define_existential_type(
     tcx: TyCtxt,
     def_id: DefId,
-    anon_node_id: ast::NodeId,
+    opaque_node_id: ast::NodeId,
 ) -> bool {
     let mut node_id = tcx
         .hir
@@ -851,9 +854,9 @@ pub fn may_define_existential_type(
         .unwrap();
     // named existential types can be defined by any siblings or
     // children of siblings
-    let mod_id = tcx.hir.get_parent(anon_node_id);
+    let mod_id = tcx.hir.get_parent(opaque_node_id);
     // so we walk up the node tree until we hit the root or the parent
-    // of the anon type
+    // of the opaque type
     while node_id != mod_id && node_id != ast::CRATE_NODE_ID {
         node_id = tcx.hir.get_parent(node_id);
     }
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index c283c4d3caba3..b8dd2a12fb58d 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -483,7 +483,7 @@ fn ty_is_local_constructor(ty: Ty, in_crate: InCrate) -> bool {
         ty::Closure(..) |
         ty::Generator(..) |
         ty::GeneratorWitness(..) |
-        ty::Anon(..) => {
+        ty::Opaque(..) => {
             bug!("ty_is_local invoked on unexpected type: {:?}", ty)
         }
     }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index b34378151ccb3..a7c697c1cbafd 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -258,7 +258,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 ty::Tuple(..) => Some(10),
                 ty::Projection(..) => Some(11),
                 ty::Param(..) => Some(12),
-                ty::Anon(..) => Some(13),
+                ty::Opaque(..) => Some(13),
                 ty::Never => Some(14),
                 ty::Adt(adt, ..) => match adt.adt_kind() {
                     AdtKind::Struct => Some(15),
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 939ba92c7badf..e50f59cbc82c1 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -366,7 +366,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
 
         let ty = ty.super_fold_with(self);
         match ty.sty {
-            ty::Anon(def_id, substs) if !substs.has_escaping_regions() => { // (*)
+            ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*)
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal {
                     Reveal::UserFacing => ty,
@@ -986,7 +986,7 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>(
         ty::Projection(ref data) => {
             (data.trait_ref(tcx).def_id, data.substs)
         }
-        ty::Anon(def_id, substs) => (def_id, substs),
+        ty::Opaque(def_id, substs) => (def_id, substs),
         ty::Infer(ty::TyVar(_)) => {
             // If the self-type is an inference variable, then it MAY wind up
             // being a projected type, so induce an ambiguity.
@@ -1518,7 +1518,7 @@ fn confirm_impl_candidate<'cx, 'gcx, 'tcx>(
     let substs = translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.node);
     let ty = if let ty::AssociatedKind::Existential = assoc_ty.item.kind {
         let item_substs = Substs::identity_for_item(tcx, assoc_ty.item.def_id);
-        tcx.mk_anon(assoc_ty.item.def_id, item_substs)
+        tcx.mk_opaque(assoc_ty.item.def_id, item_substs)
     } else {
         tcx.type_of(assoc_ty.item.def_id)
     };
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 3a0f770082409..fd8898dffd4f2 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -258,7 +258,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
         ty::Dynamic(..)
         | ty::Projection(..)
         | ty::Param(_)
-        | ty::Anon(..)
+        | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Generator(..) => false,
     }
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 8b4954cc501dd..ea8bc3b20aae9 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -99,7 +99,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let ty = ty.super_fold_with(self);
         match ty.sty {
-            ty::Anon(def_id, substs) if !substs.has_escaping_regions() => {
+            ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => {
                 // (*)
                 // Only normalize `impl Trait` after type-checking, usually in codegen.
                 match self.param_env.reveal {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 69bdeec6eea23..232ef108537fe 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1492,7 +1492,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         // before we go into the whole skolemization thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().sty {
-            ty::Projection(_) | ty::Anon(..) => {}
+            ty::Projection(_) | ty::Opaque(..) => {}
             ty::Infer(ty::TyVar(_)) => {
                 span_bug!(obligation.cause.span,
                     "Self=_ should have been handled by assemble_candidates");
@@ -1528,7 +1528,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty {
             ty::Projection(ref data) =>
                 (data.trait_ref(self.tcx()).def_id, data.substs),
-            ty::Anon(def_id, substs) => (def_id, substs),
+            ty::Opaque(def_id, substs) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
@@ -2203,7 +2203,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 ))
             }
 
-            ty::Projection(_) | ty::Param(_) | ty::Anon(..) => None,
+            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
             ty::Infer(ty::CanonicalTy(_)) |
@@ -2265,7 +2265,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                 }
             }
 
-            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Anon(..) => {
+            ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
             }
@@ -2369,7 +2369,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                     .collect()
             }
 
-            ty::Anon(def_id, substs) => {
+            ty::Opaque(def_id, substs) => {
                 // We can resolve the `impl Trait` to its concrete type,
                 // which enforces a DAG between the functions requiring
                 // the auto trait bounds in question.
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 6981d92f05f00..eb6f7140a7db7 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2136,7 +2136,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
             self,
             Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
             Generator, GeneratorWitness, Dynamic, Closure, Tuple,
-            Param, Infer, Projection, Anon, Foreign);
+            Param, Infer, Projection, Opaque, Foreign);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("Region interner: #{}", self.interners.region.borrow().len());
@@ -2606,8 +2606,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
-        self.mk_ty(Anon(def_id, substs))
+    pub fn mk_opaque(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(Opaque(def_id, substs))
     }
 
     pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index aa6ee420a2162..2b833c57140b4 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -229,7 +229,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
                     "type parameter".to_string()
                 }
             }
-            ty::Anon(..) => "anonymized type".to_string(),
+            ty::Opaque(..) => "opaque type".to_string(),
             ty::Error => "type error".to_string(),
         }
     }
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 567d1c668f7c7..22a77bd6253c8 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -47,7 +47,7 @@ pub enum SimplifiedTypeGen<D>
     ClosureSimplifiedType(D),
     GeneratorSimplifiedType(D),
     GeneratorWitnessSimplifiedType(usize),
-    AnonSimplifiedType(D),
+    OpaqueSimplifiedType(D),
     FunctionSimplifiedType(usize),
     ParameterSimplifiedType,
     ForeignSimplifiedType(DefId),
@@ -115,8 +115,8 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 None
             }
         }
-        ty::Anon(def_id, _) => {
-            Some(AnonSimplifiedType(def_id))
+        ty::Opaque(def_id, _) => {
+            Some(OpaqueSimplifiedType(def_id))
         }
         ty::Foreign(def_id) => {
             Some(ForeignSimplifiedType(def_id))
@@ -146,7 +146,7 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
             ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
             GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
             GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),
-            AnonSimplifiedType(d) => AnonSimplifiedType(map(d)),
+            OpaqueSimplifiedType(d) => OpaqueSimplifiedType(map(d)),
             FunctionSimplifiedType(n) => FunctionSimplifiedType(n),
             ParameterSimplifiedType => ParameterSimplifiedType,
             ForeignSimplifiedType(d) => ForeignSimplifiedType(d),
@@ -181,7 +181,7 @@ impl<'a, 'gcx, D> HashStable<StableHashingContext<'a>> for SimplifiedTypeGen<D>
             ClosureSimplifiedType(d) => d.hash_stable(hcx, hasher),
             GeneratorSimplifiedType(d) => d.hash_stable(hcx, hasher),
             GeneratorWitnessSimplifiedType(n) => n.hash_stable(hcx, hasher),
-            AnonSimplifiedType(d) => d.hash_stable(hcx, hasher),
+            OpaqueSimplifiedType(d) => d.hash_stable(hcx, hasher),
             FunctionSimplifiedType(n) => n.hash_stable(hcx, hasher),
             ForeignSimplifiedType(d) => d.hash_stable(hcx, hasher),
         }
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index b9371ec39ccda..341ce40d153b0 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -150,7 +150,7 @@ impl FlagComputation {
                 self.add_projection_ty(data);
             }
 
-            &ty::Anon(_, substs) => {
+            &ty::Opaque(_, substs) => {
                 self.add_flags(TypeFlags::HAS_PROJECTION);
                 self.add_substs(substs);
             }
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 26010c3d5f55c..a661125d1ca03 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -771,7 +771,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
         // in the normalized form
         if self.just_constrained {
             match t.sty {
-                ty::Projection(..) | ty::Anon(..) => { return false; }
+                ty::Projection(..) | ty::Opaque(..) => { return false; }
                 _ => { }
             }
         }
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index e38bb411a14f9..0272865bda45b 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -385,7 +385,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
         ty::FnPtr(_) |
         ty::Projection(_) |
         ty::Param(_) |
-        ty::Anon(..) |
+        ty::Opaque(..) |
         ty::Infer(_) |
         ty::Error |
         ty::GeneratorWitness(..) |
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 4524c486272b5..17d613a2b181a 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1103,7 +1103,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             }
 
             // Types with no meaningful known layout.
-            ty::Projection(_) | ty::Anon(..) => {
+            ty::Projection(_) | ty::Opaque(..) => {
                 let normalized = tcx.normalize_erasing_regions(param_env, ty);
                 if ty == normalized {
                     return Err(LayoutError::Unknown(ty));
@@ -1373,7 +1373,7 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
                 }
             }
 
-            ty::Projection(_) | ty::Anon(..) => {
+            ty::Projection(_) | ty::Opaque(..) => {
                 let normalized = tcx.normalize_erasing_regions(param_env, ty);
                 if ty == normalized {
                     Err(err)
@@ -1685,7 +1685,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
                 }
             }
 
-            ty::Projection(_) | ty::Anon(..) | ty::Param(_) |
+            ty::Projection(_) | ty::Opaque(..) | ty::Param(_) |
             ty::Infer(_) | ty::Error => {
                 bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 63308ac46d10f..7666b3c9bb2b7 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -559,7 +559,7 @@ impl<'tcx> TyS<'tcx> {
 
     pub fn is_suggestable(&self) -> bool {
         match self.sty {
-            TyKind::Anon(..) |
+            TyKind::Opaque(..) |
             TyKind::FnDef(..) |
             TyKind::FnPtr(..) |
             TyKind::Dynamic(..) |
@@ -2265,7 +2265,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                     .collect()
             }
 
-            Projection(..) | Anon(..) => {
+            Projection(..) | Opaque(..) => {
                 // must calculate explicitly.
                 // FIXME: consider special-casing always-Sized projections
                 vec![ty]
diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs
index 5171bfb7e0608..68f6707087687 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -144,7 +144,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             ty::Float(..) |       // OutlivesScalar
             ty::Never |           // ...
             ty::Adt(..) |         // OutlivesNominalType
-            ty::Anon(..) |        // OutlivesNominalType (ish)
+            ty::Opaque(..) |        // OutlivesNominalType (ish)
             ty::Foreign(..) |     // OutlivesNominalType
             ty::Str |             // OutlivesScalar (ish)
             ty::Array(..) |       // ...
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index d72e48c04fed4..8f84fb7e39101 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -564,11 +564,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
         }
 
-        (&ty::Anon(a_def_id, a_substs), &ty::Anon(b_def_id, b_substs))
+        (&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
             if a_def_id == b_def_id =>
         {
             let substs = relate_substs(relation, None, a_substs, b_substs)?;
-            Ok(tcx.mk_anon(a_def_id, substs))
+            Ok(tcx.mk_opaque(a_def_id, substs))
         }
 
         _ =>
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 60b85e8a8eb9a..737878375ec18 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -865,7 +865,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
             ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
             ty::Projection(ref data) => ty::Projection(data.fold_with(folder)),
-            ty::Anon(did, substs) => ty::Anon(did, substs.fold_with(folder)),
+            ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
             ty::Bool | ty::Char | ty::Str | ty::Int(_) |
             ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
             ty::Param(..) | ty::Never | ty::Foreign(..) => return self
@@ -900,7 +900,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::GeneratorWitness(ref types) => types.visit_with(visitor),
             ty::Closure(_did, ref substs) => substs.visit_with(visitor),
             ty::Projection(ref data) => data.visit_with(visitor),
-            ty::Anon(_, ref substs) => substs.visit_with(visitor),
+            ty::Opaque(_, ref substs) => substs.visit_with(visitor),
             ty::Bool | ty::Char | ty::Str | ty::Int(_) |
             ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
             ty::Param(..) | ty::Never | ty::Foreign(..) => false,
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 7c7ee9b330ecc..6d3ee69a88ced 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -157,13 +157,13 @@ pub enum TyKind<'tcx> {
     /// `<T as Trait<..>>::N`.
     Projection(ProjectionTy<'tcx>),
 
-    /// Anonymized (`impl Trait`) type found in a return type.
+    /// Opaque (`impl Trait`) type found in a return type.
     /// The DefId comes either from
     /// * the `impl Trait` ast::Ty node,
     /// * or the `existential type` declaration
     /// The substitutions are for the generics of the function in question.
     /// After typeck, the concrete type can be found in the `types` map.
-    Anon(DefId, &'tcx Substs<'tcx>),
+    Opaque(DefId, &'tcx Substs<'tcx>),
 
     /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
     Param(ParamTy),
@@ -1764,7 +1764,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
 
     pub fn is_impl_trait(&self) -> bool {
         match self.sty {
-            Anon(..) => true,
+            Opaque(..) => true,
             _ => false,
         }
     }
@@ -1791,7 +1791,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
                 }
                 v
             }
-            Adt(_, substs) | Anon(_, substs) => {
+            Adt(_, substs) | Opaque(_, substs) => {
                 substs.regions().collect()
             }
             Closure(_, ClosureSubsts { ref substs }) |
@@ -1876,7 +1876,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
             ty::Adt(def, _substs) =>
                 def.sized_constraint(tcx).is_empty(),
 
-            ty::Projection(_) | ty::Param(_) | ty::Anon(..) => false,
+            ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
 
             ty::Infer(ty::TyVar(_)) => false,
 
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index f7679dc8ce0f0..cc0429de2f624 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -956,7 +956,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Can refer to a type which may drop.
         // FIXME(eddyb) check this against a ParamEnv.
         ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) |
-        ty::Anon(..) | ty::Infer(_) | ty::Error => true,
+        ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
 
         // Structural recursion.
         ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index 6d3ba22c57f27..cf87c2d457471 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -114,7 +114,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
                 substs.types().rev().chain(opt_ty)
             }));
         }
-        ty::Adt(_, substs) | ty::Anon(_, substs) => {
+        ty::Adt(_, substs) | ty::Opaque(_, substs) => {
             stack.extend(substs.types().rev());
         }
         ty::Closure(_, ref substs) => {
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index fc55d8f34a23f..63206a660df41 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -360,7 +360,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
                     // types appearing in the fn signature
                 }
 
-                ty::Anon(did, substs) => {
+                ty::Opaque(did, substs) => {
                     // all of the requirements on type parameters
                     // should've been checked by the instantiation
                     // of whatever returned this exact `impl Trait`.
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 0f15c75c2fb36..3cee594043116 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -17,7 +17,7 @@ use ty::{BrAnon, BrEnv, BrFresh, BrNamed};
 use ty::{Bool, Char, Adt};
 use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
 use ty::{Param, RawPtr, Ref, Never, Tuple};
-use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Anon};
+use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
 use ty::{Dynamic, Int, Uint, Infer};
 use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
 use util::nodemap::FxHashSet;
@@ -1103,9 +1103,9 @@ define_print! {
                 }
                 Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]),
                 Projection(ref data) => data.print(f, cx),
-                Anon(def_id, substs) => {
+                Opaque(def_id, substs) => {
                     if cx.is_verbose {
-                        return write!(f, "Anon({:?}, {:?})", def_id, substs);
+                        return write!(f, "Opaque({:?}, {:?})", def_id, substs);
                     }
 
                     ty::tls::with(|tcx| {
diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs
index a08b964cd721d..95a094bf909e1 100644
--- a/src/librustc_codegen_llvm/debuginfo/type_names.rs
+++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs
@@ -174,7 +174,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::Error |
         ty::Infer(_) |
         ty::Projection(..) |
-        ty::Anon(..) |
+        ty::Opaque(..) |
         ty::GeneratorWitness(..) |
         ty::Param(_) => {
             bug!("debuginfo: Trying to create type name for \
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 2c410e8efb10a..33181bd80e937 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -721,7 +721,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             ty::Generator(..) |
             ty::GeneratorWitness(..) |
             ty::Projection(..) |
-            ty::Anon(..) |
+            ty::Opaque(..) |
             ty::FnDef(..) => bug!("Unexpected type in foreign function"),
         }
     }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
index af42667016780..265cd305eb97e 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
@@ -72,7 +72,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         // types.
         let param_env = self.param_env;
         let mir_output_ty = mir.local_decls[RETURN_PLACE].ty;
-        let anon_type_map =
+        let opaque_type_map =
             self.fully_perform_op(
                 Locations::All,
                 CustomTypeOp::new(
@@ -80,8 +80,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         let mut obligations = ObligationAccumulator::default();
 
                         let dummy_body_id = ObligationCause::dummy().body_id;
-                        let (output_ty, anon_type_map) =
-                            obligations.add(infcx.instantiate_anon_types(
+                        let (output_ty, opaque_type_map) =
+                            obligations.add(infcx.instantiate_opaque_types(
                                 mir_def_id,
                                 dummy_body_id,
                                 param_env,
@@ -92,8 +92,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                             output_ty
                         );
                         debug!(
-                            "equate_inputs_and_outputs: anon_type_map={:#?}",
-                            anon_type_map
+                            "equate_inputs_and_outputs: opaque_type_map={:#?}",
+                            opaque_type_map
                         );
 
                         debug!(
@@ -106,29 +106,30 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                                 .eq(output_ty, mir_output_ty)?,
                         );
 
-                        for (&anon_def_id, anon_decl) in &anon_type_map {
-                            let anon_defn_ty = tcx.type_of(anon_def_id);
-                            let anon_defn_ty = anon_defn_ty.subst(tcx, anon_decl.substs);
-                            let anon_defn_ty = renumber::renumber_regions(
+                        for (&opaque_def_id, opaque_decl) in &opaque_type_map {
+                            let opaque_defn_ty = tcx.type_of(opaque_def_id);
+                            let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs);
+                            let opaque_defn_ty = renumber::renumber_regions(
                                 infcx,
-                                &anon_defn_ty,
+                                &opaque_defn_ty,
                             );
                             debug!(
                                 "equate_inputs_and_outputs: concrete_ty={:?}",
-                                anon_decl.concrete_ty
+                                opaque_decl.concrete_ty
                             );
-                            debug!("equate_inputs_and_outputs: anon_defn_ty={:?}", anon_defn_ty);
+                            debug!("equate_inputs_and_outputs: opaque_defn_ty={:?}",
+                                   opaque_defn_ty);
                             obligations.add(
                                 infcx
                                     .at(&ObligationCause::dummy(), param_env)
-                                    .eq(anon_decl.concrete_ty, anon_defn_ty)?,
+                                    .eq(opaque_decl.concrete_ty, opaque_defn_ty)?,
                             );
                         }
 
                         debug!("equate_inputs_and_outputs: equated");
 
                         Ok(InferOk {
-                            value: Some(anon_type_map),
+                            value: Some(opaque_type_map),
                             obligations: obligations.into_vec(),
                         })
                     },
@@ -146,22 +147,22 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                 None
             });
 
-        // Finally, if we instantiated the anon types successfully, we
+        // Finally, if we instantiated the opaque types successfully, we
         // have to solve any bounds (e.g., `-> impl Iterator` needs to
         // prove that `T: Iterator` where `T` is the type we
         // instantiated it with).
-        if let Some(anon_type_map) = anon_type_map {
+        if let Some(opaque_type_map) = opaque_type_map {
             self.fully_perform_op(
                 Locations::All,
                 CustomTypeOp::new(
                     |_cx| {
-                        infcx.constrain_anon_types(&anon_type_map, universal_region_relations);
+                        infcx.constrain_opaque_types(&opaque_type_map, universal_region_relations);
                         Ok(InferOk {
                             value: (),
                             obligations: vec![],
                         })
                     },
-                    || "anon_type_map".to_string(),
+                    || "opaque_type_map".to_string(),
                 ),
             ).unwrap();
         }
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 3187a91e22597..dc437ee8510d7 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -385,7 +385,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
             ty::Projection(..) |
             ty::Param(_) |
             ty::GeneratorWitness(_) |
-            ty::Anon(..) => {
+            ty::Opaque(..) => {
                 bug!("DefPathBasedNames: Trying to create type name for \
                                          unexpected type: {:?}", t);
             }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 5166f69ba0330..27f27ef9a1a50 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -490,7 +490,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
             ty::FnDef(def_id, ..) |
             ty::Closure(def_id, ..) |
             ty::Generator(def_id, ..) |
-            ty::Anon(def_id, _) => Some(def_id),
+            ty::Opaque(def_id, _) => Some(def_id),
             _ => None
         };
 
@@ -652,7 +652,7 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> {
     in_body: bool,
     span: Span,
     empty_tables: &'a ty::TypeckTables<'tcx>,
-    visited_anon_tys: FxHashSet<DefId>
+    visited_opaque_tys: FxHashSet<DefId>
 }
 
 impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
@@ -954,7 +954,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
                     return true;
                 }
             }
-            ty::Anon(def_id, ..) => {
+            ty::Opaque(def_id, ..) => {
                 for predicate in &self.tcx.predicates_of(def_id).predicates {
                     let trait_ref = match *predicate {
                         ty::Predicate::Trait(ref poly_trait_predicate) => {
@@ -977,10 +977,10 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
                             return true;
                         }
                         for subst in trait_ref.substs.iter() {
-                            // Skip repeated `Anon`s to avoid infinite recursion.
+                            // Skip repeated `Opaque`s to avoid infinite recursion.
                             if let UnpackedKind::Type(ty) = subst.unpack() {
-                                if let ty::Anon(def_id, ..) = ty.sty {
-                                    if !self.visited_anon_tys.insert(def_id) {
+                                if let ty::Opaque(def_id, ..) = ty.sty {
+                                    if !self.visited_opaque_tys.insert(def_id) {
                                         continue;
                                     }
                                 }
@@ -1726,7 +1726,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         in_body: false,
         span: krate.span,
         empty_tables: &empty_tables,
-        visited_anon_tys: FxHashSet()
+        visited_opaque_tys: FxHashSet()
     };
     intravisit::walk_crate(&mut visitor, krate);
 
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index a27a447ad4b09..e3ec2e6b9ce02 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -123,7 +123,7 @@ fn dropck_outlives<'tcx>(
 
                             // A projection that we couldn't resolve - it
                             // might have a destructor.
-                            ty::Projection(..) | ty::Anon(..) => {
+                            ty::Projection(..) | ty::Opaque(..) => {
                                 result.kinds.push(ty.into());
                             }
 
@@ -266,7 +266,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
         }),
 
         // Types that can't be resolved. Pass them forward.
-        ty::Projection(..) | ty::Anon(..) | ty::Param(..) => Ok(DtorckConstraint {
+        ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => Ok(DtorckConstraint {
             outlives: vec![],
             dtorck_types: vec![ty],
             overflows: vec![],
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 804aad3c0ecce..b3ed44264644e 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1347,7 +1347,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
                 let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
                 self.normalize_ty(
                     span,
-                    tcx.mk_anon(did, substs),
+                    tcx.mk_opaque(did, substs),
                 )
             }
             Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) |
@@ -1540,7 +1540,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
         });
         debug!("impl_trait_ty_to_ty: final substs = {:?}", substs);
 
-        let ty = tcx.mk_anon(def_id, substs);
+        let ty = tcx.mk_opaque(def_id, substs);
         debug!("impl_trait_ty_to_ty: {}", ty);
         ty
     }
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 52e5e57f74759..ebe0c279aafab 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -78,8 +78,8 @@ enum PointerKind<'tcx> {
     Length,
     /// The unsize info of this projection
     OfProjection(&'tcx ty::ProjectionTy<'tcx>),
-    /// The unsize info of this anon ty
-    OfAnon(DefId, &'tcx Substs<'tcx>),
+    /// The unsize info of this opaque ty
+    OfOpaque(DefId, &'tcx Substs<'tcx>),
     /// The unsize info of this parameter
     OfParam(&'tcx ty::ParamTy),
 }
@@ -124,7 +124,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             ty::Foreign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
             ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)),
-            ty::Anon(def_id, substs) => Some(PointerKind::OfAnon(def_id, substs)),
+            ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
             ty::Param(ref p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
             ty::Infer(_) => None,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 5cc87e12ed069..b23f06998841c 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -91,7 +91,7 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use std::slice;
 use namespace::Namespace;
 use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
-use rustc::infer::anon_types::AnonTypeDecl;
+use rustc::infer::opaque_types::OpaqueTypeDecl;
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::middle::region;
 use rustc::mir::interpret::{ConstValue, GlobalId};
@@ -212,11 +212,11 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
     deferred_generator_interiors: RefCell<Vec<(hir::BodyId, Ty<'tcx>)>>,
 
-    // Anonymized types found in explicit return types and their
+    // Opaque types found in explicit return types and their
     // associated fresh inference variable. Writeback resolves these
     // variables to get the concrete type, which can be used to
-    // deanonymize Anon, after typeck is done with all functions.
-    anon_types: RefCell<DefIdMap<AnonTypeDecl<'tcx>>>,
+    // 'de-opaque' OpaqueTypeDecl, after typeck is done with all functions.
+    opaque_types: RefCell<DefIdMap<OpaqueTypeDecl<'tcx>>>,
 
     /// Each type parameter has an implicit region bound that
     /// indicates it must outlive at least the function body (the user
@@ -635,7 +635,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
             deferred_call_resolutions: RefCell::new(DefIdMap()),
             deferred_cast_checks: RefCell::new(Vec::new()),
             deferred_generator_interiors: RefCell::new(Vec::new()),
-            anon_types: RefCell::new(DefIdMap()),
+            opaque_types: RefCell::new(DefIdMap()),
             implicit_region_bound,
             body_id,
         }
@@ -1024,7 +1024,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
 
     let declared_ret_ty = fn_sig.output();
     fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
-    let revealed_ret_ty = fcx.instantiate_anon_types_from_return_value(fn_id, &declared_ret_ty);
+    let revealed_ret_ty = fcx.instantiate_opaque_types_from_return_value(fn_id, &declared_ret_ty);
     fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
     fn_sig = fcx.tcx.mk_fn_sig(
         fn_sig.inputs().iter().cloned(),
@@ -2217,24 +2217,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         result
     }
 
-    /// Replace the anonymized types from the return value of the
-    /// function with type variables and records the `AnonTypeMap` for
+    /// Replace the opaque types from the return value of the
+    /// function with type variables and records the `OpaqueTypeMap` for
     /// later use during writeback. See
-    /// `InferCtxt::instantiate_anon_types` for more details.
-    fn instantiate_anon_types_from_return_value<T: TypeFoldable<'tcx>>(
+    /// `InferCtxt::instantiate_opaque_types` for more details.
+    fn instantiate_opaque_types_from_return_value<T: TypeFoldable<'tcx>>(
         &self,
         fn_id: ast::NodeId,
         value: &T,
     ) -> T {
         let fn_def_id = self.tcx.hir.local_def_id(fn_id);
         debug!(
-            "instantiate_anon_types_from_return_value(fn_def_id={:?}, value={:?})",
+            "instantiate_opaque_types_from_return_value(fn_def_id={:?}, value={:?})",
             fn_def_id,
             value
         );
 
-        let (value, anon_type_map) = self.register_infer_ok_obligations(
-            self.instantiate_anon_types(
+        let (value, opaque_type_map) = self.register_infer_ok_obligations(
+            self.instantiate_opaque_types(
                 fn_def_id,
                 self.body_id,
                 self.param_env,
@@ -2242,9 +2242,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             )
         );
 
-        let mut anon_types = self.anon_types.borrow_mut();
-        for (ty, decl) in anon_type_map {
-            let old_value = anon_types.insert(ty, decl);
+        let mut opaque_types = self.opaque_types.borrow_mut();
+        for (ty, decl) in opaque_type_map {
+            let old_value = opaque_types.insert(ty, decl);
             assert!(old_value.is_none(), "instantiated twice: {:?}/{:?}", ty, decl);
         }
 
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 867864b3853d0..05fe0cb9262cc 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -347,8 +347,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                                        body_hir_id,
                                        call_site_region);
 
-        self.constrain_anon_types(
-            &self.fcx.anon_types.borrow(),
+        self.constrain_opaque_types(
+            &self.fcx.opaque_types.borrow(),
             self.outlives_environment.free_region_map(),
         );
     }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 99e0e8775b0cd..9e09f2cd1851e 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -18,7 +18,7 @@ use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::util::ExplicitSelf;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::middle::lang_items;
-use rustc::infer::anon_types::may_define_existential_type;
+use rustc::infer::opaque_types::may_define_existential_type;
 
 use syntax::ast;
 use syntax::feature_gate::{self, GateIssue};
@@ -576,13 +576,13 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
     ty.fold_with(&mut ty::fold::BottomUpFolder {
         tcx: fcx.tcx,
         fldop: |ty| {
-            if let ty::Anon(def_id, substs) = ty.sty {
-                trace!("check_existential_types: anon_ty, {:?}, {:?}", def_id, substs);
+            if let ty::Opaque(def_id, substs) = ty.sty {
+                trace!("check_existential_types: opaque_ty, {:?}, {:?}", def_id, substs);
                 let generics = tcx.generics_of(def_id);
                 // only check named existential types
                 if generics.parent.is_none() {
-                    let anon_node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-                    if may_define_existential_type(tcx, fn_def_id, anon_node_id) {
+                    let opaque_node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+                    if may_define_existential_type(tcx, fn_def_id, opaque_node_id) {
                         trace!("check_existential_types may define. Generics: {:#?}", generics);
                         let mut seen: FxHashMap<_, Vec<_>> = FxHashMap();
                         for (subst, param) in substs.iter().zip(&generics.params) {
@@ -674,7 +674,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
                         }
                     }
                 } // if is_named_existential_type
-            } // if let Anon
+            } // if let Opaque
             ty
         },
         reg_op: |reg| reg,
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 0d8401c1c86ef..0b2f92ac4bcb6 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -48,7 +48,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
         wbcx.visit_fru_field_types();
-        wbcx.visit_anon_types(body.value.span);
+        wbcx.visit_opaque_types(body.value.span);
         wbcx.visit_cast_types();
         wbcx.visit_free_region_map();
         wbcx.visit_user_provided_tys();
@@ -393,18 +393,18 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         }
     }
 
-    fn visit_anon_types(&mut self, span: Span) {
-        for (&def_id, anon_defn) in self.fcx.anon_types.borrow().iter() {
+    fn visit_opaque_types(&mut self, span: Span) {
+        for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() {
             let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
-            let instantiated_ty = self.resolve(&anon_defn.concrete_ty, &node_id);
+            let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &node_id);
 
             let generics = self.tcx().generics_of(def_id);
 
             let definition_ty = if generics.parent.is_some() {
                 // impl trait
-                self.fcx.infer_anon_definition_from_instantiation(
+                self.fcx.infer_opaque_definition_from_instantiation(
                     def_id,
-                    anon_defn,
+                    opaque_defn,
                     instantiated_ty,
                 )
             } else {
@@ -427,8 +427,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                         // find a type parameter
                         if let ty::Param(..) = ty.sty {
                             // look it up in the substitution list
-                            assert_eq!(anon_defn.substs.len(), generics.params.len());
-                            for (subst, param) in anon_defn.substs.iter().zip(&generics.params) {
+                            assert_eq!(opaque_defn.substs.len(), generics.params.len());
+                            for (subst, param) in opaque_defn.substs.iter().zip(&generics.params) {
                                 if let UnpackedKind::Type(subst) = subst.unpack() {
                                     if subst == ty {
                                         // found it in the substitution list, replace with the
@@ -460,7 +460,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                             ty::ReStatic => region,
                             _ => {
                                 trace!("checking {:?}", region);
-                                for (subst, p) in anon_defn.substs.iter().zip(&generics.params) {
+                                for (subst, p) in opaque_defn.substs.iter().zip(&generics.params) {
                                     if let UnpackedKind::Lifetime(subst) = subst.unpack() {
                                         if subst == region {
                                             // found it in the substitution list, replace with the
@@ -477,7 +477,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                                         }
                                     }
                                 }
-                                trace!("anon_defn: {:#?}", anon_defn);
+                                trace!("opaque_defn: {:#?}", opaque_defn);
                                 trace!("generics: {:#?}", generics);
                                 self.tcx()
                                     .sess
@@ -501,7 +501,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                 })
             };
 
-            if let ty::Anon(defin_ty_def_id, _substs) = definition_ty.sty {
+            if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.sty {
                 if def_id == defin_ty_def_id {
                     // Concrete type resolved to the existential type itself
                     // Force a cycle error
@@ -516,8 +516,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                 if old != definition_ty {
                     span_bug!(
                         span,
-                        "visit_anon_types tried to write \
-                         different types for the same existential type: {:?}, {:?}, {:?}",
+                        "visit_opaque_types tried to write \
+                        different types for the same existential type: {:?}, {:?}, {:?}",
                         def_id,
                         definition_ty,
                         old,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index b956c72b3a2da..2a01ac555ae5c 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1643,9 +1643,10 @@ fn explicit_predicates_of<'a, 'tcx>(
         Node::ImplItem(item) => match item.node {
             ImplItemKind::Existential(ref bounds) => {
                 let substs = Substs::identity_for_item(tcx, def_id);
-                let anon_ty = tcx.mk_anon(def_id, substs);
+                let opaque_ty = tcx.mk_opaque(def_id, substs);
 
                 // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
+<<<<<<< HEAD
                 let bounds = compute_bounds(
                     &icx,
                     anon_ty,
@@ -1653,8 +1654,15 @@ fn explicit_predicates_of<'a, 'tcx>(
                     SizedByDefault::Yes,
                     tcx.def_span(def_id),
                 );
-
-                predicates.extend(bounds.predicates(tcx, anon_ty));
+=======
+                let bounds = compute_bounds(&icx,
+                                            opaque_ty,
+                                            bounds,
+                                            SizedByDefault::Yes,
+                                            tcx.def_span(def_id));
+>>>>>>> ca386bc20a... Changing TyAnon -> TyOpaque and relevant functions
+
+                predicates.extend(bounds.predicates(tcx, opaque_ty));
                 &item.generics
             }
             _ => &item.generics,
@@ -1684,12 +1692,12 @@ fn explicit_predicates_of<'a, 'tcx>(
                     ref generics,
                 }) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
-                    let anon_ty = tcx.mk_anon(def_id, substs);
+                    let opaque_ty = tcx.mk_opaque(def_id, substs);
 
                     // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
                     let bounds = compute_bounds(
                         &icx,
-                        anon_ty,
+                        opaque_ty,
                         bounds,
                         SizedByDefault::Yes,
                         tcx.def_span(def_id),
@@ -1699,11 +1707,11 @@ fn explicit_predicates_of<'a, 'tcx>(
                         // impl Trait
                         return ty::GenericPredicates {
                             parent: None,
-                            predicates: bounds.predicates(tcx, anon_ty),
+                            predicates: bounds.predicates(tcx, opaque_ty),
                         };
                     } else {
                         // named existential types
-                        predicates.extend(bounds.predicates(tcx, anon_ty));
+                        predicates.extend(bounds.predicates(tcx, opaque_ty));
                         generics
                     }
                 }
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 37b0b83ccd088..07f6fa5e8ad13 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -1,4 +1,4 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+//n Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -62,7 +62,7 @@ struct ParameterCollector {
 impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
         match t.sty {
-            ty::Projection(..) | ty::Anon(..) if !self.include_nonconstraining => {
+            ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => {
                 // projections are not injective
                 return false;
             }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index a79215497182e..95544da0b8e0d 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -302,7 +302,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_trait_ref(current, data.trait_ref(tcx), variance);
             }
 
-            ty::Anon(_, substs) => {
+            ty::Opaque(_, substs) => {
                 self.add_constraints_from_invariant_substs(current, substs, variance);
             }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 5c23d0f6b3990..c07906e0dbf31 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2672,11 +2672,11 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
 
             ty::Param(ref p) => Generic(p.name.to_string()),
 
-            ty::Anon(def_id, substs) => {
+            ty::Opaque(def_id, substs) => {
                 // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                 // by looking up the projections associated with the def_id.
                 let predicates_of = cx.tcx.predicates_of(def_id);
-                let substs = cx.tcx.lift(&substs).expect("Anon lift failed");
+                let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
                 let bounds = predicates_of.instantiate(cx.tcx, substs);
                 let mut regions = vec![];
                 let mut has_sized = false;

From c34dd37f854dc4fcb8c2e3eebe4f9dae6b24784a Mon Sep 17 00:00:00 2001
From: Eduard-Mihai Burtescu <edy.burt@gmail.com>
Date: Thu, 6 Sep 2018 15:04:21 +0300
Subject: [PATCH 06/30] rustc_resolve: don't record uniform_paths canaries as
 reexports.

---
 src/librustc_resolve/resolve_imports.rs       | 10 +++++++++-
 .../uniform-paths/auxiliary/issue-53691.rs    | 19 +++++++++++++++++++
 .../run-pass/uniform-paths/issue-53691.rs     | 18 ++++++++++++++++++
 3 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs
 create mode 100644 src/test/run-pass/uniform-paths/issue-53691.rs

diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index c60f9293d58e7..3e7f33265d1fd 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -1155,7 +1155,15 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                 None => continue,
             };
 
-            if binding.is_import() || binding.is_macro_def() {
+            // Don't reexport `uniform_path` canaries.
+            let non_canary_import = match binding.kind {
+                NameBindingKind::Import { directive, .. } => {
+                    !directive.is_uniform_paths_canary
+                }
+                _ => false,
+            };
+
+            if non_canary_import || binding.is_macro_def() {
                 let def = binding.def();
                 if def != Def::Err {
                     if !def.def_id().is_local() {
diff --git a/src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs b/src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs
new file mode 100644
index 0000000000000..5845afd72fbe7
--- /dev/null
+++ b/src/test/run-pass/uniform-paths/auxiliary/issue-53691.rs
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// edition:2018
+
+#![feature(uniform_paths)]
+
+mod m { pub fn f() {} }
+mod n { pub fn g() {} }
+
+pub use m::f;
+pub use n::g;
diff --git a/src/test/run-pass/uniform-paths/issue-53691.rs b/src/test/run-pass/uniform-paths/issue-53691.rs
new file mode 100644
index 0000000000000..62be31d6b85fe
--- /dev/null
+++ b/src/test/run-pass/uniform-paths/issue-53691.rs
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-53691.rs
+
+extern crate issue_53691;
+
+fn main() {
+    issue_53691::f();
+    issue_53691::g();
+}

From f4d4faaeedbdb7271221c9b48fd809a5e8469445 Mon Sep 17 00:00:00 2001
From: ms2300 <matt.sewall@gmail.com>
Date: Sat, 25 Aug 2018 11:53:26 -0600
Subject: [PATCH 07/30] Fixing tests from anon -> opaque

---
 src/librustc_mir/transform/qualify_min_const_fn.rs     |  2 +-
 src/librustc_typeck/collect.rs                         | 10 +---------
 src/librustc_typeck/constrained_type_params.rs         |  2 +-
 .../generic_type_does_not_live_long_enough.nll.stderr  |  2 +-
 .../generic_type_does_not_live_long_enough.stderr      |  2 +-
 .../never_reveal_concrete_type.stderr                  |  2 +-
 .../no_revealing_outside_defining_module.stderr        |  4 ++--
 src/test/ui/impl-trait/equality2.rs                    |  2 +-
 src/test/ui/impl-trait/equality2.stderr                |  2 +-
 9 files changed, 10 insertions(+), 18 deletions(-)

diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 56e32ea5d1a23..eacc23c9c4fe2 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -100,7 +100,7 @@ fn check_ty(
                 span,
                 "mutable references in const fn are unstable".into(),
             )),
-            ty::Anon(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
+            ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
             ty::FnPtr(..) => {
                 return Err((span, "function pointers in const fn are unstable".into()))
             }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 2a01ac555ae5c..702af3d221b83 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1646,21 +1646,13 @@ fn explicit_predicates_of<'a, 'tcx>(
                 let opaque_ty = tcx.mk_opaque(def_id, substs);
 
                 // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
-<<<<<<< HEAD
                 let bounds = compute_bounds(
                     &icx,
-                    anon_ty,
+                    opaque_ty,
                     bounds,
                     SizedByDefault::Yes,
                     tcx.def_span(def_id),
                 );
-=======
-                let bounds = compute_bounds(&icx,
-                                            opaque_ty,
-                                            bounds,
-                                            SizedByDefault::Yes,
-                                            tcx.def_span(def_id));
->>>>>>> ca386bc20a... Changing TyAnon -> TyOpaque and relevant functions
 
                 predicates.extend(bounds.predicates(tcx, opaque_ty));
                 &item.generics
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 07f6fa5e8ad13..1b481fc5a7d31 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -1,4 +1,4 @@
-//n Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
diff --git a/src/test/ui/existential_types/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/existential_types/generic_type_does_not_live_long_enough.nll.stderr
index a480f54ac1873..471eda45dafdc 100644
--- a/src/test/ui/existential_types/generic_type_does_not_live_long_enough.nll.stderr
+++ b/src/test/ui/existential_types/generic_type_does_not_live_long_enough.nll.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/generic_type_does_not_live_long_enough.rs:16:18
    |
 LL |     let z: i32 = x; //~ ERROR mismatched types
-   |                  ^ expected i32, found anonymized type
+   |                  ^ expected i32, found opaque type
    |
    = note: expected type `i32`
               found type `WrongGeneric::<&{integer}>`
diff --git a/src/test/ui/existential_types/generic_type_does_not_live_long_enough.stderr b/src/test/ui/existential_types/generic_type_does_not_live_long_enough.stderr
index 189ad7d49a485..f1773b7c2fc8f 100644
--- a/src/test/ui/existential_types/generic_type_does_not_live_long_enough.stderr
+++ b/src/test/ui/existential_types/generic_type_does_not_live_long_enough.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/generic_type_does_not_live_long_enough.rs:16:18
    |
 LL |     let z: i32 = x; //~ ERROR mismatched types
-   |                  ^ expected i32, found anonymized type
+   |                  ^ expected i32, found opaque type
    |
    = note: expected type `i32`
               found type `WrongGeneric::<&{integer}>`
diff --git a/src/test/ui/existential_types/never_reveal_concrete_type.stderr b/src/test/ui/existential_types/never_reveal_concrete_type.stderr
index 449799c91b79a..ab937a9483c0c 100644
--- a/src/test/ui/existential_types/never_reveal_concrete_type.stderr
+++ b/src/test/ui/existential_types/never_reveal_concrete_type.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/never_reveal_concrete_type.rs:24:27
    |
 LL |     let _: &'static str = x; //~ mismatched types
-   |                           ^ expected reference, found anonymized type
+   |                           ^ expected reference, found opaque type
    |
    = note: expected type `&'static str`
               found type `NoReveal`
diff --git a/src/test/ui/existential_types/no_revealing_outside_defining_module.stderr b/src/test/ui/existential_types/no_revealing_outside_defining_module.stderr
index a1c98c6d4b89e..3f03174a4917b 100644
--- a/src/test/ui/existential_types/no_revealing_outside_defining_module.stderr
+++ b/src/test/ui/existential_types/no_revealing_outside_defining_module.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/no_revealing_outside_defining_module.rs:26:19
    |
 LL |     let _: &str = bomp(); //~ ERROR mismatched types
-   |                   ^^^^^^ expected &str, found anonymized type
+   |                   ^^^^^^ expected &str, found opaque type
    |
    = note: expected type `&str`
               found type `Boo`
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
 LL | fn bomp() -> boo::Boo {
    |              -------- expected `Boo` because of return type
 LL |     "" //~ ERROR mismatched types
-   |     ^^ expected anonymized type, found reference
+   |     ^^ expected opaque type, found reference
    |
    = note: expected type `Boo`
               found type `&'static str`
diff --git a/src/test/ui/impl-trait/equality2.rs b/src/test/ui/impl-trait/equality2.rs
index ec3dc15d8464e..2ce24cf789dd3 100644
--- a/src/test/ui/impl-trait/equality2.rs
+++ b/src/test/ui/impl-trait/equality2.rs
@@ -36,7 +36,7 @@ fn main() {
     //~^ ERROR mismatched types
     //~| expected type `u32`
     //~| found type `impl Foo`
-    //~| expected u32, found anonymized type
+    //~| expected u32, found opaque type
 
     let _: i32 = Leak::leak(hide(0_i32));
     //~^ ERROR mismatched types
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
index e4ff2f6824783..da51e35947a3b 100644
--- a/src/test/ui/impl-trait/equality2.stderr
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/equality2.rs:35:18
    |
 LL |     let _: u32 = hide(0_u32);
-   |                  ^^^^^^^^^^^ expected u32, found anonymized type
+   |                  ^^^^^^^^^^^ expected u32, found opaque type
    |
    = note: expected type `u32`
               found type `impl Foo`

From 1adfdefca2e18b5d7c65f0d19a75b15534e45e6b Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 7 Aug 2018 10:10:05 -0500
Subject: [PATCH 08/30] rustdoc: collect trait impls as an early pass

---
 src/librustdoc/clean/inline.rs               | 86 +++--------------
 src/librustdoc/core.rs                       |  4 +-
 src/librustdoc/passes/collect_trait_impls.rs | 99 ++++++++++++++++++++
 src/librustdoc/passes/mod.rs                 |  6 ++
 src/librustdoc/visit_ast.rs                  |  6 +-
 src/test/rustdoc/traits-in-bodies.rs         | 18 +++-
 6 files changed, 137 insertions(+), 82 deletions(-)
 create mode 100644 src/librustdoc/passes/collect_trait_impls.rs

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 75d7488d26a75..f9c631fcfcdb6 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -290,78 +290,12 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
         impls.extend(get_blanket_impls_with_def_id(cx, did));
     }
 
-    // If this is the first time we've inlined something from another crate, then
-    // we inline *all* impls from all the crates into this crate. Note that there's
-    // currently no way for us to filter this based on type, and we likely need
-    // many impls for a variety of reasons.
-    //
-    // Primarily, the impls will be used to populate the documentation for this
-    // type being inlined, but impls can also be used when generating
-    // documentation for primitives (no way to find those specifically).
-    if cx.populated_all_crate_impls.get() {
-        return impls;
-    }
-
-    cx.populated_all_crate_impls.set(true);
-
-    for &cnum in tcx.crates().iter() {
-        for did in tcx.all_trait_implementations(cnum).iter() {
-            build_impl(cx, *did, &mut impls);
-        }
-    }
-
-    // Also try to inline primitive impls from other crates.
-    let lang_items = tcx.lang_items();
-    let primitive_impls = [
-        lang_items.isize_impl(),
-        lang_items.i8_impl(),
-        lang_items.i16_impl(),
-        lang_items.i32_impl(),
-        lang_items.i64_impl(),
-        lang_items.i128_impl(),
-        lang_items.usize_impl(),
-        lang_items.u8_impl(),
-        lang_items.u16_impl(),
-        lang_items.u32_impl(),
-        lang_items.u64_impl(),
-        lang_items.u128_impl(),
-        lang_items.f32_impl(),
-        lang_items.f64_impl(),
-        lang_items.f32_runtime_impl(),
-        lang_items.f64_runtime_impl(),
-        lang_items.char_impl(),
-        lang_items.str_impl(),
-        lang_items.slice_impl(),
-        lang_items.slice_u8_impl(),
-        lang_items.str_alloc_impl(),
-        lang_items.slice_alloc_impl(),
-        lang_items.slice_u8_alloc_impl(),
-        lang_items.const_ptr_impl(),
-        lang_items.mut_ptr_impl(),
-    ];
-
-    for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
-        if !def_id.is_local() {
-            build_impl(cx, def_id, &mut impls);
-
-            let auto_impls = get_auto_traits_with_def_id(cx, def_id);
-            let blanket_impls = get_blanket_impls_with_def_id(cx, def_id);
-            let mut renderinfo = cx.renderinfo.borrow_mut();
-
-            let new_impls: Vec<clean::Item> = auto_impls.into_iter()
-                .chain(blanket_impls.into_iter())
-                .filter(|i| renderinfo.inlined.insert(i.def_id))
-                .collect();
-
-            impls.extend(new_impls);
-        }
-    }
-
     impls
 }
 
 pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
     if !cx.renderinfo.borrow_mut().inlined.insert(did) {
+        debug!("already inlined, bailing: {:?}", did);
         return
     }
 
@@ -371,9 +305,12 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
 
     // Only inline impl if the implemented trait is
     // reachable in rustdoc generated documentation
-    if let Some(traitref) = associated_trait {
-        if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
-            return
+    if !did.is_local() {
+        if let Some(traitref) = associated_trait {
+            if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
+                debug!("trait {:?} not reachable, bailing: {:?}", traitref.def_id, did);
+                return
+            }
         }
     }
 
@@ -381,9 +318,12 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
 
     // Only inline impl if the implementing type is
     // reachable in rustdoc generated documentation
-    if let Some(did) = for_.def_id() {
-        if !cx.access_levels.borrow().is_doc_reachable(did) {
-            return
+    if !did.is_local() {
+        if let Some(did) = for_.def_id() {
+            if !cx.access_levels.borrow().is_doc_reachable(did) {
+                debug!("impl type {:?} not accessible, bailing", did);
+                return
+            }
         }
     }
 
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index a312913a69c17..623ff4c46e9fa 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -37,7 +37,7 @@ use syntax_pos::DUMMY_SP;
 use errors;
 use errors::emitter::{Emitter, EmitterWriter};
 
-use std::cell::{RefCell, Cell};
+use std::cell::RefCell;
 use std::mem;
 use rustc_data_structures::sync::{self, Lrc};
 use std::rc::Rc;
@@ -60,7 +60,6 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
     /// The stack of module NodeIds up till this point
     pub crate_name: Option<String>,
     pub cstore: Rc<CStore>,
-    pub populated_all_crate_impls: Cell<bool>,
     // Note that external items for which `doc(hidden)` applies to are shown as
     // non-reachable while local items aren't. This is because we're reusing
     // the access levels from crateanalysis.
@@ -511,7 +510,6 @@ pub fn run_core(search_paths: SearchPaths,
                 resolver: &resolver,
                 crate_name,
                 cstore: cstore.clone(),
-                populated_all_crate_impls: Cell::new(false),
                 access_levels: RefCell::new(access_levels),
                 external_traits: Default::default(),
                 active_extern_traits: Default::default(),
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
new file mode 100644
index 0000000000000..0be5ab07dea76
--- /dev/null
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -0,0 +1,99 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use clean::*;
+
+use super::Pass;
+use core::DocContext;
+
+pub const COLLECT_TRAIT_IMPLS: Pass =
+    Pass::early("collect-trait-impls", collect_trait_impls,
+                "retrieves trait impls for items in the crate");
+
+pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate {
+    if let Some(ref mut it) = krate.module {
+        if let ModuleItem(Module { ref mut items, .. }) = it.inner {
+            for &cnum in cx.tcx.crates().iter() {
+                for &did in cx.tcx.all_trait_implementations(cnum).iter() {
+                    inline::build_impl(cx, did, items);
+                }
+            }
+
+            // `tcx.crates()` doesn't include the local crate, and `tcx.all_trait_implementations`
+            // doesn't work with it anyway, so pull them from the HIR map instead
+            for &trait_did in cx.all_traits.iter() {
+                for &impl_node in cx.tcx.hir.trait_impls(trait_did) {
+                    let impl_did = cx.tcx.hir.local_def_id(impl_node);
+                    inline::build_impl(cx, impl_did, items);
+                }
+            }
+
+            // Also try to inline primitive impls from other crates.
+            let lang_items = cx.tcx.lang_items();
+            let primitive_impls = [
+                lang_items.isize_impl(),
+                lang_items.i8_impl(),
+                lang_items.i16_impl(),
+                lang_items.i32_impl(),
+                lang_items.i64_impl(),
+                lang_items.i128_impl(),
+                lang_items.usize_impl(),
+                lang_items.u8_impl(),
+                lang_items.u16_impl(),
+                lang_items.u32_impl(),
+                lang_items.u64_impl(),
+                lang_items.u128_impl(),
+                lang_items.f32_impl(),
+                lang_items.f64_impl(),
+                lang_items.f32_runtime_impl(),
+                lang_items.f64_runtime_impl(),
+                lang_items.char_impl(),
+                lang_items.str_impl(),
+                lang_items.slice_impl(),
+                lang_items.slice_u8_impl(),
+                lang_items.str_alloc_impl(),
+                lang_items.slice_alloc_impl(),
+                lang_items.slice_u8_alloc_impl(),
+                lang_items.const_ptr_impl(),
+                lang_items.mut_ptr_impl(),
+            ];
+
+            for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
+                if !def_id.is_local() {
+                    inline::build_impl(cx, def_id, items);
+
+                    let auto_impls = get_auto_traits_with_def_id(cx, def_id);
+                    let blanket_impls = get_blanket_impls_with_def_id(cx, def_id);
+                    let mut renderinfo = cx.renderinfo.borrow_mut();
+
+                    let new_impls: Vec<Item> = auto_impls.into_iter()
+                        .chain(blanket_impls.into_iter())
+                        .filter(|i| renderinfo.inlined.insert(i.def_id))
+                        .collect();
+
+                    items.extend(new_impls);
+                }
+            }
+        } else {
+            panic!("collect-trait-impls can't run");
+        }
+    } else {
+        panic!("collect-trait-impls can't run");
+    }
+
+    // pulling in the impls puts their trait info into the DocContext, but that's already been
+    // drained by now, so stuff that info into the Crate so the rendering can pick it up
+    let mut external_traits = cx.external_traits.borrow_mut();
+    for (did, trait_) in external_traits.drain() {
+        krate.external_traits.entry(did).or_insert(trait_);
+    }
+
+    krate
+}
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 16251877bb106..09281aa7cfaf4 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -43,6 +43,9 @@ pub use self::propagate_doc_cfg::PROPAGATE_DOC_CFG;
 mod collect_intra_doc_links;
 pub use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
 
+mod collect_trait_impls;
+pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
+
 /// Represents a single pass.
 #[derive(Copy, Clone)]
 pub enum Pass {
@@ -132,10 +135,12 @@ pub const PASSES: &'static [Pass] = &[
     STRIP_PRIV_IMPORTS,
     PROPAGATE_DOC_CFG,
     COLLECT_INTRA_DOC_LINKS,
+    COLLECT_TRAIT_IMPLS,
 ];
 
 /// The list of passes run by default.
 pub const DEFAULT_PASSES: &'static [&'static str] = &[
+    "collect-trait-impls",
     "strip-hidden",
     "strip-private",
     "collect-intra-doc-links",
@@ -146,6 +151,7 @@ pub const DEFAULT_PASSES: &'static [&'static str] = &[
 
 /// The list of default passes run with `--document-private-items` is passed to rustdoc.
 pub const DEFAULT_PRIVATE_PASSES: &'static [&'static str] = &[
+    "collect-trait-impls",
     "strip-priv-imports",
     "collect-intra-doc-links",
     "collapse-docs",
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 451e24d6c0dc9..ce438cd99a4b6 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -510,9 +510,9 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
                           ref tr,
                           ref ty,
                           ref item_ids) => {
-                // Don't duplicate impls when inlining, we'll pick them up
-                // regardless of where they're located.
-                if !self.inlining {
+                // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick
+                // them up regardless of where they're located.
+                if !self.inlining && tr.is_none() {
                     let items = item_ids.iter()
                                         .map(|ii| self.cx.tcx.hir.impl_item(ii.id).clone())
                                         .collect();
diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs
index 3acf4af5fd247..26ed544412275 100644
--- a/src/test/rustdoc/traits-in-bodies.rs
+++ b/src/test/rustdoc/traits-in-bodies.rs
@@ -11,11 +11,10 @@
 //prior to fixing `everybody_loops` to preserve items, rustdoc would crash on this file, as it
 //didn't see that `SomeStruct` implemented `Clone`
 
-//FIXME(misdreavus): whenever rustdoc shows traits impl'd inside bodies, make sure this test
-//reflects that
-
 pub struct Bounded<T: Clone>(T);
 
+// @has traits_in_bodies/struct.SomeStruct.html
+// @has - '//code' 'impl Clone for SomeStruct'
 pub struct SomeStruct;
 
 fn asdf() -> Bounded<SomeStruct> {
@@ -27,3 +26,16 @@ fn asdf() -> Bounded<SomeStruct> {
 
     Bounded(SomeStruct)
 }
+
+// @has traits_in_bodies/struct.Point.html
+// @has - '//code' 'impl Copy for Point'
+#[derive(Clone)]
+pub struct Point {
+    x: i32,
+    y: i32,
+}
+
+const _FOO: () = {
+    impl Copy for Point {}
+    ()
+};

From f1566f7b0ff6943c329d06e9582d6344d8e21da5 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 7 Aug 2018 11:30:57 -0500
Subject: [PATCH 09/30] print local inlined consts via the HIR map

---
 src/librustdoc/clean/inline.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index f9c631fcfcdb6..2c3714ee0c2ab 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -404,7 +404,11 @@ fn build_module(cx: &DocContext, did: DefId, visited: &mut FxHashSet<DefId>) ->
 }
 
 pub fn print_inlined_const(cx: &DocContext, did: DefId) -> String {
-    cx.tcx.rendered_const(did)
+    if let Some(node_id) = cx.tcx.hir.as_local_node_id(did) {
+        cx.tcx.hir.node_to_pretty_string(node_id)
+    } else {
+        cx.tcx.rendered_const(did)
+    }
 }
 
 fn build_const(cx: &DocContext, did: DefId) -> clean::Constant {

From c66547855806be71eba875af27aac1218b0ad90d Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 7 Aug 2018 15:17:27 -0500
Subject: [PATCH 10/30] ignore rustdoc/doc-proc-macro on stage1

---
 src/test/rustdoc/doc-proc-macro.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/test/rustdoc/doc-proc-macro.rs b/src/test/rustdoc/doc-proc-macro.rs
index b3b403a7b86aa..01a4a410b03fb 100644
--- a/src/test/rustdoc/doc-proc-macro.rs
+++ b/src/test/rustdoc/doc-proc-macro.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-stage1
+
 // Issue #52129: ICE when trying to document the `quote` proc-macro from proc_macro
 
 // As of this writing, we don't currently attempt to document proc-macros. However, we shouldn't

From ce5e4e57c754ddd9d11af0b8a245ef0b34cbaf1a Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Fri, 10 Aug 2018 17:24:40 -0500
Subject: [PATCH 11/30] only move access_levels/external_traits after early
 passes

---
 src/librustdoc/clean/mod.rs                  | 7 ++-----
 src/librustdoc/core.rs                       | 4 ++++
 src/librustdoc/passes/collect_trait_impls.rs | 7 -------
 src/librustdoc/passes/strip_private.rs       | 4 ++--
 4 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index da18e3e6b91b3..68d812762a96c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -209,9 +209,6 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tc
             }));
         }
 
-        let mut access_levels = cx.access_levels.borrow_mut();
-        let mut external_traits = cx.external_traits.borrow_mut();
-
         Crate {
             name,
             version: None,
@@ -219,8 +216,8 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tc
             module: Some(module),
             externs,
             primitives,
-            access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())),
-            external_traits: mem::replace(&mut external_traits, Default::default()),
+            access_levels: Arc::new(Default::default()),
+            external_traits: Default::default(),
             masked_crates,
         }
     }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 623ff4c46e9fa..3a942aa6c8db1 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -41,6 +41,7 @@ use std::cell::RefCell;
 use std::mem;
 use rustc_data_structures::sync::{self, Lrc};
 use std::rc::Rc;
+use std::sync::Arc;
 use std::path::PathBuf;
 
 use visit_ast::RustdocVisitor;
@@ -596,6 +597,9 @@ pub fn run_core(search_paths: SearchPaths,
 
             ctxt.sess().abort_if_errors();
 
+            krate.access_levels = Arc::new(ctxt.access_levels.into_inner());
+            krate.external_traits = ctxt.external_traits.into_inner();
+
             (krate, ctxt.renderinfo.into_inner(), passes)
         }), &sess)
     })
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 0be5ab07dea76..0ee1657f21516 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -88,12 +88,5 @@ pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate {
         panic!("collect-trait-impls can't run");
     }
 
-    // pulling in the impls puts their trait info into the DocContext, but that's already been
-    // drained by now, so stuff that info into the Crate so the rendering can pick it up
-    let mut external_traits = cx.external_traits.borrow_mut();
-    for (did, trait_) in external_traits.drain() {
-        krate.external_traits.entry(did).or_insert(trait_);
-    }
-
     krate
 }
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index 3b17a768ffdee..4fa5943faca07 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -22,10 +22,10 @@ pub const STRIP_PRIVATE: Pass =
 
 /// Strip private items from the point of view of a crate or externally from a
 /// crate, specified by the `xcrate` flag.
-pub fn strip_private(mut krate: clean::Crate, _: &DocContext) -> clean::Crate {
+pub fn strip_private(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
     // This stripper collects all *retained* nodes.
     let mut retained = DefIdSet();
-    let access_levels = krate.access_levels.clone();
+    let access_levels = cx.access_levels.borrow().clone();
 
     // strip all private items
     {

From 033fd7a5e9bbdee292502a55083cfd7ac8b07c38 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 14 Aug 2018 12:08:12 -0500
Subject: [PATCH 12/30] don't record an external trait if it's not external

---
 src/librustdoc/clean/inline.rs | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 2c3714ee0c2ab..20c5a9febed9e 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -519,6 +519,10 @@ fn separate_supertrait_bounds(mut g: clean::Generics)
 }
 
 pub fn record_extern_trait(cx: &DocContext, did: DefId) {
+    if did.is_local() {
+        return;
+    }
+
     if cx.external_traits.borrow().contains_key(&did) ||
         cx.active_extern_traits.borrow().contains(&did)
     {

From dc3899ecf33f19db9a60e585c54daecac6a078ca Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 14 Aug 2018 14:41:07 -0500
Subject: [PATCH 13/30] undo some tweaks to build_impl

---
 src/librustdoc/clean/inline.rs | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 20c5a9febed9e..1f5174f84359a 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -295,7 +295,6 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
 
 pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
     if !cx.renderinfo.borrow_mut().inlined.insert(did) {
-        debug!("already inlined, bailing: {:?}", did);
         return
     }
 
@@ -305,12 +304,9 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
 
     // Only inline impl if the implemented trait is
     // reachable in rustdoc generated documentation
-    if !did.is_local() {
-        if let Some(traitref) = associated_trait {
-            if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
-                debug!("trait {:?} not reachable, bailing: {:?}", traitref.def_id, did);
-                return
-            }
+    if let Some(traitref) = associated_trait {
+        if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
+            return
         }
     }
 
@@ -318,12 +314,9 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
 
     // Only inline impl if the implementing type is
     // reachable in rustdoc generated documentation
-    if !did.is_local() {
-        if let Some(did) = for_.def_id() {
-            if !cx.access_levels.borrow().is_doc_reachable(did) {
-                debug!("impl type {:?} not accessible, bailing", did);
-                return
-            }
+    if let Some(did) = for_.def_id() {
+        if !cx.access_levels.borrow().is_doc_reachable(did) {
+            return
         }
     }
 
@@ -356,6 +349,8 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
            .collect()
     }).unwrap_or(FxHashSet());
 
+    debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
+
     ret.push(clean::Item {
         inner: clean::ImplItem(clean::Impl {
             unsafety: hir::Unsafety::Normal,

From 825126a599d5a42aa1fe6d73a66883a202492593 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 14 Aug 2018 14:43:03 -0500
Subject: [PATCH 14/30] add a bunch of debug prints

---
 src/librustdoc/clean/inline.rs | 1 +
 src/librustdoc/html/render.rs  | 4 ++++
 src/librustdoc/passes/mod.rs   | 7 +++++++
 3 files changed, 12 insertions(+)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 1f5174f84359a..4d47ec8c84aed 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -526,6 +526,7 @@ pub fn record_extern_trait(cx: &DocContext, did: DefId) {
 
     cx.active_extern_traits.borrow_mut().push(did);
 
+    debug!("record_extern_trait: {:?}", did);
     let trait_ = build_external_trait(cx, did);
 
     cx.external_traits.borrow_mut().insert(did, trait_);
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 368c056f021c1..9d6ea70ed6563 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1223,6 +1223,10 @@ impl<'a> SourceCollector<'a> {
 
 impl DocFolder for Cache {
     fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+        if item.def_id.is_local() {
+            debug!("folding item \"{:?}\", a {}", item.name, item.type_());
+        }
+
         // If this is a stripped module,
         // we don't want it or its children in the search index.
         let orig_stripped_mod = match item.inner {
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 09281aa7cfaf4..95c613cc14d11 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -195,6 +195,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
                 // We need to recurse into stripped modules to strip things
                 // like impl methods but when doing so we must not add any
                 // items to the `retained` set.
+                debug!("Stripper: recursing into stripped {} {:?}", i.type_(), i.name);
                 let old = mem::replace(&mut self.update_retained, false);
                 let ret = self.fold_item_recur(i);
                 self.update_retained = old;
@@ -218,6 +219,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             | clean::ForeignTypeItem => {
                 if i.def_id.is_local() {
                     if !self.access_levels.is_exported(i.def_id) {
+                        debug!("Stripper: stripping {} {:?}", i.type_(), i.name);
                         return None;
                     }
                 }
@@ -231,6 +233,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
 
             clean::ModuleItem(..) => {
                 if i.def_id.is_local() && i.visibility != Some(clean::Public) {
+                    debug!("Stripper: stripping module {:?}", i.name);
                     let old = mem::replace(&mut self.update_retained, false);
                     let ret = StripItem(self.fold_item_recur(i).unwrap()).strip();
                     self.update_retained = old;
@@ -302,11 +305,13 @@ impl<'a> fold::DocFolder for ImplStripper<'a> {
             }
             if let Some(did) = imp.for_.def_id() {
                 if did.is_local() && !imp.for_.is_generic() && !self.retained.contains(&did) {
+                    debug!("ImplStripper: impl item for stripped type; removing");
                     return None;
                 }
             }
             if let Some(did) = imp.trait_.def_id() {
                 if did.is_local() && !self.retained.contains(&did) {
+                    debug!("ImplStripper: impl item for stripped trait; removing");
                     return None;
                 }
             }
@@ -314,6 +319,8 @@ impl<'a> fold::DocFolder for ImplStripper<'a> {
                 for typaram in generics {
                     if let Some(did) = typaram.def_id() {
                         if did.is_local() && !self.retained.contains(&did) {
+                            debug!("ImplStripper: stripped item in trait's generics; \
+                                   removing impl");
                             return None;
                         }
                     }

From 5254548e597ecc8d34e379dbe59206fa61d66e47 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 14 Aug 2018 14:44:45 -0500
Subject: [PATCH 15/30] handle local names when registering FQNs

---
 src/librustdoc/clean/inline.rs | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 4d47ec8c84aed..17f1a8120abf1 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -158,12 +158,11 @@ pub fn load_attrs(cx: &DocContext, did: DefId) -> clean::Attributes {
 /// These names are used later on by HTML rendering to generate things like
 /// source links back to the original item.
 pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
+    let mut crate_name = cx.tcx.crate_name(did.krate).to_string();
     if did.is_local() {
-        debug!("record_extern_fqn(did={:?}, kind+{:?}): def_id is local, aborting", did, kind);
-        return;
+        crate_name = cx.crate_name.clone().unwrap_or(crate_name);
     }
 
-    let crate_name = cx.tcx.crate_name(did.krate).to_string();
     let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
         // extern blocks have an empty name
         let s = elem.data.to_string();
@@ -178,7 +177,12 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
     } else {
         once(crate_name).chain(relative).collect()
     };
-    cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
+
+    if did.is_local() {
+        cx.renderinfo.borrow_mut().exact_paths.insert(did, fqn);
+    } else {
+        cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
+    }
 }
 
 pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {

From ca612863cd2cf6d11b6daf39188c97375767dfba Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 14 Aug 2018 15:19:15 -0500
Subject: [PATCH 16/30] pull local types from the HIR instead of tcx

---
 src/librustdoc/clean/inline.rs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 17f1a8120abf1..b773a59b16b1e 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -314,7 +314,16 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
         }
     }
 
-    let for_ = tcx.type_of(did).clean(cx);
+    let for_ = if let Some(nodeid) = tcx.hir.as_local_node_id(did) {
+        match tcx.hir.expect_item(nodeid).node {
+            hir::ItemKind::Impl(.., ref t, _) => {
+                t.clean(cx)
+            }
+            _ => panic!("did given to build_impl was not an impl"),
+        }
+    } else {
+        tcx.type_of(did).clean(cx)
+    };
 
     // Only inline impl if the implementing type is
     // reachable in rustdoc generated documentation

From eaacf59681c85ddf6c60a14df9752db77ce907c0 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 14 Aug 2018 16:42:34 -0500
Subject: [PATCH 17/30] collect impl items from the HIR if available

---
 src/librustdoc/clean/inline.rs | 23 +++++++++++++++++------
 1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index b773a59b16b1e..89516a1a7dc0f 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -334,13 +334,24 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
     }
 
     let predicates = tcx.predicates_of(did);
-    let trait_items = tcx.associated_items(did).filter_map(|item| {
-        if associated_trait.is_some() || item.vis == ty::Visibility::Public {
-            Some(item.clean(cx))
-        } else {
-            None
+    let trait_items = if let Some(nodeid) = tcx.hir.as_local_node_id(did) {
+        match tcx.hir.expect_item(nodeid).node {
+            hir::ItemKind::Impl(.., ref item_ids) => {
+                item_ids.iter()
+                        .map(|ii| tcx.hir.impl_item(ii.id).clean(cx))
+                        .collect::<Vec<_>>()
+            }
+            _ => panic!("did given to build_impl was not an impl"),
         }
-    }).collect::<Vec<_>>();
+    } else {
+        tcx.associated_items(did).filter_map(|item| {
+            if associated_trait.is_some() || item.vis == ty::Visibility::Public {
+                Some(item.clean(cx))
+            } else {
+                None
+            }
+        }).collect::<Vec<_>>()
+    };
     let polarity = tcx.impl_polarity(did);
     let trait_ = associated_trait.clean(cx).map(|bound| {
         match bound {

From 17d48343f5fb91f630c71a3bdf451e70cd0289ce Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 14 Aug 2018 17:38:41 -0500
Subject: [PATCH 18/30] pull impl generics from HIR if available

---
 src/librustdoc/clean/inline.rs | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 89516a1a7dc0f..7e8d32f991ce7 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -334,23 +334,29 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
     }
 
     let predicates = tcx.predicates_of(did);
-    let trait_items = if let Some(nodeid) = tcx.hir.as_local_node_id(did) {
+    let (trait_items, generics) = if let Some(nodeid) = tcx.hir.as_local_node_id(did) {
         match tcx.hir.expect_item(nodeid).node {
-            hir::ItemKind::Impl(.., ref item_ids) => {
-                item_ids.iter()
-                        .map(|ii| tcx.hir.impl_item(ii.id).clean(cx))
-                        .collect::<Vec<_>>()
+            hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => {
+                (
+                    item_ids.iter()
+                            .map(|ii| tcx.hir.impl_item(ii.id).clean(cx))
+                            .collect::<Vec<_>>(),
+                    gen.clean(cx),
+                )
             }
             _ => panic!("did given to build_impl was not an impl"),
         }
     } else {
-        tcx.associated_items(did).filter_map(|item| {
-            if associated_trait.is_some() || item.vis == ty::Visibility::Public {
-                Some(item.clean(cx))
-            } else {
-                None
-            }
-        }).collect::<Vec<_>>()
+        (
+            tcx.associated_items(did).filter_map(|item| {
+                if associated_trait.is_some() || item.vis == ty::Visibility::Public {
+                    Some(item.clean(cx))
+                } else {
+                    None
+                }
+            }).collect::<Vec<_>>(),
+            (tcx.generics_of(did), &predicates).clean(cx),
+        )
     };
     let polarity = tcx.impl_polarity(did);
     let trait_ = associated_trait.clean(cx).map(|bound| {
@@ -378,7 +384,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
     ret.push(clean::Item {
         inner: clean::ImplItem(clean::Impl {
             unsafety: hir::Unsafety::Normal,
-            generics: (tcx.generics_of(did), &predicates).clean(cx),
+            generics,
             provided_trait_methods: provided,
             trait_,
             for_,

From 15dba89730c1826c2a6e602ffd24e45939584085 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Wed, 15 Aug 2018 10:41:15 -0500
Subject: [PATCH 19/30] swap external_traits into the crate before running
 strip_hidden

---
 src/librustdoc/passes/strip_hidden.rs | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index cc0b6fb6d6705..eab4022a3389f 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -24,9 +24,13 @@ pub const STRIP_HIDDEN: Pass =
                 "strips all doc(hidden) items from the output");
 
 /// Strip items marked `#[doc(hidden)]`
-pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate {
+pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
     let mut retained = DefIdSet();
 
+    // as an early pass, the external traits haven't been swapped in, so we need to do that ahead
+    // of time
+    mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut());
+
     // strip all #[doc(hidden)] items
     let krate = {
         let mut stripper = Stripper{ retained: &mut retained, update_retained: true };
@@ -35,7 +39,10 @@ pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate {
 
     // strip all impls referencing stripped items
     let mut stripper = ImplStripper { retained: &retained };
-    stripper.fold_crate(krate)
+    let mut krate = stripper.fold_crate(krate);
+    mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut());
+
+    krate
 }
 
 struct Stripper<'a> {
@@ -46,7 +53,7 @@ struct Stripper<'a> {
 impl<'a> fold::DocFolder for Stripper<'a> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         if i.attrs.lists("doc").has_word("hidden") {
-            debug!("found one in strip_hidden; removing");
+            debug!("strip_hidden: stripping {} {:?}", i.type_(), i.name);
             // use a dedicated hidden item for given item type if any
             match i.inner {
                 clean::StructFieldItem(..) | clean::ModuleItem(..) => {

From c39de06fe10461a369eabeff51784a7d3b82ccb2 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 21 Aug 2018 16:22:20 -0500
Subject: [PATCH 20/30] don't check visibility when inlining local impls

those get handled properly in strip-hidden anyway
---
 src/librustdoc/clean/inline.rs             | 16 ++++++++-----
 src/test/rustdoc/inline_local/trait-vis.rs | 28 ++++++++++++++++++++++
 2 files changed, 38 insertions(+), 6 deletions(-)
 create mode 100644 src/test/rustdoc/inline_local/trait-vis.rs

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 7e8d32f991ce7..d248bb58fc599 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -308,9 +308,11 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
 
     // Only inline impl if the implemented trait is
     // reachable in rustdoc generated documentation
-    if let Some(traitref) = associated_trait {
-        if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
-            return
+    if !did.is_local() {
+        if let Some(traitref) = associated_trait {
+            if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
+                return
+            }
         }
     }
 
@@ -327,9 +329,11 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
 
     // Only inline impl if the implementing type is
     // reachable in rustdoc generated documentation
-    if let Some(did) = for_.def_id() {
-        if !cx.access_levels.borrow().is_doc_reachable(did) {
-            return
+    if !did.is_local() {
+        if let Some(did) = for_.def_id() {
+            if !cx.access_levels.borrow().is_doc_reachable(did) {
+                return
+            }
         }
     }
 
diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs
new file mode 100644
index 0000000000000..1035e357ef649
--- /dev/null
+++ b/src/test/rustdoc/inline_local/trait-vis.rs
@@ -0,0 +1,28 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait ThisTrait {}
+
+mod asdf {
+    use ThisTrait;
+
+    pub struct SomeStruct;
+
+    impl ThisTrait for SomeStruct {}
+
+    trait PrivateTrait {}
+
+    impl PrivateTrait for SomeStruct {}
+}
+
+// @has trait_vis/struct.SomeStruct.html
+// @has - '//code' 'impl ThisTrait for SomeStruct'
+// !@has - '//code' 'impl PrivateTrait for SomeStruct'
+pub use asdf::SomeStruct;

From 810332f3673f362f97e3a911f3fec9e49eb8383a Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Mon, 27 Aug 2018 12:42:43 -0500
Subject: [PATCH 21/30] add more tests for traits-in-non-module-scope

---
 src/librustdoc/passes/mod.rs                  |  2 +-
 .../inline_cross/auxiliary/trait-vis.rs       | 23 +++++++++++++++++++
 src/test/rustdoc/inline_cross/trait-vis.rs    | 17 ++++++++++++++
 src/test/rustdoc/inline_local/trait-vis.rs    |  2 +-
 src/test/rustdoc/primitive-generic-impl.rs    |  3 ---
 src/test/rustdoc/traits-in-bodies.rs          | 21 +++++++++++++++++
 6 files changed, 63 insertions(+), 5 deletions(-)
 create mode 100644 src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs
 create mode 100644 src/test/rustdoc/inline_cross/trait-vis.rs

diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index 95c613cc14d11..24fec62dd573a 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -320,7 +320,7 @@ impl<'a> fold::DocFolder for ImplStripper<'a> {
                     if let Some(did) = typaram.def_id() {
                         if did.is_local() && !self.retained.contains(&did) {
                             debug!("ImplStripper: stripped item in trait's generics; \
-                                   removing impl");
+                                    removing impl");
                             return None;
                         }
                     }
diff --git a/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs b/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs
new file mode 100644
index 0000000000000..7457a5d4899fe
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/auxiliary/trait-vis.rs
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "inner"]
+
+pub struct SomeStruct;
+
+fn asdf() {
+    const _FOO: () = {
+        impl Clone for SomeStruct {
+            fn clone(&self) -> Self {
+                SomeStruct
+            }
+        }
+    };
+}
diff --git a/src/test/rustdoc/inline_cross/trait-vis.rs b/src/test/rustdoc/inline_cross/trait-vis.rs
new file mode 100644
index 0000000000000..5b5410b1da44d
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/trait-vis.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:trait-vis.rs
+
+extern crate inner;
+
+// @has trait_vis/struct.SomeStruct.html
+// @has - '//code' 'impl Clone for SomeStruct'
+pub use inner::SomeStruct;
diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs
index 1035e357ef649..73b1cc2ce8f2d 100644
--- a/src/test/rustdoc/inline_local/trait-vis.rs
+++ b/src/test/rustdoc/inline_local/trait-vis.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
diff --git a/src/test/rustdoc/primitive-generic-impl.rs b/src/test/rustdoc/primitive-generic-impl.rs
index b4351b8268c8b..a771b1b15ce4d 100644
--- a/src/test/rustdoc/primitive-generic-impl.rs
+++ b/src/test/rustdoc/primitive-generic-impl.rs
@@ -10,9 +10,6 @@
 
 #![crate_name = "foo"]
 
-// we need to reexport something from libstd so that `all_trait_implementations` is called.
-pub use std::string::String;
-
 include!("primitive/primitive-generic-impl.rs");
 
 // @has foo/primitive.i32.html '//h3[@id="impl-ToString"]//code' 'impl<T> ToString for T'
diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs
index 26ed544412275..a1d4019bba2bf 100644
--- a/src/test/rustdoc/traits-in-bodies.rs
+++ b/src/test/rustdoc/traits-in-bodies.rs
@@ -39,3 +39,24 @@ const _FOO: () = {
     impl Copy for Point {}
     ()
 };
+
+// @has traits_in_bodies/struct.Inception.html
+// @has - '//code' 'impl Clone for Inception'
+pub struct Inception;
+
+static _BAR: usize = {
+    trait HiddenTrait {
+        fn hidden_fn(&self) {
+            for _ in 0..5 {
+                impl Clone for Inception {
+                    fn clone(&self) -> Self {
+                        // we need to go deeper
+                        Inception
+                    }
+                }
+            }
+        }
+    }
+
+    5
+};

From 5fd1d8357ee94bc6b49ec975e1ab4f37ac4b487a Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Tue, 28 Aug 2018 11:33:45 -0500
Subject: [PATCH 22/30] don't index trait impls if the trait isn't also
 documented

---
 src/librustdoc/html/render.rs                | 34 +++++++++++++++++---
 src/librustdoc/lib.rs                        |  1 +
 src/test/rustdoc/traits-in-bodies-private.rs | 23 +++++++++++++
 3 files changed, 53 insertions(+), 5 deletions(-)
 create mode 100644 src/test/rustdoc/traits-in-bodies-private.rs

diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 9d6ea70ed6563..d052760724e67 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -337,6 +337,15 @@ pub struct Cache {
     // and their parent id here and indexes them at the end of crate parsing.
     orphan_impl_items: Vec<(DefId, clean::Item)>,
 
+    // Similarly to `orphan_impl_items`, sometimes trait impls are picked up
+    // even though the trait itself is not exported. This can happen if a trait
+    // was defined in function/expression scope, since the impl will be picked
+    // up by `collect-trait-impls` but the trait won't be scraped out in the HIR
+    // crawl. In order to prevent crashes when looking for spotlight traits or
+    // when gathering trait documentation on a type, hold impls here while
+    // folding and add them to the cache later on if we find the trait.
+    orphan_trait_impls: Vec<(DefId, FxHashSet<DefId>, Impl)>,
+
     /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias,
     /// we need the alias element to have an array of items.
     aliases: FxHashMap<String, Vec<IndexItem>>,
@@ -594,6 +603,7 @@ pub fn run(mut krate: clean::Crate,
         access_levels: krate.access_levels.clone(),
         crate_version: krate.version.take(),
         orphan_impl_items: Vec::new(),
+        orphan_trait_impls: Vec::new(),
         traits: mem::replace(&mut krate.external_traits, FxHashMap()),
         deref_trait_did,
         deref_mut_trait_did,
@@ -636,6 +646,14 @@ pub fn run(mut krate: clean::Crate,
     cache.stack.push(krate.name.clone());
     krate = cache.fold_crate(krate);
 
+    for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) {
+        if cache.traits.contains_key(&trait_did) {
+            for did in dids {
+                cache.impls.entry(did).or_insert(vec![]).push(impl_.clone());
+            }
+        }
+    }
+
     // Build our search index
     let index = build_index(&krate, &mut cache);
 
@@ -1224,7 +1242,7 @@ impl<'a> SourceCollector<'a> {
 impl DocFolder for Cache {
     fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
         if item.def_id.is_local() {
-            debug!("folding item \"{:?}\", a {}", item.name, item.type_());
+            debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id);
         }
 
         // If this is a stripped module,
@@ -1455,10 +1473,16 @@ impl DocFolder for Cache {
                 } else {
                     unreachable!()
                 };
-                for did in dids {
-                    self.impls.entry(did).or_default().push(Impl {
-                        impl_item: item.clone(),
-                    });
+                let impl_item = Impl {
+                    impl_item: item,
+                };
+                if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) {
+                    for did in dids {
+                        self.impls.entry(did).or_insert(vec![]).push(impl_item.clone());
+                    }
+                } else {
+                    let trait_did = impl_item.trait_did().unwrap();
+                    self.orphan_trait_impls.push((trait_did, dids, impl_item));
                 }
                 None
             } else {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 1acae86f0068f..11cf43dad4a92 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -25,6 +25,7 @@
 #![feature(ptr_offset_from)]
 #![feature(crate_visibility_modifier)]
 #![feature(const_fn)]
+#![feature(drain_filter)]
 
 #![recursion_limit="256"]
 
diff --git a/src/test/rustdoc/traits-in-bodies-private.rs b/src/test/rustdoc/traits-in-bodies-private.rs
new file mode 100644
index 0000000000000..ac3be7e61e9a0
--- /dev/null
+++ b/src/test/rustdoc/traits-in-bodies-private.rs
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// when implementing the fix for traits-in-bodies, there was an ICE when documenting private items
+// and a trait was defined in non-module scope
+
+// compile-flags:--document-private-items
+
+// @has traits_in_bodies_private/struct.SomeStruct.html
+// @!has - '//code' 'impl HiddenTrait for SomeStruct'
+pub struct SomeStruct;
+
+fn __implementation_details() {
+    trait HiddenTrait {}
+    impl HiddenTrait for SomeStruct {}
+}

From ce70d912c175520232e26d56b0e3d1ed93f408d2 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Thu, 30 Aug 2018 12:10:15 -0500
Subject: [PATCH 23/30] collect auto-/blanket-impls during collect-trait-impls

---
 src/librustdoc/clean/inline.rs               | 28 +++------
 src/librustdoc/clean/mod.rs                  | 60 +++++++-------------
 src/librustdoc/passes/collect_trait_impls.rs | 40 ++++++++++++-
 3 files changed, 65 insertions(+), 63 deletions(-)

diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index d248bb58fc599..a91336dced398 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -29,8 +29,6 @@ use clean::{
     self,
     GetDefId,
     ToSource,
-    get_auto_traits_with_def_id,
-    get_blanket_impls_with_def_id,
 };
 
 use super::Clean;
@@ -56,7 +54,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
     let inner = match def {
         Def::Trait(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Trait);
-            ret.extend(build_impls(cx, did, false));
+            ret.extend(build_impls(cx, did));
             clean::TraitItem(build_external_trait(cx, did))
         }
         Def::Fn(did) => {
@@ -65,27 +63,27 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHa
         }
         Def::Struct(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Struct);
-            ret.extend(build_impls(cx, did, true));
+            ret.extend(build_impls(cx, did));
             clean::StructItem(build_struct(cx, did))
         }
         Def::Union(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Union);
-            ret.extend(build_impls(cx, did, true));
+            ret.extend(build_impls(cx, did));
             clean::UnionItem(build_union(cx, did))
         }
         Def::TyAlias(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Typedef);
-            ret.extend(build_impls(cx, did, false));
+            ret.extend(build_impls(cx, did));
             clean::TypedefItem(build_type_alias(cx, did), false)
         }
         Def::Enum(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Enum);
-            ret.extend(build_impls(cx, did, true));
+            ret.extend(build_impls(cx, did));
             clean::EnumItem(build_enum(cx, did))
         }
         Def::ForeignTy(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Foreign);
-            ret.extend(build_impls(cx, did, false));
+            ret.extend(build_impls(cx, did));
             clean::ForeignTypeItem
         }
         // Never inline enum variants but leave them shown as re-exports.
@@ -274,7 +272,7 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef {
     }
 }
 
-pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean::Item> {
+pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
     let tcx = cx.tcx;
     let mut impls = Vec::new();
 
@@ -282,18 +280,6 @@ pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean:
         build_impl(cx, did, &mut impls);
     }
 
-    if auto_traits {
-        let auto_impls = get_auto_traits_with_def_id(cx, did);
-        {
-            let mut renderinfo = cx.renderinfo.borrow_mut();
-            let new_impls: Vec<clean::Item> = auto_impls.into_iter()
-                .filter(|i| renderinfo.inlined.insert(i.def_id)).collect();
-
-            impls.extend(new_impls);
-        }
-        impls.extend(get_blanket_impls_with_def_id(cx, did));
-    }
-
     impls
 }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 68d812762a96c..20e1f3f3beae1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -576,9 +576,9 @@ impl Clean<Item> for doctree::Module {
         let mut items: Vec<Item> = vec![];
         items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
         items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
-        items.extend(self.structs.iter().flat_map(|x| x.clean(cx)));
-        items.extend(self.unions.iter().flat_map(|x| x.clean(cx)));
-        items.extend(self.enums.iter().flat_map(|x| x.clean(cx)));
+        items.extend(self.structs.iter().map(|x| x.clean(cx)));
+        items.extend(self.unions.iter().map(|x| x.clean(cx)));
+        items.extend(self.enums.iter().map(|x| x.clean(cx)));
         items.extend(self.fns.iter().map(|x| x.clean(cx)));
         items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
@@ -2813,14 +2813,10 @@ pub struct Union {
     pub fields_stripped: bool,
 }
 
-impl Clean<Vec<Item>> for doctree::Struct {
-    fn clean(&self, cx: &DocContext) -> Vec<Item> {
-        let name = self.name.clean(cx);
-        let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
-        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
-
-        ret.push(Item {
-            name: Some(name),
+impl Clean<Item> for doctree::Struct {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
             def_id: cx.tcx.hir.local_def_id(self.id),
@@ -2833,20 +2829,14 @@ impl Clean<Vec<Item>> for doctree::Struct {
                 fields: self.fields.clean(cx),
                 fields_stripped: false,
             }),
-        });
-
-        ret
+        }
     }
 }
 
-impl Clean<Vec<Item>> for doctree::Union {
-    fn clean(&self, cx: &DocContext) -> Vec<Item> {
-        let name = self.name.clean(cx);
-        let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
-        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
-
-        ret.push(Item {
-            name: Some(name),
+impl Clean<Item> for doctree::Union {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
             def_id: cx.tcx.hir.local_def_id(self.id),
@@ -2859,9 +2849,7 @@ impl Clean<Vec<Item>> for doctree::Union {
                 fields: self.fields.clean(cx),
                 fields_stripped: false,
             }),
-        });
-
-        ret
+        }
     }
 }
 
@@ -2892,14 +2880,10 @@ pub struct Enum {
     pub variants_stripped: bool,
 }
 
-impl Clean<Vec<Item>> for doctree::Enum {
-    fn clean(&self, cx: &DocContext) -> Vec<Item> {
-        let name = self.name.clean(cx);
-        let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
-        ret.extend(get_blanket_impls_with_node_id(cx, self.id, name.clone()));
-
-        ret.push(Item {
-            name: Some(name),
+impl Clean<Item> for doctree::Enum {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
             def_id: cx.tcx.hir.local_def_id(self.id),
@@ -2911,9 +2895,7 @@ impl Clean<Vec<Item>> for doctree::Enum {
                 generics: self.generics.clean(cx),
                 variants_stripped: false,
             }),
-        });
-
-        ret
+        }
     }
 }
 
@@ -3442,11 +3424,7 @@ fn build_deref_target_impls(cx: &DocContext,
         let primitive = match *target {
             ResolvedPath { did, .. } if did.is_local() => continue,
             ResolvedPath { did, .. } => {
-                // We set the last parameter to false to avoid looking for auto-impls for traits
-                // and therefore avoid an ICE.
-                // The reason behind this is that auto-traits don't propagate through Deref so
-                // we're not supposed to synthesise impls for them.
-                ret.extend(inline::build_impls(cx, did, false));
+                ret.extend(inline::build_impls(cx, did));
                 continue
             }
             _ => match target.primitive_type() {
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 0ee1657f21516..56940483d7be2 100644
--- a/src/librustdoc/passes/collect_trait_impls.rs
+++ b/src/librustdoc/passes/collect_trait_impls.rs
@@ -12,14 +12,20 @@ use clean::*;
 
 use super::Pass;
 use core::DocContext;
+use fold::DocFolder;
 
 pub const COLLECT_TRAIT_IMPLS: Pass =
     Pass::early("collect-trait-impls", collect_trait_impls,
                 "retrieves trait impls for items in the crate");
 
-pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate {
+pub fn collect_trait_impls(krate: Crate, cx: &DocContext) -> Crate {
+    let mut synth = SyntheticImplCollector::new(cx);
+    let mut krate = synth.fold_crate(krate);
+
     if let Some(ref mut it) = krate.module {
         if let ModuleItem(Module { ref mut items, .. }) = it.inner {
+            items.extend(synth.impls);
+
             for &cnum in cx.tcx.crates().iter() {
                 for &did in cx.tcx.all_trait_implementations(cnum).iter() {
                     inline::build_impl(cx, did, items);
@@ -90,3 +96,35 @@ pub fn collect_trait_impls(mut krate: Crate, cx: &DocContext) -> Crate {
 
     krate
 }
+
+struct SyntheticImplCollector<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
+    cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>,
+    impls: Vec<Item>,
+}
+
+impl<'a, 'tcx, 'rcx, 'cstore> SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> {
+    fn new(cx: &'a DocContext<'a, 'tcx, 'rcx, 'cstore>) -> Self {
+        SyntheticImplCollector {
+            cx,
+            impls: Vec::new(),
+        }
+    }
+}
+
+impl<'a, 'tcx, 'rcx, 'cstore> DocFolder for SyntheticImplCollector<'a, 'tcx, 'rcx, 'cstore> {
+    fn fold_item(&mut self, i: Item) -> Option<Item> {
+        if i.is_struct() || i.is_enum() || i.is_union() {
+            if let (Some(node_id), Some(name)) =
+                (self.cx.tcx.hir.as_local_node_id(i.def_id), i.name.clone())
+            {
+                self.impls.extend(get_auto_traits_with_node_id(self.cx, node_id, name.clone()));
+                self.impls.extend(get_blanket_impls_with_node_id(self.cx, node_id, name));
+            } else {
+                self.impls.extend(get_auto_traits_with_def_id(self.cx, i.def_id));
+                self.impls.extend(get_blanket_impls_with_def_id(self.cx, i.def_id));
+            }
+        }
+
+        self.fold_item_recur(i)
+    }
+}

From 9e75db4da0af7347e36f892e706574d9d1a6b52f Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Thu, 30 Aug 2018 16:46:10 -0500
Subject: [PATCH 24/30] refactor: move `access_levels` into RenderInfo

---
 src/librustdoc/clean/blanket_impl.rs   |  2 +-
 src/librustdoc/clean/inline.rs         |  4 ++--
 src/librustdoc/clean/mod.rs            |  5 +----
 src/librustdoc/core.rs                 | 10 ++++------
 src/librustdoc/html/render.rs          |  6 ++++--
 src/librustdoc/passes/strip_private.rs |  2 +-
 src/librustdoc/visit_ast.rs            |  7 +++++--
 src/librustdoc/visit_lib.rs            |  2 +-
 8 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index e7e371cd56785..34c4c70159f3a 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -69,7 +69,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> BlanketImplFinder <'a, 'tcx, 'rcx, 'cstore> {
         let real_name = name.clone().map(|name| Ident::from_str(&name));
         let param_env = self.cx.tcx.param_env(def_id);
         for &trait_def_id in self.cx.all_traits.iter() {
-            if !self.cx.access_levels.borrow().is_doc_reachable(trait_def_id) ||
+            if !self.cx.renderinfo.borrow().access_levels.is_doc_reachable(trait_def_id) ||
                self.cx.generated_synthetics
                       .borrow_mut()
                       .get(&(def_id, trait_def_id))
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index a91336dced398..a29c62f474fa0 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -296,7 +296,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
     // reachable in rustdoc generated documentation
     if !did.is_local() {
         if let Some(traitref) = associated_trait {
-            if !cx.access_levels.borrow().is_doc_reachable(traitref.def_id) {
+            if !cx.renderinfo.borrow().access_levels.is_doc_reachable(traitref.def_id) {
                 return
             }
         }
@@ -317,7 +317,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
     // reachable in rustdoc generated documentation
     if !did.is_local() {
         if let Some(did) = for_.def_id() {
-            if !cx.access_levels.borrow().is_doc_reachable(did) {
+            if !cx.renderinfo.borrow().access_levels.is_doc_reachable(did) {
                 return
             }
         }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 20e1f3f3beae1..8ec4b7bcee8ee 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -28,7 +28,6 @@ use syntax::symbol::InternedString;
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
 
 use rustc::mir::interpret::ConstValue;
-use rustc::middle::privacy::AccessLevels;
 use rustc::middle::resolve_lifetime as rl;
 use rustc::ty::fold::TypeFolder;
 use rustc::middle::lang_items;
@@ -135,7 +134,6 @@ pub struct Crate {
     pub module: Option<Item>,
     pub externs: Vec<(CrateNum, ExternalCrate)>,
     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
-    pub access_levels: Arc<AccessLevels<DefId>>,
     // These are later on moved into `CACHEKEY`, leaving the map empty.
     // Only here so that they can be filtered through the rustdoc passes.
     pub external_traits: FxHashMap<DefId, Trait>,
@@ -216,7 +214,6 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tc
             module: Some(module),
             externs,
             primitives,
-            access_levels: Arc::new(Default::default()),
             external_traits: Default::default(),
             masked_crates,
         }
@@ -2433,7 +2430,7 @@ impl Clean<Type> for hir::Ty {
                 if let Def::TyAlias(def_id) = path.def {
                     // Substitute private type aliases
                     if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) {
-                        if !cx.access_levels.borrow().is_exported(def_id) {
+                        if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
                             alias = Some(&cx.tcx.hir.expect_item(node_id).node);
                         }
                     }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 3a942aa6c8db1..08142a77471d7 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -41,7 +41,6 @@ use std::cell::RefCell;
 use std::mem;
 use rustc_data_structures::sync::{self, Lrc};
 use std::rc::Rc;
-use std::sync::Arc;
 use std::path::PathBuf;
 
 use visit_ast::RustdocVisitor;
@@ -64,8 +63,6 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
     // Note that external items for which `doc(hidden)` applies to are shown as
     // non-reachable while local items aren't. This is because we're reusing
     // the access levels from crateanalysis.
-    /// Later on moved into `clean::Crate`
-    pub access_levels: RefCell<AccessLevels<DefId>>,
     /// Later on moved into `html::render::CACHE_KEY`
     pub renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
@@ -506,15 +503,17 @@ pub fn run_core(search_paths: SearchPaths,
                 clean::path_to_def(&tcx, &["core", "marker", "Send"])
             };
 
+            let mut renderinfo = RenderInfo::default();
+            renderinfo.access_levels = access_levels;
+
             let ctxt = DocContext {
                 tcx,
                 resolver: &resolver,
                 crate_name,
                 cstore: cstore.clone(),
-                access_levels: RefCell::new(access_levels),
                 external_traits: Default::default(),
                 active_extern_traits: Default::default(),
-                renderinfo: Default::default(),
+                renderinfo: RefCell::new(renderinfo),
                 ty_substs: Default::default(),
                 lt_substs: Default::default(),
                 impl_trait_bounds: Default::default(),
@@ -597,7 +596,6 @@ pub fn run_core(search_paths: SearchPaths,
 
             ctxt.sess().abort_if_errors();
 
-            krate.access_levels = Arc::new(ctxt.access_levels.into_inner());
             krate.external_traits = ctxt.external_traits.into_inner();
 
             (krate, ctxt.renderinfo.into_inner(), passes)
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index d052760724e67..f188fccdb3cbe 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -313,7 +313,7 @@ pub struct Cache {
     // Note that external items for which `doc(hidden)` applies to are shown as
     // non-reachable while local items aren't. This is because we're reusing
     // the access levels from crateanalysis.
-    pub access_levels: Arc<AccessLevels<DefId>>,
+    pub access_levels: AccessLevels<DefId>,
 
     /// The version of the crate being documented, if given from the `--crate-version` flag.
     pub crate_version: Option<String>,
@@ -359,6 +359,7 @@ pub struct RenderInfo {
     pub external_paths: ::core::ExternalPaths,
     pub external_typarams: FxHashMap<DefId, String>,
     pub exact_paths: FxHashMap<DefId, Vec<String>>,
+    pub access_levels: AccessLevels<DefId>,
     pub deref_trait_did: Option<DefId>,
     pub deref_mut_trait_did: Option<DefId>,
     pub owned_box_did: Option<DefId>,
@@ -578,6 +579,7 @@ pub fn run(mut krate: clean::Crate,
         external_paths,
         external_typarams,
         exact_paths,
+        access_levels,
         deref_trait_did,
         deref_mut_trait_did,
         owned_box_did,
@@ -600,7 +602,7 @@ pub fn run(mut krate: clean::Crate,
         extern_locations: FxHashMap(),
         primitive_locations: FxHashMap(),
         stripped_mod: false,
-        access_levels: krate.access_levels.clone(),
+        access_levels,
         crate_version: krate.version.take(),
         orphan_impl_items: Vec::new(),
         orphan_trait_impls: Vec::new(),
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index 4fa5943faca07..46d0034497e28 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -25,7 +25,7 @@ pub const STRIP_PRIVATE: Pass =
 pub fn strip_private(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
     // This stripper collects all *retained* nodes.
     let mut retained = DefIdSet();
-    let access_levels = cx.access_levels.borrow().clone();
+    let access_levels = cx.renderinfo.borrow().access_levels.clone();
 
     // strip all private items
     {
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index ce438cd99a4b6..3f8b13d145856 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -269,7 +269,10 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
                 Def::Enum(did) |
                 Def::ForeignTy(did) |
                 Def::TyAlias(did) if !self_is_hidden => {
-                    self.cx.access_levels.borrow_mut().map.insert(did, AccessLevel::Public);
+                    self.cx.renderinfo
+                        .borrow_mut()
+                        .access_levels.map
+                        .insert(did, AccessLevel::Public);
                 },
                 Def::Mod(did) => if !self_is_hidden {
                     ::visit_lib::LibEmbargoVisitor::new(self.cx).visit_mod(did);
@@ -284,7 +287,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> RustdocVisitor<'a, 'tcx, 'rcx, 'cstore> {
             Some(n) => n, None => return false
         };
 
-        let is_private = !self.cx.access_levels.borrow().is_public(def_did);
+        let is_private = !self.cx.renderinfo.borrow().access_levels.is_public(def_did);
         let is_hidden = inherits_doc_hidden(self.cx, def_node_id);
 
         // Only inline if requested or if the item would otherwise be stripped
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index 10a4e69dcc6cd..fd81f937f30c7 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -38,7 +38,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> {
     ) -> LibEmbargoVisitor<'a, 'tcx, 'rcx, 'cstore> {
         LibEmbargoVisitor {
             cx,
-            access_levels: cx.access_levels.borrow_mut(),
+            access_levels: RefMut::map(cx.renderinfo.borrow_mut(), |ri| &mut ri.access_levels),
             prev_level: Some(AccessLevel::Public),
             visited_mods: FxHashSet()
         }

From 8aba29a5cf25f9c84e4f753a7ea4b5c0d6446e32 Mon Sep 17 00:00:00 2001
From: QuietMisdreavus <grey@quietmisdreavus.net>
Date: Sat, 1 Sep 2018 21:20:39 -0500
Subject: [PATCH 25/30] shuffle ownership of `external_traits`

constraints:

- clean/inline.rs needs this map to fill in traits when inlining
- fold.rs needs this map to allow passes to fold trait items
- html/render.rs needs this map to seed the Cache.traits map of all
  known traits

The first two are the real problem, since `DocFolder` only operates on
`clean::Crate` but `clean/inline.rs` only sees the `DocContext`. The
introduction of early passes means that these two now exist at the same
time, so they need to share ownership of the map. Even better, the use
of `Crate` in a rustc thread pool means that it needs to be Sync, so it
can't use `Lrc<Lock>` to manually activate thread-safety.

`parking_lot` is reused from elsewhere in the tree to allow use of its
`ReentrantMutex`, as the relevant parts of rustdoc are still
single-threaded and this allows for easier use in that context.
---
 src/Cargo.lock                        |  1 +
 src/librustdoc/Cargo.toml             |  1 +
 src/librustdoc/clean/inline.rs        | 14 ++++++++++----
 src/librustdoc/clean/mod.rs           |  6 ++++--
 src/librustdoc/core.rs                |  6 +++---
 src/librustdoc/fold.rs                | 15 ++++++++-------
 src/librustdoc/html/render.rs         |  2 +-
 src/librustdoc/lib.rs                 |  1 +
 src/librustdoc/passes/strip_hidden.rs |  9 ++-------
 9 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/src/Cargo.lock b/src/Cargo.lock
index a4f9082c284cd..56efe5c5fb499 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -2417,6 +2417,7 @@ name = "rustdoc"
 version = "0.0.0"
 dependencies = [
  "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index e163fc68cbda7..845bfad7807d3 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -11,3 +11,4 @@ path = "lib.rs"
 pulldown-cmark = { version = "0.1.2", default-features = false }
 minifier = "0.0.19"
 tempfile = "3"
+parking_lot = "0.6.4"
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index a29c62f474fa0..6e1c1d17d6e15 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -538,10 +538,13 @@ pub fn record_extern_trait(cx: &DocContext, did: DefId) {
         return;
     }
 
-    if cx.external_traits.borrow().contains_key(&did) ||
-        cx.active_extern_traits.borrow().contains(&did)
     {
-        return;
+        let external_traits = cx.external_traits.lock();
+        if external_traits.borrow().contains_key(&did) ||
+            cx.active_extern_traits.borrow().contains(&did)
+        {
+            return;
+        }
     }
 
     cx.active_extern_traits.borrow_mut().push(did);
@@ -549,6 +552,9 @@ pub fn record_extern_trait(cx: &DocContext, did: DefId) {
     debug!("record_extern_trait: {:?}", did);
     let trait_ = build_external_trait(cx, did);
 
-    cx.external_traits.borrow_mut().insert(did, trait_);
+    {
+        let external_traits = cx.external_traits.lock();
+        external_traits.borrow_mut().insert(did, trait_);
+    }
     cx.active_extern_traits.borrow_mut().remove_item(&did);
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 8ec4b7bcee8ee..943bd2526c9c2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -55,6 +55,8 @@ use std::cell::RefCell;
 use std::sync::Arc;
 use std::u32;
 
+use parking_lot::ReentrantMutex;
+
 use core::{self, DocContext};
 use doctree;
 use visit_ast;
@@ -136,7 +138,7 @@ pub struct Crate {
     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
     // These are later on moved into `CACHEKEY`, leaving the map empty.
     // Only here so that they can be filtered through the rustdoc passes.
-    pub external_traits: FxHashMap<DefId, Trait>,
+    pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, Trait>>>>,
     pub masked_crates: FxHashSet<CrateNum>,
 }
 
@@ -214,7 +216,7 @@ impl<'a, 'tcx, 'rcx, 'cstore> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tc
             module: Some(module),
             externs,
             primitives,
-            external_traits: Default::default(),
+            external_traits: cx.external_traits.clone(),
             masked_crates,
         }
     }
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 08142a77471d7..253d8b93c667b 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -36,11 +36,13 @@ use syntax::symbol::keywords;
 use syntax_pos::DUMMY_SP;
 use errors;
 use errors::emitter::{Emitter, EmitterWriter};
+use parking_lot::ReentrantMutex;
 
 use std::cell::RefCell;
 use std::mem;
 use rustc_data_structures::sync::{self, Lrc};
 use std::rc::Rc;
+use std::sync::Arc;
 use std::path::PathBuf;
 
 use visit_ast::RustdocVisitor;
@@ -66,7 +68,7 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a, 'cstore: 'rcx> {
     /// Later on moved into `html::render::CACHE_KEY`
     pub renderinfo: RefCell<RenderInfo>,
     /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
-    pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>,
+    pub external_traits: Arc<ReentrantMutex<RefCell<FxHashMap<DefId, clean::Trait>>>>,
     /// Used while populating `external_traits` to ensure we don't process the same trait twice at
     /// the same time.
     pub active_extern_traits: RefCell<Vec<DefId>>,
@@ -596,8 +598,6 @@ pub fn run_core(search_paths: SearchPaths,
 
             ctxt.sess().abort_if_errors();
 
-            krate.external_traits = ctxt.external_traits.into_inner();
-
             (krate, ctxt.renderinfo.into_inner(), passes)
         }), &sess)
     })
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index 6d96bc8e36038..b8e27c5317083 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::mem;
-
 use clean::*;
 
 pub struct StripItem(pub Item);
@@ -116,11 +114,14 @@ pub trait DocFolder : Sized {
     fn fold_crate(&mut self, mut c: Crate) -> Crate {
         c.module = c.module.take().and_then(|module| self.fold_item(module));
 
-        let traits = mem::replace(&mut c.external_traits, Default::default());
-        c.external_traits.extend(traits.into_iter().map(|(k, mut v)| {
-            v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
-            (k, v)
-        }));
+        {
+            let guard = c.external_traits.lock();
+            let traits = guard.replace(Default::default());
+            guard.borrow_mut().extend(traits.into_iter().map(|(k, mut v)| {
+                v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
+                (k, v)
+            }));
+        }
         c
     }
 }
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index f188fccdb3cbe..ed71d13009d63 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -606,7 +606,7 @@ pub fn run(mut krate: clean::Crate,
         crate_version: krate.version.take(),
         orphan_impl_items: Vec::new(),
         orphan_trait_impls: Vec::new(),
-        traits: mem::replace(&mut krate.external_traits, FxHashMap()),
+        traits: krate.external_traits.lock().replace(FxHashMap()),
         deref_trait_did,
         deref_mut_trait_did,
         owned_box_did,
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 11cf43dad4a92..d0b00fd52ee77 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -50,6 +50,7 @@ extern crate rustc_errors as errors;
 extern crate pulldown_cmark;
 extern crate tempfile;
 extern crate minifier;
+extern crate parking_lot;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs
index eab4022a3389f..24dd4cc13bfe8 100644
--- a/src/librustdoc/passes/strip_hidden.rs
+++ b/src/librustdoc/passes/strip_hidden.rs
@@ -24,13 +24,9 @@ pub const STRIP_HIDDEN: Pass =
                 "strips all doc(hidden) items from the output");
 
 /// Strip items marked `#[doc(hidden)]`
-pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
+pub fn strip_hidden(krate: clean::Crate, _: &DocContext) -> clean::Crate {
     let mut retained = DefIdSet();
 
-    // as an early pass, the external traits haven't been swapped in, so we need to do that ahead
-    // of time
-    mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut());
-
     // strip all #[doc(hidden)] items
     let krate = {
         let mut stripper = Stripper{ retained: &mut retained, update_retained: true };
@@ -39,8 +35,7 @@ pub fn strip_hidden(mut krate: clean::Crate, cx: &DocContext) -> clean::Crate {
 
     // strip all impls referencing stripped items
     let mut stripper = ImplStripper { retained: &retained };
-    let mut krate = stripper.fold_crate(krate);
-    mem::swap(&mut krate.external_traits, &mut cx.external_traits.borrow_mut());
+    let krate = stripper.fold_crate(krate);
 
     krate
 }

From 73dd19f530c1b885c90d3c466161232625b38f1c Mon Sep 17 00:00:00 2001
From: Mark Rousskov <mark.simulacrum@gmail.com>
Date: Thu, 6 Sep 2018 10:20:01 -0600
Subject: [PATCH 26/30] Stabilize the 2018 edition

---
 src/doc/rustdoc/src/command-line-arguments.md | 14 ++++++++++++++
 src/doc/rustdoc/src/unstable-features.md      | 13 -------------
 src/librustdoc/lib.rs                         |  2 +-
 src/libsyntax_pos/edition.rs                  |  2 +-
 4 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md
index 417608cc5ca0a..aba485f752ab2 100644
--- a/src/doc/rustdoc/src/command-line-arguments.md
+++ b/src/doc/rustdoc/src/command-line-arguments.md
@@ -345,3 +345,17 @@ $ rustdoc src/lib.rs --sysroot /path/to/sysroot
 
 Similar to `rustc --sysroot`, this lets you change the sysroot `rustdoc` uses
 when compiling your code.
+
+### `--edition`: control the edition of docs and doctests
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs --edition 2018
+$ rustdoc --test src/lib.rs --edition 2018
+```
+
+This flag allows rustdoc to treat your rust code as the given edition. It will compile doctests with
+the given edition as well. As with `rustc`, the default edition that `rustdoc` will use is `2015`
+(the first edition).
+
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 32fb8c2f7d58e..071575b1fc094 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -346,19 +346,6 @@ details.
 
 [issue-display-warnings]: https://github.com/rust-lang/rust/issues/41574
 
-### `--edition`: control the edition of docs and doctests
-
-Using this flag looks like this:
-
-```bash
-$ rustdoc src/lib.rs -Z unstable-options --edition 2018
-$ rustdoc --test src/lib.rs -Z unstable-options --edition 2018
-```
-
-This flag allows rustdoc to treat your rust code as the given edition. It will compile doctests with
-the given edition as well. As with `rustc`, the default edition that `rustdoc` will use is `2015`
-(the first edition).
-
 ### `--extern-html-root-url`: control how rustdoc links to non-local crates
 
 Using this flag looks like this:
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 1acae86f0068f..3211607807ff3 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -286,7 +286,7 @@ fn opts() -> Vec<RustcOptGroup> {
                       \"light-suffix.css\"",
                      "PATH")
         }),
-        unstable("edition", |o| {
+        stable("edition", |o| {
             o.optopt("", "edition",
                      "edition to use when compiling rust code (default: 2015)",
                      "EDITION")
diff --git a/src/libsyntax_pos/edition.rs b/src/libsyntax_pos/edition.rs
index fce8fc3db4e4e..7709db72a02fb 100644
--- a/src/libsyntax_pos/edition.rs
+++ b/src/libsyntax_pos/edition.rs
@@ -65,7 +65,7 @@ impl Edition {
     pub fn is_stable(&self) -> bool {
         match *self {
             Edition::Edition2015 => true,
-            Edition::Edition2018 => false,
+            Edition::Edition2018 => true,
         }
     }
 }

From 8c3ac3cd84c49e19fce781efaee864600836086d Mon Sep 17 00:00:00 2001
From: Mark Rousskov <mark.simulacrum@gmail.com>
Date: Thu, 6 Sep 2018 10:47:41 -0600
Subject: [PATCH 27/30] Remove crate_visibility_modifier from 2018 edition

---
 src/libsyntax/feature_gate.rs                                  | 2 +-
 src/test/ui-fulldeps/unnecessary-extern-crate.rs               | 2 +-
 src/test/ui/crate-in-paths.rs                                  | 2 +-
 src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed | 2 +-
 src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs    | 2 +-
 src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed    | 2 +-
 src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs       | 2 +-
 src/test/ui/rust-2018/edition-lint-nested-paths.fixed          | 2 +-
 src/test/ui/rust-2018/edition-lint-nested-paths.rs             | 2 +-
 9 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index e3ea3563d853b..88e93021bf0a9 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -389,7 +389,7 @@ declare_features! (
     (active, non_exhaustive, "1.22.0", Some(44109), None),
 
     // `crate` as visibility modifier, synonymous to `pub(crate)`
-    (active, crate_visibility_modifier, "1.23.0", Some(45388), Some(Edition::Edition2018)),
+    (active, crate_visibility_modifier, "1.23.0", Some(45388), None),
 
     // extern types
     (active, extern_types, "1.23.0", Some(43467), None),
diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.rs b/src/test/ui-fulldeps/unnecessary-extern-crate.rs
index ea3e0587958b1..df723ddf590c4 100644
--- a/src/test/ui-fulldeps/unnecessary-extern-crate.rs
+++ b/src/test/ui-fulldeps/unnecessary-extern-crate.rs
@@ -11,7 +11,7 @@
 // edition:2018
 
 #![deny(unused_extern_crates)]
-#![feature(alloc, test, libc)]
+#![feature(alloc, test, libc, crate_visibility_modifier)]
 
 extern crate alloc;
 //~^ ERROR unused extern crate
diff --git a/src/test/ui/crate-in-paths.rs b/src/test/ui/crate-in-paths.rs
index ef01294f941aa..cbf60b6b6a696 100644
--- a/src/test/ui/crate-in-paths.rs
+++ b/src/test/ui/crate-in-paths.rs
@@ -10,7 +10,7 @@
 
 // edition:2018
 
-#![feature(edition_2018_preview)]
+#![feature(crate_visibility_modifier)]
 
 mod bar {
     crate struct Foo;
diff --git a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
index 279d4e9a80622..211d2b726de1a 100644
--- a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
+++ b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
@@ -10,7 +10,7 @@
 
 // run-rustfix
 
-#![feature(rust_2018_preview)]
+#![feature(rust_2018_preview, crate_visibility_modifier)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 mod foo {
diff --git a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs
index ff290555a695c..90b5a7f816226 100644
--- a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs
+++ b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.rs
@@ -10,7 +10,7 @@
 
 // run-rustfix
 
-#![feature(rust_2018_preview)]
+#![feature(rust_2018_preview, crate_visibility_modifier)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 mod foo {
diff --git a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed
index 929b7cd061b3e..94803a117dc54 100644
--- a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed
+++ b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.fixed
@@ -10,7 +10,7 @@
 
 // run-rustfix
 
-#![feature(rust_2018_preview)]
+#![feature(rust_2018_preview, crate_visibility_modifier)]
 #![deny(absolute_paths_not_starting_with_crate)]
 #![allow(unused_imports)]
 #![allow(dead_code)]
diff --git a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs
index b5693c4bb93ad..7f68eeff438cd 100644
--- a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs
+++ b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.rs
@@ -10,7 +10,7 @@
 
 // run-rustfix
 
-#![feature(rust_2018_preview)]
+#![feature(rust_2018_preview, crate_visibility_modifier)]
 #![deny(absolute_paths_not_starting_with_crate)]
 #![allow(unused_imports)]
 #![allow(dead_code)]
diff --git a/src/test/ui/rust-2018/edition-lint-nested-paths.fixed b/src/test/ui/rust-2018/edition-lint-nested-paths.fixed
index 06f6b6d75a700..ee54229bfb240 100644
--- a/src/test/ui/rust-2018/edition-lint-nested-paths.fixed
+++ b/src/test/ui/rust-2018/edition-lint-nested-paths.fixed
@@ -10,7 +10,7 @@
 
 // run-rustfix
 
-#![feature(rust_2018_preview)]
+#![feature(rust_2018_preview, crate_visibility_modifier)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 use crate::foo::{a, b};
diff --git a/src/test/ui/rust-2018/edition-lint-nested-paths.rs b/src/test/ui/rust-2018/edition-lint-nested-paths.rs
index c2831ec04b797..9a42f5f28c821 100644
--- a/src/test/ui/rust-2018/edition-lint-nested-paths.rs
+++ b/src/test/ui/rust-2018/edition-lint-nested-paths.rs
@@ -10,7 +10,7 @@
 
 // run-rustfix
 
-#![feature(rust_2018_preview)]
+#![feature(rust_2018_preview, crate_visibility_modifier)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 use foo::{a, b};

From 358fc5b62126f997a1c38ba4c8be60ae16e4a2c4 Mon Sep 17 00:00:00 2001
From: Jorge Aparicio <jorge@japaric.io>
Date: Fri, 7 Sep 2018 12:43:39 +0200
Subject: [PATCH 28/30] stabilize `#[panic_handler]`

---
 src/libstd/lib.rs                             |  1 -
 src/libsyntax/feature_gate.rs                 |  7 ++-----
 .../compile-fail/auxiliary/some-panic-impl.rs |  1 -
 src/test/compile-fail/panic-handler-twice.rs  |  1 -
 src/test/run-make-fulldeps/issue-51671/app.rs |  1 -
 .../panic-impl-provider.rs                    |  1 -
 .../const-eval/const_panic_libcore_main.rs    |  1 -
 .../const_panic_libcore_main.stderr           | 12 +++++------
 .../feature-gate-panic-handler.rs             | 21 -------------------
 .../feature-gate-panic-handler.stderr         | 11 ----------
 .../auxiliary/some-panic-impl.rs              |  1 -
 .../panic-handler-bad-signature-1.rs          |  1 -
 .../panic-handler-bad-signature-1.stderr      |  4 ++--
 .../panic-handler-bad-signature-2.rs          |  1 -
 .../panic-handler-bad-signature-2.stderr      |  2 +-
 .../panic-handler-bad-signature-3.rs          |  1 -
 .../panic-handler-bad-signature-3.stderr      |  2 +-
 .../panic-handler-bad-signature-4.rs          |  1 -
 .../panic-handler-bad-signature-4.stderr      |  2 +-
 .../panic-handler/panic-handler-duplicate.rs  |  1 -
 .../panic-handler-duplicate.stderr            |  4 ++--
 .../panic-handler-requires-panic-info.rs      |  1 -
 .../ui/panic-handler/panic-handler-std.rs     |  1 -
 .../ui/panic-handler/panic-handler-std.stderr |  4 ++--
 src/test/ui/panic_implementation-closures.rs  |  1 -
 25 files changed, 17 insertions(+), 67 deletions(-)
 delete mode 100644 src/test/ui/feature-gates/feature-gate-panic-handler.rs
 delete mode 100644 src/test/ui/feature-gates/feature-gate-panic-handler.stderr

diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index e7195b3e21ee3..4278926b042f3 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -312,7 +312,6 @@
 #![feature(doc_keyword)]
 #![feature(panic_info_message)]
 #![cfg_attr(stage0, feature(panic_implementation))]
-#![cfg_attr(not(stage0), feature(panic_handler))]
 #![feature(non_exhaustive)]
 
 #![default_lib_allocator]
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index e3ea3563d853b..0270e36db1177 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -487,7 +487,6 @@ declare_features! (
 
     // RFC 2070: #[panic_implementation] / #[panic_handler]
     (active, panic_implementation, "1.28.0", Some(44489), None),
-    (active, panic_handler, "1.30.0", Some(44489), None),
 
     // #[doc(keyword = "...")]
     (active, doc_keyword, "1.28.0", Some(51315), None),
@@ -674,6 +673,7 @@ declare_features! (
     (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None),
     // Allows all literals in attribute lists and values of key-value pairs.
     (accepted, attr_literals, "1.30.0", Some(34981), None),
+    (accepted, panic_handler, "1.30.0", Some(44489), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -1143,10 +1143,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
            cfg_fn!(panic_implementation))),
 
     // RFC 2070
-    ("panic_handler", Normal, Gated(Stability::Unstable,
-                                    "panic_handler",
-                                    "#[panic_handler] is an unstable feature",
-                                    cfg_fn!(panic_handler))),
+    ("panic_handler", Normal, Ungated),
 
     ("alloc_error_handler", Normal, Gated(Stability::Unstable,
                            "alloc_error_handler",
diff --git a/src/test/compile-fail/auxiliary/some-panic-impl.rs b/src/test/compile-fail/auxiliary/some-panic-impl.rs
index e3b4fba176e3c..090123198d175 100644
--- a/src/test/compile-fail/auxiliary/some-panic-impl.rs
+++ b/src/test/compile-fail/auxiliary/some-panic-impl.rs
@@ -11,7 +11,6 @@
 // no-prefer-dynamic
 
 #![crate_type = "rlib"]
-#![feature(panic_handler)]
 #![no_std]
 
 use core::panic::PanicInfo;
diff --git a/src/test/compile-fail/panic-handler-twice.rs b/src/test/compile-fail/panic-handler-twice.rs
index 6c9515ca90994..10e0453cf5ed4 100644
--- a/src/test/compile-fail/panic-handler-twice.rs
+++ b/src/test/compile-fail/panic-handler-twice.rs
@@ -10,7 +10,6 @@
 
 // aux-build:some-panic-impl.rs
 
-#![feature(panic_handler)]
 #![feature(lang_items)]
 #![no_std]
 #![no_main]
diff --git a/src/test/run-make-fulldeps/issue-51671/app.rs b/src/test/run-make-fulldeps/issue-51671/app.rs
index e980b12039e96..4066214f4b47e 100644
--- a/src/test/run-make-fulldeps/issue-51671/app.rs
+++ b/src/test/run-make-fulldeps/issue-51671/app.rs
@@ -10,7 +10,6 @@
 
 #![crate_type = "bin"]
 #![feature(lang_items)]
-#![feature(panic_handler)]
 #![no_main]
 #![no_std]
 
diff --git a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs
index 065b2b6bf18fa..77aae7ee2c06b 100644
--- a/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs
+++ b/src/test/run-make-fulldeps/panic-impl-transitive/panic-impl-provider.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![crate_type = "rlib"]
-#![feature(panic_handler)]
 #![no_std]
 
 use core::panic::PanicInfo;
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
index f5e5f9778faed..0364123994dff 100644
--- a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
+++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs
@@ -10,7 +10,6 @@
 
 #![crate_type = "bin"]
 #![feature(lang_items)]
-#![feature(panic_handler)]
 #![feature(const_panic)]
 #![no_main]
 #![no_std]
diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr b/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr
index 7cb9f51c427a7..44b30c08cdea2 100644
--- a/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr
+++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.stderr
@@ -1,31 +1,31 @@
 error: this constant cannot be used
-  --> $DIR/const_panic_libcore_main.rs:20:1
+  --> $DIR/const_panic_libcore_main.rs:19:1
    |
 LL | const Z: () = panic!("cheese");
    | ^^^^^^^^^^^^^^----------------^
    |               |
-   |               the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_main.rs:20:15
+   |               the evaluated program panicked at 'cheese', $DIR/const_panic_libcore_main.rs:19:15
    |
    = note: #[deny(const_err)] on by default
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: this constant cannot be used
-  --> $DIR/const_panic_libcore_main.rs:23:1
+  --> $DIR/const_panic_libcore_main.rs:22:1
    |
 LL | const Y: () = unreachable!();
    | ^^^^^^^^^^^^^^--------------^
    |               |
-   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_main.rs:23:15
+   |               the evaluated program panicked at 'internal error: entered unreachable code', $DIR/const_panic_libcore_main.rs:22:15
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
 error: this constant cannot be used
-  --> $DIR/const_panic_libcore_main.rs:26:1
+  --> $DIR/const_panic_libcore_main.rs:25:1
    |
 LL | const X: () = unimplemented!();
    | ^^^^^^^^^^^^^^----------------^
    |               |
-   |               the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore_main.rs:26:15
+   |               the evaluated program panicked at 'not yet implemented', $DIR/const_panic_libcore_main.rs:25:15
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
diff --git a/src/test/ui/feature-gates/feature-gate-panic-handler.rs b/src/test/ui/feature-gates/feature-gate-panic-handler.rs
deleted file mode 100644
index fd16268ef8b4e..0000000000000
--- a/src/test/ui/feature-gates/feature-gate-panic-handler.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C panic=abort
-
-#![no_std]
-#![no_main]
-
-use core::panic::PanicInfo;
-
-#[panic_handler] //~ ERROR #[panic_handler] is an unstable feature (see issue #44489)
-fn panic(info: &PanicInfo) -> ! {
-    loop {}
-}
diff --git a/src/test/ui/feature-gates/feature-gate-panic-handler.stderr b/src/test/ui/feature-gates/feature-gate-panic-handler.stderr
deleted file mode 100644
index 9680a240a9925..0000000000000
--- a/src/test/ui/feature-gates/feature-gate-panic-handler.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: #[panic_handler] is an unstable feature (see issue #44489)
-  --> $DIR/feature-gate-panic-handler.rs:18:1
-   |
-LL | #[panic_handler] //~ ERROR #[panic_handler] is an unstable feature (see issue #44489)
-   | ^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(panic_handler)] to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs b/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs
index e3b4fba176e3c..090123198d175 100644
--- a/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs
+++ b/src/test/ui/panic-handler/auxiliary/some-panic-impl.rs
@@ -11,7 +11,6 @@
 // no-prefer-dynamic
 
 #![crate_type = "rlib"]
-#![feature(panic_handler)]
 #![no_std]
 
 use core::panic::PanicInfo;
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
index cc7e337fc9e65..8d53c66adbd93 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-1.rs
@@ -10,7 +10,6 @@
 
 // compile-flags:-C panic=abort
 
-#![feature(panic_handler)]
 #![no_std]
 #![no_main]
 
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr
index 5771f4277b46d..72b85da028f1f 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-1.stderr
@@ -1,11 +1,11 @@
 error: return type should be `!`
-  --> $DIR/panic-handler-bad-signature-1.rs:22:6
+  --> $DIR/panic-handler-bad-signature-1.rs:21:6
    |
 LL | ) -> () //~ ERROR return type should be `!`
    |      ^^
 
 error: argument should be `&PanicInfo`
-  --> $DIR/panic-handler-bad-signature-1.rs:21:11
+  --> $DIR/panic-handler-bad-signature-1.rs:20:11
    |
 LL |     info: PanicInfo, //~ ERROR argument should be `&PanicInfo`
    |           ^^^^^^^^^
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
index ec698903c846e..0e8b3d5e855cb 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-2.rs
@@ -10,7 +10,6 @@
 
 // compile-flags:-C panic=abort
 
-#![feature(panic_handler)]
 #![no_std]
 #![no_main]
 
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr
index 4823f8a2781b0..f2bcb6b680952 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-2.stderr
@@ -1,5 +1,5 @@
 error: argument should be `&PanicInfo`
-  --> $DIR/panic-handler-bad-signature-2.rs:21:11
+  --> $DIR/panic-handler-bad-signature-2.rs:20:11
    |
 LL |     info: &'static PanicInfo, //~ ERROR argument should be `&PanicInfo`
    |           ^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
index 585716c7c7569..ac1b19105b62e 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.rs
@@ -10,7 +10,6 @@
 
 // compile-flags:-C panic=abort
 
-#![feature(panic_handler)]
 #![no_std]
 #![no_main]
 
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr
index 5d0395e17f54d..77227e0d5a61c 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-3.stderr
@@ -1,5 +1,5 @@
 error: function should have one argument
-  --> $DIR/panic-handler-bad-signature-3.rs:20:1
+  --> $DIR/panic-handler-bad-signature-3.rs:19:1
    |
 LL | fn panic() -> ! { //~ ERROR function should have one argument
    | ^^^^^^^^^^^^^^^
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
index 9cda37f27b332..f4728408a1afa 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-4.rs
@@ -10,7 +10,6 @@
 
 // compile-flags:-C panic=abort
 
-#![feature(panic_handler)]
 #![no_std]
 #![no_main]
 
diff --git a/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr b/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr
index a61b9b3743c7d..0dd47cafd7553 100644
--- a/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr
+++ b/src/test/ui/panic-handler/panic-handler-bad-signature-4.stderr
@@ -1,5 +1,5 @@
 error: should have no type parameters
-  --> $DIR/panic-handler-bad-signature-4.rs:20:1
+  --> $DIR/panic-handler-bad-signature-4.rs:19:1
    |
 LL | / fn panic<T>(pi: &PanicInfo) -> ! {
 LL | |     //~^ ERROR should have no type parameters
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.rs b/src/test/ui/panic-handler/panic-handler-duplicate.rs
index 7d7fe251869f1..c4fb4903e0031 100644
--- a/src/test/ui/panic-handler/panic-handler-duplicate.rs
+++ b/src/test/ui/panic-handler/panic-handler-duplicate.rs
@@ -11,7 +11,6 @@
 // compile-flags:-C panic=abort
 
 #![feature(lang_items)]
-#![feature(panic_handler)]
 #![no_std]
 #![no_main]
 
diff --git a/src/test/ui/panic-handler/panic-handler-duplicate.stderr b/src/test/ui/panic-handler/panic-handler-duplicate.stderr
index d8afaa27e2662..e243d9079d851 100644
--- a/src/test/ui/panic-handler/panic-handler-duplicate.stderr
+++ b/src/test/ui/panic-handler/panic-handler-duplicate.stderr
@@ -1,5 +1,5 @@
 error[E0152]: duplicate lang item found: `panic_impl`.
-  --> $DIR/panic-handler-duplicate.rs:26:1
+  --> $DIR/panic-handler-duplicate.rs:25:1
    |
 LL | / fn panic2(info: &PanicInfo) -> ! { //~ ERROR duplicate lang item found: `panic_impl`.
 LL | |     loop {}
@@ -7,7 +7,7 @@ LL | | }
    | |_^
    |
 note: first defined here.
-  --> $DIR/panic-handler-duplicate.rs:21:1
+  --> $DIR/panic-handler-duplicate.rs:20:1
    |
 LL | / fn panic(info: &PanicInfo) -> ! {
 LL | |     loop {}
diff --git a/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs b/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs
index ec68a414f54d5..133d6c0557ab6 100644
--- a/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs
+++ b/src/test/ui/panic-handler/panic-handler-requires-panic-info.rs
@@ -13,7 +13,6 @@
 
 #![feature(lang_items)]
 #![feature(no_core)]
-#![feature(panic_handler)]
 #![no_core]
 #![no_main]
 
diff --git a/src/test/ui/panic-handler/panic-handler-std.rs b/src/test/ui/panic-handler/panic-handler-std.rs
index 7cbe0a35baed8..ff5995237cf21 100644
--- a/src/test/ui/panic-handler/panic-handler-std.rs
+++ b/src/test/ui/panic-handler/panic-handler-std.rs
@@ -10,7 +10,6 @@
 
 // error-pattern: duplicate lang item found: `panic_impl`.
 
-#![feature(panic_handler)]
 
 use std::panic::PanicInfo;
 
diff --git a/src/test/ui/panic-handler/panic-handler-std.stderr b/src/test/ui/panic-handler/panic-handler-std.stderr
index b141a2171646c..4ec1c6df35522 100644
--- a/src/test/ui/panic-handler/panic-handler-std.stderr
+++ b/src/test/ui/panic-handler/panic-handler-std.stderr
@@ -1,5 +1,5 @@
 error[E0152]: duplicate lang item found: `panic_impl`.
-  --> $DIR/panic-handler-std.rs:18:1
+  --> $DIR/panic-handler-std.rs:17:1
    |
 LL | / fn panic(info: PanicInfo) -> ! {
 LL | |     loop {}
@@ -9,7 +9,7 @@ LL | | }
    = note: first defined in crate `std`.
 
 error: argument should be `&PanicInfo`
-  --> $DIR/panic-handler-std.rs:18:16
+  --> $DIR/panic-handler-std.rs:17:16
    |
 LL | fn panic(info: PanicInfo) -> ! {
    |                ^^^^^^^^^
diff --git a/src/test/ui/panic_implementation-closures.rs b/src/test/ui/panic_implementation-closures.rs
index 6642db6ee76bf..5902a1ae1b023 100644
--- a/src/test/ui/panic_implementation-closures.rs
+++ b/src/test/ui/panic_implementation-closures.rs
@@ -12,7 +12,6 @@
 
 #![crate_type = "rlib"]
 #![no_std]
-#![feature(panic_handler)]
 
 #[panic_handler]
 pub fn panic_fmt(_: &::core::panic::PanicInfo) -> ! {

From 8aae6ca44a1bea64e2be3f2ce5a4581bb65d43ef Mon Sep 17 00:00:00 2001
From: Tom Tromey <tom@tromey.com>
Date: Wed, 5 Sep 2018 13:05:46 -0600
Subject: [PATCH 29/30] Have rust-lldb look for the rust-enabled lldb

We're shipping a rust-enabled lldb, but the "lldb" executable is not
installed into the "bin" directory by rustup.  See the discussion in
https://github.com/rust-lang-nursery/rustup.rs/pull/1492 for
background on this decision.  There, we agreed to have rust-lldb
prefer the rust-enabled lldb if it is installed.

This patch changes dist.rs to put lldb into rustlib, following what
was done for the other LLVM tools in #53955, and then fixes rust-lldb
to prefer that lldb, if it exists.

See issue #48168
---
 src/bootstrap/dist.rs |  7 ++++---
 src/etc/rust-lldb     | 26 +++++++++++++++++---------
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 167e4a78edaf8..2d94704fda7d6 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -2056,7 +2056,8 @@ impl Step for Lldb {
         drop(fs::remove_dir_all(&image));
 
         // Prepare the image directory
-        let dst = image.join("bin");
+        let root = image.join("lib/rustlib").join(&*target);
+        let dst = root.join("bin");
         t!(fs::create_dir_all(&dst));
         for program in &["lldb", "lldb-argdumper", "lldb-mi", "lldb-server"] {
             let exe = bindir.join(exe(program, &target));
@@ -2065,7 +2066,7 @@ impl Step for Lldb {
 
         // The libraries.
         let libdir = builder.llvm_out(target).join("lib");
-        let dst = image.join("lib");
+        let dst = root.join("lib");
         t!(fs::create_dir_all(&dst));
         for entry in t!(fs::read_dir(&libdir)) {
             let entry = entry.unwrap();
@@ -2093,7 +2094,7 @@ impl Step for Lldb {
             let entry = t!(entry);
             if let Ok(name) = entry.file_name().into_string() {
                 if name.starts_with("python") {
-                    let dst = image.join(libdir_name)
+                    let dst = root.join(libdir_name)
                         .join(entry.file_name());
                     t!(fs::create_dir_all(&dst));
                     builder.cp_r(&entry.path(), &dst);
diff --git a/src/etc/rust-lldb b/src/etc/rust-lldb
index 6a2849b55485e..6ed8210349e17 100755
--- a/src/etc/rust-lldb
+++ b/src/etc/rust-lldb
@@ -12,27 +12,35 @@
 # Exit if anything fails
 set -e
 
-LLDB_VERSION=`lldb --version 2>/dev/null | head -1 | cut -d. -f1`
+# Find out where to look for the pretty printer Python module
+RUSTC_SYSROOT=`rustc --print sysroot`
+
+# Find the host triple so we can find lldb in rustlib.
+host=`rustc -vV | sed -n -e 's/^host: //p'`
+
+lldb=lldb
+if [ -f "$RUSTC_SYSROOT/lib/rustlib/$host/bin/lldb" ]; then
+    lldb="$RUSTC_SYSROOT/lib/rustlib/$host/bin/lldb"
+else
+    LLDB_VERSION=`"$lldb" --version 2>/dev/null | head -1 | cut -d. -f1`
 
-if [ "$LLDB_VERSION" = "lldb-350" ]
-then
-    echo "***"
+    if [ "$LLDB_VERSION" = "lldb-350" ]
+    then
+        echo "***"
 	echo \
 "WARNING: This version of LLDB has known issues with Rust and cannot \
 display the contents of local variables!"
-    echo "***"
+        echo "***"
+    fi
 fi
 
-# Find out where to look for the pretty printer Python module
-RUSTC_SYSROOT=`rustc --print sysroot`
-
 # Prepare commands that will be loaded before any file on the command line has been loaded
 script_import="command script import \"$RUSTC_SYSROOT/lib/rustlib/etc/lldb_rust_formatters.py\""
 category_definition="type summary add --no-value --python-function lldb_rust_formatters.print_val -x \".*\" --category Rust"
 category_enable="type category enable Rust"
 
 # Call LLDB with the commands added to the argument list
-exec lldb --one-line-before-file="$script_import" \
+exec "$lldb" --one-line-before-file="$script_import" \
     --one-line-before-file="$category_definition" \
     --one-line-before-file="$category_enable" \
     "$@"

From ef440686131096e08635df418a70507bfc621a30 Mon Sep 17 00:00:00 2001
From: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
Date: Thu, 6 Sep 2018 11:06:32 +0200
Subject: [PATCH 30/30] rustbuild: allow configuring llvm version suffix

Signed-off-by: Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
---
 config.toml.example     | 4 ++++
 src/bootstrap/config.rs | 3 +++
 src/bootstrap/native.rs | 4 ++++
 3 files changed, 11 insertions(+)

diff --git a/config.toml.example b/config.toml.example
index 35f69cd05b607..087dc418e2dce 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -82,6 +82,10 @@
 # passed to prefer linking to shared libraries.
 #link-shared = false
 
+# When building llvm, this configures what is being appended to the version.
+# If absent, we let the version as-is.
+#version-suffix = "-rust"
+
 # On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass
 # with clang-cl, so this is special in that it only compiles LLVM with clang-cl
 #clang-cl = '/path/to/clang-cl.exe'
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index bf4d39c4947e5..70b21a1567b0f 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -86,6 +86,7 @@ pub struct Config {
     pub llvm_targets: Option<String>,
     pub llvm_experimental_targets: String,
     pub llvm_link_jobs: Option<u32>,
+    pub llvm_version_suffix: Option<String>,
 
     pub lld_enabled: bool,
     pub lldb_enabled: bool,
@@ -256,6 +257,7 @@ struct Llvm {
     experimental_targets: Option<String>,
     link_jobs: Option<u32>,
     link_shared: Option<bool>,
+    version_suffix: Option<String>,
     clang_cl: Option<String>
 }
 
@@ -516,6 +518,7 @@ impl Config {
             config.llvm_experimental_targets = llvm.experimental_targets.clone()
                 .unwrap_or("WebAssembly;RISCV".to_string());
             config.llvm_link_jobs = llvm.link_jobs;
+            config.llvm_version_suffix = llvm.version_suffix.clone();
             config.llvm_clang_cl = llvm.clang_cl.clone();
         }
 
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index caf38d766f54e..828a7d14c0437 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -239,6 +239,10 @@ impl Step for Llvm {
             cfg.define("LLVM_NATIVE_BUILD", builder.llvm_out(builder.config.build).join("build"));
         }
 
+        if let Some(ref suffix) = builder.config.llvm_version_suffix {
+            cfg.define("LLVM_VERSION_SUFFIX", suffix);
+        }
+
         if let Some(ref python) = builder.config.python {
             cfg.define("PYTHON_EXECUTABLE", python);
         }