about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-05-22 22:57:48 +0000
committerbors <bors@rust-lang.org>2019-05-22 22:57:48 +0000
commit11f01bfb9f79b569aee6ac724eea59c7105a7f19 (patch)
tree98c0858868a7f91e62eb087072cb4332a0fa0e18
parent37ff5d388f8c004ca248adb635f1cc84d347eda0 (diff)
parent68065173c72ae426fcae9a708cabb739eab8110a (diff)
downloadrust-11f01bfb9f79b569aee6ac724eea59c7105a7f19.tar.gz
rust-11f01bfb9f79b569aee6ac724eea59c7105a7f19.zip
Auto merge of #61044 - Centril:rollup-ztsgb9p, r=Centril
Rollup of 8 pull requests

Successful merges:

 - #60300 (Allow null-pointer-optimized enums in FFI if their underlying representation is FFI safe)
 - #60773 (Always try to project predicates when finding auto traits in rustdoc)
 - #60809 (Add FAQ for NLL migration)
 - #61023 (Migrate from recursion to iterate on qualify consts visitor impl)
 - #61029 (Simplify RefCell minimum_spanning_tree example)
 - #61030 (Make maybe_codegen_consume_direct iterate instead of doing recursion)
 - #61034 (rustc_metadata: parametrize schema::CrateRoot by 'tcx and rip out old unused incremental infra.)
 - #61037 (Update clippy submodule)

Failed merges:

r? @ghost
-rw-r--r--src/libcore/cell.rs46
-rw-r--r--src/libcore/num/mod.rs1
-rw-r--r--src/libcore/ptr.rs1
-rw-r--r--src/librustc/traits/auto_trait.rs85
-rw-r--r--src/librustc_codegen_ssa/mir/operand.rs70
-rw-r--r--src/librustc_lint/types.rs108
-rw-r--r--src/librustc_metadata/creader.rs6
-rw-r--r--src/librustc_metadata/cstore.rs6
-rw-r--r--src/librustc_metadata/cstore_impl.rs7
-rw-r--r--src/librustc_metadata/decoder.rs13
-rw-r--r--src/librustc_metadata/encoder.rs289
-rw-r--r--src/librustc_metadata/index.rs17
-rw-r--r--src/librustc_metadata/index_builder.rs224
-rw-r--r--src/librustc_metadata/isolated_encoder.rs48
-rw-r--r--src/librustc_metadata/lib.rs3
-rw-r--r--src/librustc_metadata/schema.rs209
-rw-r--r--src/librustc_mir/borrow_check/mod.rs5
-rw-r--r--src/librustc_mir/error_codes.rs32
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs94
-rw-r--r--src/libsyntax/feature_gate.rs7
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/test/rustdoc/issue-60726.rs35
-rw-r--r--src/test/ui/borrowck/borrowck-anon-fields-variant.stderr1
-rw-r--r--src/test/ui/borrowck/borrowck-describe-lvalue.stderr2
-rw-r--r--src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr1
-rw-r--r--src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr1
-rw-r--r--src/test/ui/borrowck/borrowck-mutate-in-guard.stderr2
-rw-r--r--src/test/ui/consts/const_let_refutable.stderr2
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr1
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr1
-rw-r--r--src/test/ui/empty/empty-never-array.stderr1
-rw-r--r--src/test/ui/feature-gates/feature-gate-nll.stderr1
-rw-r--r--src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs1
-rw-r--r--src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr11
-rw-r--r--src/test/ui/issues/issue-15381.stderr1
-rw-r--r--src/test/ui/issues/issue-40510-1.migrate.stderr1
-rw-r--r--src/test/ui/issues/issue-40510-3.migrate.stderr1
-rw-r--r--src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr3
-rw-r--r--src/test/ui/issues/issue-49824.stderr1
-rw-r--r--src/test/ui/lint/lint-ctypes-enum.rs33
-rw-r--r--src/test/ui/lint/lint-ctypes-enum.stderr42
-rw-r--r--src/test/ui/pattern/pattern-bindings-after-at.stderr1
-rw-r--r--src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr1
-rw-r--r--src/test/ui/thread-local-in-ctfe.stderr2
m---------src/tools/clippy20
45 files changed, 590 insertions, 848 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index fcfd80d9266..9672cf4ffed 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -67,16 +67,26 @@
 //! mutability:
 //!
 //! ```
+//! use std::cell::{RefCell, RefMut};
 //! use std::collections::HashMap;
-//! use std::cell::RefCell;
 //! use std::rc::Rc;
 //!
 //! fn main() {
 //!     let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
-//!     shared_map.borrow_mut().insert("africa", 92388);
-//!     shared_map.borrow_mut().insert("kyoto", 11837);
-//!     shared_map.borrow_mut().insert("piccadilly", 11826);
-//!     shared_map.borrow_mut().insert("marbles", 38);
+//!     // Create a new block to limit the scope of the dynamic borrow
+//!     {
+//!         let mut map: RefMut<_> = shared_map.borrow_mut();
+//!         map.insert("africa", 92388);
+//!         map.insert("kyoto", 11837);
+//!         map.insert("piccadilly", 11826);
+//!         map.insert("marbles", 38);
+//!     }
+//!
+//!     // Note that if we had not let the previous borrow of the cache fall out
+//!     // of scope then the subsequent borrow would cause a dynamic thread panic.
+//!     // This is the major hazard of using `RefCell`.
+//!     let total: i32 = shared_map.borrow().values().sum();
+//!     println!("{}", total);
 //! }
 //! ```
 //!
@@ -102,27 +112,15 @@
 //!
 //! impl Graph {
 //!     fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> {
-//!         // Create a new scope to contain the lifetime of the
-//!         // dynamic borrow
-//!         {
-//!             // Take a reference to the inside of cache cell
-//!             let mut cache = self.span_tree_cache.borrow_mut();
-//!             if cache.is_some() {
-//!                 return cache.as_ref().unwrap().clone();
-//!             }
-//!
-//!             let span_tree = self.calc_span_tree();
-//!             *cache = Some(span_tree);
-//!         }
+//!         self.span_tree_cache.borrow_mut()
+//!             .get_or_insert_with(|| self.calc_span_tree())
+//!             .clone()
+//!     }
 //!
-//!         // Recursive call to return the just-cached value.
-//!         // Note that if we had not let the previous borrow
-//!         // of the cache fall out of scope then the subsequent
-//!         // recursive borrow would cause a dynamic thread panic.
-//!         // This is the major hazard of using `RefCell`.
-//!         self.minimum_spanning_tree()
+//!     fn calc_span_tree(&self) -> Vec<(i32, i32)> {
+//!         // Expensive computation goes here
+//!         vec![]
 //!     }
-//! #   fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] }
 //! }
 //! ```
 //!
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 562a7a4b3c7..932c0eaa4c7 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -50,6 +50,7 @@ assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", s
                 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
                 #[repr(transparent)]
                 #[rustc_layout_scalar_valid_range_start(1)]
+                #[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
                 pub struct $Ty($Int);
             }
 
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 006b1e143ee..4bb4d3ee466 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2938,6 +2938,7 @@ impl<'a, T: ?Sized> From<NonNull<T>> for Unique<T> {
 #[stable(feature = "nonnull", since = "1.25.0")]
 #[repr(transparent)]
 #[rustc_layout_scalar_valid_range_start(1)]
+#[cfg_attr(not(stage0), rustc_nonnull_optimization_guaranteed)]
 pub struct NonNull<T: ?Sized> {
     pointer: *const T,
 }
diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs
index 57f5e239188..2fa896962da 100644
--- a/src/librustc/traits/auto_trait.rs
+++ b/src/librustc/traits/auto_trait.rs
@@ -700,22 +700,64 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                             }
                     }
 
-                    // We can only call poly_project_and_unify_type when our predicate's
-                    // Ty contains an inference variable - otherwise, there won't be anything to
-                    // unify
-                    if p.ty().skip_binder().has_infer_types() {
-                        debug!("Projecting and unifying projection predicate {:?}",
-                               predicate);
-                        match poly_project_and_unify_type(select, &obligation.with(p)) {
-                            Err(e) => {
-                                debug!(
-                                    "evaluate_nested_obligations: Unable to unify predicate \
-                                     '{:?}' '{:?}', bailing out",
-                                    ty, e
-                                );
-                                return false;
-                            }
-                            Ok(Some(v)) => {
+                    // There are three possible cases when we project a predicate:
+                    //
+                    // 1. We encounter an error. This means that it's impossible for
+                    // our current type to implement the auto trait - there's bound
+                    // that we could add to our ParamEnv that would 'fix' this kind
+                    // of error, as it's not caused by an unimplemented type.
+                    //
+                    // 2. We succesfully project the predicate (Ok(Some(_))), generating
+                    //  some subobligations. We then process these subobligations
+                    //  like any other generated sub-obligations.
+                    //
+                    // 3. We receieve an 'ambiguous' result (Ok(None))
+                    // If we were actually trying to compile a crate,
+                    // we would need to re-process this obligation later.
+                    // However, all we care about is finding out what bounds
+                    // are needed for our type to implement a particular auto trait.
+                    // We've already added this obligation to our computed ParamEnv
+                    // above (if it was necessary). Therefore, we don't need
+                    // to do any further processing of the obligation.
+                    //
+                    // Note that we *must* try to project *all* projection predicates
+                    // we encounter, even ones without inference variable.
+                    // This ensures that we detect any projection errors,
+                    // which indicate that our type can *never* implement the given
+                    // auto trait. In that case, we will generate an explicit negative
+                    // impl (e.g. 'impl !Send for MyType'). However, we don't
+                    // try to process any of the generated subobligations -
+                    // they contain no new information, since we already know
+                    // that our type implements the projected-through trait,
+                    // and can lead to weird region issues.
+                    //
+                    // Normally, we'll generate a negative impl as a result of encountering
+                    // a type with an explicit negative impl of an auto trait
+                    // (for example, raw pointers have !Send and !Sync impls)
+                    // However, through some **interesting** manipulations of the type
+                    // system, it's actually possible to write a type that never
+                    // implements an auto trait due to a projection error, not a normal
+                    // negative impl error. To properly handle this case, we need
+                    // to ensure that we catch any potential projection errors,
+                    // and turn them into an explicit negative impl for our type.
+                    debug!("Projecting and unifying projection predicate {:?}",
+                           predicate);
+
+                    match poly_project_and_unify_type(select, &obligation.with(p)) {
+                        Err(e) => {
+                            debug!(
+                                "evaluate_nested_obligations: Unable to unify predicate \
+                                 '{:?}' '{:?}', bailing out",
+                                ty, e
+                            );
+                            return false;
+                        }
+                        Ok(Some(v)) => {
+                            // We only care about sub-obligations
+                            // when we started out trying to unify
+                            // some inference variables. See the comment above
+                            // for more infomration
+                            if p.ty().skip_binder().has_infer_types() {
                                 if !self.evaluate_nested_obligations(
                                     ty,
                                     v.clone().iter().cloned(),
@@ -728,7 +770,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
                                     return false;
                                 }
                             }
-                            Ok(None) => {
+                        }
+                        Ok(None) => {
+                            // It's ok not to make progress when hvave no inference variables -
+                            // in that case, we were only performing unifcation to check if an
+                            // error occured (which would indicate that it's impossible for our
+                            // type to implement the auto trait).
+                            // However, we should always make progress (either by generating
+                            // subobligations or getting an error) when we started off with
+                            // inference variables
+                            if p.ty().skip_binder().has_infer_types() {
                                 panic!("Unexpected result when selecting {:?} {:?}", ty, obligation)
                             }
                         }
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 3b8e5b44953..3db05b7214d 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -380,45 +380,47 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     ) -> Option<OperandRef<'tcx, Bx::Value>> {
         debug!("maybe_codegen_consume_direct(place={:?})", place);
 
-        // watch out for locals that do not have an
-        // alloca; they are handled somewhat differently
-        if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
-            match self.locals[index] {
-                LocalRef::Operand(Some(o)) => {
-                    return Some(o);
-                }
-                LocalRef::Operand(None) => {
-                    bug!("use of {:?} before def", place);
-                }
-                LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
-                    // use path below
-                }
-            }
-        }
+        place.iterate(|place_base, place_projection| {
+            if let mir::PlaceBase::Local(index) = place_base {
+                match self.locals[*index] {
+                    LocalRef::Operand(Some(mut o)) => {
+                        // Moves out of scalar and scalar pair fields are trivial.
+                        for proj in place_projection {
+                            match proj.elem {
+                                mir::ProjectionElem::Field(ref f, _) => {
+                                    o = o.extract_field(bx, f.index());
+                                }
+                                mir::ProjectionElem::Index(_) |
+                                mir::ProjectionElem::ConstantIndex { .. } => {
+                                    // ZSTs don't require any actual memory access.
+                                    // FIXME(eddyb) deduplicate this with the identical
+                                    // checks in `codegen_consume` and `extract_field`.
+                                    let elem = o.layout.field(bx.cx(), 0);
+                                    if elem.is_zst() {
+                                        o = OperandRef::new_zst(bx, elem);
+                                    } else {
+                                        return None;
+                                    }
+                                }
+                                _ => return None,
+                            }
+                        }
 
-        // Moves out of scalar and scalar pair fields are trivial.
-        if let &mir::Place::Projection(ref proj) = place {
-            if let Some(o) = self.maybe_codegen_consume_direct(bx, &proj.base) {
-                match proj.elem {
-                    mir::ProjectionElem::Field(ref f, _) => {
-                        return Some(o.extract_field(bx, f.index()));
+                        Some(o)
                     }
-                    mir::ProjectionElem::Index(_) |
-                    mir::ProjectionElem::ConstantIndex { .. } => {
-                        // ZSTs don't require any actual memory access.
-                        // FIXME(eddyb) deduplicate this with the identical
-                        // checks in `codegen_consume` and `extract_field`.
-                        let elem = o.layout.field(bx.cx(), 0);
-                        if elem.is_zst() {
-                            return Some(OperandRef::new_zst(bx, elem));
-                        }
+                    LocalRef::Operand(None) => {
+                        bug!("use of {:?} before def", place);
+                    }
+                    LocalRef::Place(..) | LocalRef::UnsizedPlace(..) => {
+                        // watch out for locals that do not have an
+                        // alloca; they are handled somewhat differently
+                        None
                     }
-                    _ => {}
                 }
+            } else {
+                None
             }
-        }
-
-        None
+        })
     }
 
     pub fn codegen_consume(
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 38b6e2c1979..ac18e131c4a 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -1,10 +1,11 @@
 #![allow(non_snake_case)]
 
 use rustc::hir::{ExprKind, Node};
+use crate::hir::def_id::DefId;
 use rustc::hir::lowering::is_range_literal;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
-use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx};
+use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx, SizeSkeleton};
 use rustc::{lint, util};
 use rustc_data_structures::indexed_vec::Idx;
 use util::nodemap::FxHashSet;
@@ -14,11 +15,11 @@ use lint::{LintPass, LateLintPass};
 use std::cmp;
 use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 
-use syntax::{ast, attr};
+use syntax::{ast, attr, source_map};
 use syntax::errors::Applicability;
+use syntax::symbol::sym;
 use rustc_target::spec::abi::Abi;
 use syntax_pos::Span;
-use syntax::source_map;
 
 use rustc::hir;
 
@@ -522,42 +523,79 @@ enum FfiResult<'tcx> {
     },
 }
 
+fn is_zst<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId, ty: Ty<'tcx>) -> bool {
+    tcx.layout_of(tcx.param_env(did).and(ty)).map(|layout| layout.is_zst()).unwrap_or(false)
+}
+
+fn ty_is_known_nonnull<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
+    match ty.sty {
+        ty::FnPtr(_) => true,
+        ty::Ref(..) => true,
+        ty::Adt(field_def, substs) if field_def.repr.transparent() && field_def.is_struct() => {
+            for field in &field_def.non_enum_variant().fields {
+                let field_ty = tcx.normalize_erasing_regions(
+                    ParamEnv::reveal_all(),
+                    field.ty(tcx, substs),
+                );
+                if is_zst(tcx, field.did, field_ty) {
+                    continue;
+                }
+
+                let attrs = tcx.get_attrs(field_def.did);
+                if attrs.iter().any(|a| a.check_name(sym::rustc_nonnull_optimization_guaranteed)) ||
+                    ty_is_known_nonnull(tcx, field_ty) {
+                    return true;
+                }
+            }
+
+            false
+        }
+        _ => false,
+    }
+}
+
 /// Check if this enum can be safely exported based on the
 /// "nullable pointer optimization". Currently restricted
-/// to function pointers and references, but could be
-/// expanded to cover NonZero raw pointers and newtypes.
+/// to function pointers, references, core::num::NonZero*,
+/// core::ptr::NonNull, and #[repr(transparent)] newtypes.
 /// FIXME: This duplicates code in codegen.
 fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  def: &'tcx ty::AdtDef,
+                                  ty: Ty<'tcx>,
+                                  ty_def: &'tcx ty::AdtDef,
                                   substs: SubstsRef<'tcx>)
                                   -> bool {
-    if def.variants.len() == 2 {
-        let data_idx;
+    if ty_def.variants.len() != 2 {
+        return false;
+    }
 
-        let zero = VariantIdx::new(0);
-        let one = VariantIdx::new(1);
+    let get_variant_fields = |index| &ty_def.variants[VariantIdx::new(index)].fields;
+    let variant_fields = [get_variant_fields(0), get_variant_fields(1)];
+    let fields = if variant_fields[0].is_empty() {
+        &variant_fields[1]
+    } else if variant_fields[1].is_empty() {
+        &variant_fields[0]
+    } else {
+        return false;
+    };
 
-        if def.variants[zero].fields.is_empty() {
-            data_idx = one;
-        } else if def.variants[one].fields.is_empty() {
-            data_idx = zero;
-        } else {
-            return false;
-        }
+    if fields.len() != 1 {
+        return false;
+    }
 
-        if def.variants[data_idx].fields.len() == 1 {
-            match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
-                ty::FnPtr(_) => {
-                    return true;
-                }
-                ty::Ref(..) => {
-                    return true;
-                }
-                _ => {}
-            }
-        }
+    let field_ty = fields[0].ty(tcx, substs);
+    if !ty_is_known_nonnull(tcx, field_ty) {
+        return false;
     }
-    false
+
+    // At this point, the field's type is known to be nonnull and the parent enum is Option-like.
+    // If the computed size for the field and the enum are different, the nonnull optimization isn't
+    // being applied (and we've got a problem somewhere).
+    let compute_size_skeleton = |t| SizeSkeleton::compute(t, tcx, ParamEnv::reveal_all()).unwrap();
+    if !compute_size_skeleton(ty).same_size(compute_size_skeleton(field_ty)) {
+        bug!("improper_ctypes: Option nonnull optimization not applied?");
+    }
+
+    true
 }
 
 impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
@@ -612,14 +650,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                             );
                             // repr(transparent) types are allowed to have arbitrary ZSTs, not just
                             // PhantomData -- skip checking all ZST fields
-                            if def.repr.transparent() {
-                                let is_zst = cx
-                                    .layout_of(cx.param_env(field.did).and(field_ty))
-                                    .map(|layout| layout.is_zst())
-                                    .unwrap_or(false);
-                                if is_zst {
-                                    continue;
-                                }
+                            if def.repr.transparent() && is_zst(cx, field.did, field_ty) {
+                                continue;
                             }
                             let r = self.check_type_for_ffi(cache, field_ty);
                             match r {
@@ -682,7 +714,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                         // discriminant.
                         if !def.repr.c() && def.repr.int.is_none() {
                             // Special-case types like `Option<extern fn()>`.
-                            if !is_repr_nullable_ptr(cx, def, substs) {
+                            if !is_repr_nullable_ptr(cx, ty, def, substs) {
                                 return FfiUnsafe {
                                     ty: ty,
                                     reason: "enum has no representation hint",
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 3e00ba3c620..991bebc647d 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -162,7 +162,7 @@ impl<'a> CrateLoader<'a> {
 
     fn verify_no_symbol_conflicts(&self,
                                   span: Span,
-                                  root: &CrateRoot) {
+                                  root: &CrateRoot<'_>) {
         // Check for (potential) conflicts with the local crate
         if self.local_crate_name == root.name &&
            self.sess.local_crate_disambiguator() == root.disambiguator {
@@ -476,7 +476,7 @@ impl<'a> CrateLoader<'a> {
     // Go through the crate metadata and load any crates that it references
     fn resolve_crate_deps(&mut self,
                           root: &Option<CratePaths>,
-                          crate_root: &CrateRoot,
+                          crate_root: &CrateRoot<'_>,
                           metadata: &MetadataBlob,
                           krate: CrateNum,
                           span: Span,
@@ -582,7 +582,7 @@ impl<'a> CrateLoader<'a> {
     /// implemented as dynamic libraries, but we have a possible future where
     /// custom derive (and other macro-1.1 style features) are implemented via
     /// executables and custom IPC.
-    fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option<PathBuf>, span: Span)
+    fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option<PathBuf>, span: Span)
                           -> Vec<(ast::Name, Lrc<SyntaxExtension>)> {
         use std::{env, mem};
         use crate::dynamic_lib::DynamicLibrary;
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 22a13f37722..5d8fabc7e69 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -64,7 +64,11 @@ pub struct CrateMetadata {
     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
     pub alloc_decoding_state: AllocDecodingState,
 
-    pub root: schema::CrateRoot,
+    // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
+    // lifetime is only used behind `Lazy` / `LazySeq`, and therefore
+    // acts like an universal (`for<'tcx>`), that is paired up with
+    // whichever `TyCtxt` is being used to decode those values.
+    pub root: schema::CrateRoot<'static>,
 
     /// For each public item in this crate, we encode a key. When the
     /// crate is loaded, we read all the keys and put them in this
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 2070a38b7b8..49f93c4014d 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -246,12 +246,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
 
     used_crate_source => { Lrc::new(cdata.source.clone()) }
 
-    exported_symbols => {
-        let cnum = cdata.cnum;
-        assert!(cnum != LOCAL_CRATE);
-
-        Arc::new(cdata.exported_symbols(tcx))
-    }
+    exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) }
 }
 
 pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index d2ba82b5a1c..a89cfe42eaa 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -365,7 +365,7 @@ for DecodeContext<'a, 'tcx> {
 
 implement_ty_decoder!( DecodeContext<'a, 'tcx> );
 
-impl<'a, 'tcx> MetadataBlob {
+impl<'tcx> MetadataBlob {
     pub fn is_compatible(&self) -> bool {
         self.raw_bytes().starts_with(METADATA_HEADER)
     }
@@ -374,7 +374,7 @@ impl<'a, 'tcx> MetadataBlob {
         Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
     }
 
-    pub fn get_root(&self) -> CrateRoot {
+    pub fn get_root(&self) -> CrateRoot<'tcx> {
         let slice = self.raw_bytes();
         let offset = METADATA_HEADER.len();
         let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) |
@@ -444,7 +444,7 @@ impl<'tcx> EntryKind<'tcx> {
 ///  |- proc macro #0 (DefIndex 1:N)
 ///  |- proc macro #1 (DefIndex 1:N+1)
 ///  \- ...
-crate fn proc_macro_def_path_table(crate_root: &CrateRoot,
+crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>,
                                    proc_macros: &[(ast::Name, Lrc<SyntaxExtension>)])
                                    -> DefPathTable
 {
@@ -475,7 +475,7 @@ impl<'a, 'tcx> CrateMetadata {
 
     fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
         assert!(!self.is_proc_macro(item_id));
-        self.root.index.lookup(self.blob.raw_bytes(), item_id)
+        self.root.entries_index.lookup(self.blob.raw_bytes(), item_id)
     }
 
     fn entry(&self, item_id: DefIndex) -> Entry<'tcx> {
@@ -1126,10 +1126,7 @@ impl<'a, 'tcx> CrateMetadata {
             // link those in so we skip those crates.
             vec![]
         } else {
-            let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> =
-                LazySeq::with_position_and_length(self.root.exported_symbols.position,
-                                                  self.root.exported_symbols.len);
-            lazy_seq.decode((self, tcx)).collect()
+            self.root.exported_symbols.decode((self, tcx)).collect()
         }
     }
 
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 7f0993e799f..6711e54053a 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1,6 +1,4 @@
 use crate::index::Index;
-use crate::index_builder::{FromId, IndexBuilder, Untracked};
-use crate::isolated_encoder::IsolatedEncoder;
 use crate::schema::*;
 
 use rustc::middle::cstore::{LinkagePreference, NativeLibrary,
@@ -46,6 +44,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
     opaque: opaque::Encoder,
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
+    entries_index: Index<'tcx>,
+
     lazy_state: LazyState,
     type_shorthands: FxHashMap<Ty<'tcx>, usize>,
     predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
@@ -300,28 +300,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         })
     }
 
-    // Encodes something that corresponds to a single DepNode::GlobalMetaData
-    // and registers the Fingerprint in the `metadata_hashes` map.
-    pub fn tracked<'x, DATA, R>(&'x mut self,
-                                op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R,
-                                data: DATA)
-                                -> R {
-        op(&mut IsolatedEncoder::new(self), data)
+    /// Emit the data for a `DefId` to the metadata. The function to
+    /// emit the data is `op`, and it will be given `data` as
+    /// arguments. This `record` function will call `op` to generate
+    /// the `Entry` (which may point to other encoded information)
+    /// and will then record the `Lazy<Entry>` for use in the index.
+    // FIXME(eddyb) remove this.
+    pub fn record<DATA>(&mut self,
+                        id: DefId,
+                        op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>,
+                        data: DATA)
+    {
+        assert!(id.is_local());
+
+        let entry = op(self, data);
+        let entry = self.lazy(&entry);
+        self.entries_index.record(id, entry);
     }
 
-    fn encode_info_for_items(&mut self) -> Index {
+    fn encode_info_for_items(&mut self) {
         let krate = self.tcx.hir().krate();
-        let mut index = IndexBuilder::new(self);
         let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public };
-        index.record(DefId::local(CRATE_DEF_INDEX),
-                     IsolatedEncoder::encode_info_for_mod,
-                     FromId(hir::CRATE_HIR_ID, (&krate.module, &krate.attrs, &vis)));
-        let mut visitor = EncodeVisitor { index };
-        krate.visit_all_item_likes(&mut visitor.as_deep_visitor());
+        self.record(DefId::local(CRATE_DEF_INDEX),
+                     EncodeContext::encode_info_for_mod,
+                     (hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis));
+        krate.visit_all_item_likes(&mut self.as_deep_visitor());
         for macro_def in &krate.exported_macros {
-            visitor.visit_macro_def(macro_def);
+            self.visit_macro_def(macro_def);
         }
-        visitor.index.into_items()
     }
 
     fn encode_def_path_table(&mut self) -> Lazy<DefPathTable> {
@@ -371,38 +377,30 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         self.lazy_seq_ref(adapted.iter().map(|rc| &**rc))
     }
 
-    fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
+    fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
         let mut i = self.position();
 
-        let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ());
-        let dylib_dependency_formats = self.tracked(
-            IsolatedEncoder::encode_dylib_dependency_formats,
-            ());
+        let crate_deps = self.encode_crate_deps();
+        let dylib_dependency_formats = self.encode_dylib_dependency_formats();
         let dep_bytes = self.position() - i;
 
         // Encode the lib features.
         i = self.position();
-        let lib_features = self.tracked(IsolatedEncoder::encode_lib_features, ());
+        let lib_features = self.encode_lib_features();
         let lib_feature_bytes = self.position() - i;
 
         // Encode the language items.
         i = self.position();
-        let lang_items = self.tracked(IsolatedEncoder::encode_lang_items, ());
-        let lang_items_missing = self.tracked(
-            IsolatedEncoder::encode_lang_items_missing,
-            ());
+        let lang_items = self.encode_lang_items();
+        let lang_items_missing = self.encode_lang_items_missing();
         let lang_item_bytes = self.position() - i;
 
         // Encode the native libraries used
         i = self.position();
-        let native_libraries = self.tracked(
-            IsolatedEncoder::encode_native_libraries,
-            ());
+        let native_libraries = self.encode_native_libraries();
         let native_lib_bytes = self.position() - i;
 
-        let foreign_modules = self.tracked(
-            IsolatedEncoder::encode_foreign_modules,
-            ());
+        let foreign_modules = self.encode_foreign_modules();
 
         // Encode source_map
         i = self.position();
@@ -416,22 +414,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         // Encode the def IDs of impls, for coherence checking.
         i = self.position();
-        let impls = self.tracked(IsolatedEncoder::encode_impls, ());
+        let impls = self.encode_impls();
         let impl_bytes = self.position() - i;
 
         // Encode exported symbols info.
         i = self.position();
         let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
-        let exported_symbols = self.tracked(
-            IsolatedEncoder::encode_exported_symbols,
-            &exported_symbols);
+        let exported_symbols = self.encode_exported_symbols(&exported_symbols);
         let exported_symbols_bytes = self.position() - i;
 
         let tcx = self.tcx;
 
         // Encode the items.
         i = self.position();
-        let items = self.encode_info_for_items();
+        self.encode_info_for_items();
         let item_bytes = self.position() - i;
 
         // Encode the allocation index
@@ -462,10 +458,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             self.lazy_seq(interpret_alloc_index)
         };
 
-        // Index the items
         i = self.position();
-        let index = items.write_index(&mut self.opaque);
-        let index_bytes = self.position() - i;
+        let entries_index = self.entries_index.write_index(&mut self.opaque);
+        let entries_index_bytes = self.position() - i;
 
         let attrs = tcx.hir().krate_attrs();
         let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro);
@@ -516,7 +511,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             impls,
             exported_symbols,
             interpret_alloc_index,
-            index,
+            entries_index,
         });
 
         let total_bytes = self.position();
@@ -539,7 +534,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
             println!("    exp. symbols bytes: {}", exported_symbols_bytes);
             println!("  def-path table bytes: {}", def_path_table_bytes);
             println!("            item bytes: {}", item_bytes);
-            println!("           index bytes: {}", index_bytes);
+            println!("   entries index bytes: {}", entries_index_bytes);
             println!("            zero bytes: {}", zero_bytes);
             println!("           total bytes: {}", total_bytes);
         }
@@ -548,40 +543,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
     }
 }
 
-// These are methods for encoding various things. They are meant to be used with
-// IndexBuilder::record() and EncodeContext::tracked(). They actually
-// would not have to be methods of IsolatedEncoder (free standing functions
-// taking IsolatedEncoder as first argument would be just fine) but by making
-// them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>`
-// clause again and again.
-impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
+impl EncodeContext<'_, 'tcx> {
     fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq<ty::Variance> {
-        debug!("IsolatedEncoder::encode_variances_of({:?})", def_id);
+        debug!("EncodeContext::encode_variances_of({:?})", def_id);
         let tcx = self.tcx;
-        self.lazy_seq_from_slice(&tcx.variances_of(def_id))
+        self.lazy_seq_ref(&tcx.variances_of(def_id)[..])
     }
 
     fn encode_item_type(&mut self, def_id: DefId) -> Lazy<Ty<'tcx>> {
         let tcx = self.tcx;
         let ty = tcx.type_of(def_id);
-        debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty);
+        debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty);
         self.lazy(&ty)
     }
 
-    /// Encode data for the given variant of the given ADT. The
-    /// index of the variant is untracked: this is ok because we
-    /// will have to lookup the adt-def by its id, and that gives us
-    /// the right to access any information in the adt-def (including,
-    /// e.g., the length of the various vectors).
     fn encode_enum_variant_info(
         &mut self,
-        (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
+        (enum_did, index): (DefId, VariantIdx),
     ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let def = tcx.adt_def(enum_did);
         let variant = &def.variants[index];
         let def_id = variant.def_id;
-        debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id);
+        debug!("EncodeContext::encode_enum_variant_info({:?})", def_id);
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -625,17 +609,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         }
     }
 
-    /// Encode the constructor for the given variant of the given ADT. See
-    /// `encode_enum_variant_info` for an explanation about why the index is untracked.
     fn encode_enum_variant_ctor(
         &mut self,
-        (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>),
+        (enum_did, index): (DefId, VariantIdx),
     ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let def = tcx.adt_def(enum_did);
         let variant = &def.variants[index];
         let def_id = variant.ctor_def_id.unwrap();
-        debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id);
+        debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id);
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
@@ -681,18 +663,17 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         }
     }
 
-    fn encode_info_for_mod(&mut self,
-                           FromId(id, (md, attrs, vis)): FromId<(&hir::Mod,
-                                                                 &[ast::Attribute],
-                                                                 &hir::Visibility)>)
-                           -> Entry<'tcx> {
+    fn encode_info_for_mod(
+        &mut self,
+        (id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility),
+    ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let def_id = tcx.hir().local_def_id_from_hir_id(id);
-        debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
 
         let data = ModData {
             reexports: match tcx.module_exports(def_id) {
-                Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()),
+                Some(ref exports) => self.lazy_seq_ref(&exports[..]),
                 _ => LazySeq::empty(),
             },
         };
@@ -719,23 +700,16 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         }
     }
 
-    /// Encode data for the given field of the given variant of the
-    /// given ADT. The indices of the variant/field are untracked:
-    /// this is ok because we will have to lookup the adt-def by its
-    /// id, and that gives us the right to access any information in
-    /// the adt-def (including, e.g., the length of the various
-    /// vectors).
-    fn encode_field(&mut self,
-                    (adt_def_id, Untracked((variant_index, field_index))): (DefId,
-                                                                            Untracked<(VariantIdx,
-                                                                                       usize)>))
-                    -> Entry<'tcx> {
+    fn encode_field(
+        &mut self,
+        (adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize),
+    ) -> Entry<'tcx> {
         let tcx = self.tcx;
         let variant = &tcx.adt_def(adt_def_id).variants[variant_index];
         let field = &variant.fields[field_index];
 
         let def_id = field.did;
-        debug!("IsolatedEncoder::encode_field({:?})", def_id);
+        debug!("EncodeContext::encode_field({:?})", def_id);
 
         let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap();
         let variant_data = tcx.hir().expect_variant_data(variant_id);
@@ -761,7 +735,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id);
+        debug!("EncodeContext::encode_struct_ctor({:?})", def_id);
         let tcx = self.tcx;
         let adt_def = tcx.adt_def(adt_def_id);
         let variant = adt_def.non_enum_variant();
@@ -821,25 +795,25 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     fn encode_generics(&mut self, def_id: DefId) -> Lazy<ty::Generics> {
-        debug!("IsolatedEncoder::encode_generics({:?})", def_id);
+        debug!("EncodeContext::encode_generics({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(tcx.generics_of(def_id))
     }
 
     fn encode_predicates(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
-        debug!("IsolatedEncoder::encode_predicates({:?})", def_id);
+        debug!("EncodeContext::encode_predicates({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(&tcx.predicates_of(def_id))
     }
 
     fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
-        debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id);
+        debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id);
         let tcx = self.tcx;
         self.lazy(&tcx.predicates_defined_on(def_id))
     }
 
     fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id);
         let tcx = self.tcx;
 
         let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -949,7 +923,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id);
         let tcx = self.tcx;
 
         let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap();
@@ -1064,7 +1038,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
     // Encodes the inherent implementations of a structure, enumeration, or trait.
     fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq<DefIndex> {
-        debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id);
+        debug!("EncodeContext::encode_inherent_implementations({:?})", def_id);
         let implementations = self.tcx.inherent_impls(def_id);
         if implementations.is_empty() {
             LazySeq::empty()
@@ -1077,12 +1051,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     fn encode_stability(&mut self, def_id: DefId) -> Option<Lazy<attr::Stability>> {
-        debug!("IsolatedEncoder::encode_stability({:?})", def_id);
+        debug!("EncodeContext::encode_stability({:?})", def_id);
         self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab))
     }
 
     fn encode_deprecation(&mut self, def_id: DefId) -> Option<Lazy<attr::Deprecation>> {
-        debug!("IsolatedEncoder::encode_deprecation({:?})", def_id);
+        debug!("EncodeContext::encode_deprecation({:?})", def_id);
         self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr))
     }
 
@@ -1096,7 +1070,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_item({:?})", def_id);
 
         let kind = match item.node {
             hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic,
@@ -1118,7 +1092,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 EntryKind::Fn(self.lazy(&data))
             }
             hir::ItemKind::Mod(ref m) => {
-                return self.encode_info_for_mod(FromId(item.hir_id, (m, &item.attrs, &item.vis)));
+                return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis));
             }
             hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod,
             hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm,
@@ -1391,9 +1365,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
     fn encode_info_for_ty_param(
         &mut self,
-        (def_id, Untracked(encode_type)): (DefId, Untracked<bool>),
+        (def_id, encode_type): (DefId, bool),
     ) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id);
         self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type)
     }
 
@@ -1401,12 +1375,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         &mut self,
         def_id: DefId,
     ) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_const_param({:?})", def_id);
         self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true)
     }
 
     fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_closure({:?})", def_id);
         let tcx = self.tcx;
 
         let tables = self.tcx.typeck_tables_of(def_id);
@@ -1450,7 +1424,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> {
-        debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id);
         let tcx = self.tcx;
         let id = tcx.hir().as_local_hir_id(def_id).unwrap();
         let body_id = tcx.hir().body_owned_by(id);
@@ -1478,23 +1452,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 
     fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq<ast::Attribute> {
-        // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because
-        //       we rely on the HashStable specialization for [Attribute]
-        //       to properly filter things out.
-        self.lazy_seq_from_slice(attrs)
+        self.lazy_seq_ref(attrs)
     }
 
-    fn encode_native_libraries(&mut self, _: ()) -> LazySeq<NativeLibrary> {
+    fn encode_native_libraries(&mut self) -> LazySeq<NativeLibrary> {
         let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
         self.lazy_seq(used_libraries.iter().cloned())
     }
 
-    fn encode_foreign_modules(&mut self, _: ()) -> LazySeq<ForeignModule> {
+    fn encode_foreign_modules(&mut self) -> LazySeq<ForeignModule> {
         let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
         self.lazy_seq(foreign_modules.iter().cloned())
     }
 
-    fn encode_crate_deps(&mut self, _: ()) -> LazySeq<CrateDep> {
+    fn encode_crate_deps(&mut self) -> LazySeq<CrateDep> {
         let crates = self.tcx.crates();
 
         let mut deps = crates
@@ -1528,13 +1499,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep))
     }
 
-    fn encode_lib_features(&mut self, _: ()) -> LazySeq<(ast::Name, Option<ast::Name>)> {
+    fn encode_lib_features(&mut self) -> LazySeq<(ast::Name, Option<ast::Name>)> {
         let tcx = self.tcx;
         let lib_features = tcx.lib_features();
         self.lazy_seq(lib_features.to_vec())
     }
 
-    fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> {
+    fn encode_lang_items(&mut self) -> LazySeq<(DefIndex, usize)> {
         let tcx = self.tcx;
         let lang_items = tcx.lang_items();
         let lang_items = lang_items.items().iter();
@@ -1548,14 +1519,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
         }))
     }
 
-    fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq<lang_items::LangItem> {
+    fn encode_lang_items_missing(&mut self) -> LazySeq<lang_items::LangItem> {
         let tcx = self.tcx;
         self.lazy_seq_ref(&tcx.lang_items().missing)
     }
 
     /// Encodes an index, mapping each trait to its (local) implementations.
-    fn encode_impls(&mut self, _: ()) -> LazySeq<TraitImpls> {
-        debug!("IsolatedEncoder::encode_impls()");
+    fn encode_impls(&mut self) -> LazySeq<TraitImpls> {
+        debug!("EncodeContext::encode_impls()");
         let tcx = self.tcx;
         let mut visitor = ImplVisitor {
             tcx,
@@ -1580,12 +1551,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
                 TraitImpls {
                     trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
-                    impls: self.lazy_seq_from_slice(&impls[..]),
+                    impls: self.lazy_seq_ref(&impls),
                 }
             })
             .collect();
 
-        self.lazy_seq_from_slice(&all_impls[..])
+        self.lazy_seq_ref(&all_impls)
     }
 
     // Encodes all symbols exported from this crate into the metadata.
@@ -1595,13 +1566,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     // symbol associated with them (they weren't translated) or if they're an FFI
     // definition (as that's not defined in this crate).
     fn encode_exported_symbols(&mut self,
-                               exported_symbols: &[(ExportedSymbol<'_>, SymbolExportLevel)])
-                               -> EncodedExportedSymbols {
+                               exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)])
+                               -> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
         // The metadata symbol name is special. It should not show up in
         // downstream crates.
         let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
 
-        let lazy_seq = self.lazy_seq(exported_symbols
+        self.lazy_seq(exported_symbols
             .iter()
             .filter(|&&(ref exported_symbol, _)| {
                 match *exported_symbol {
@@ -1611,15 +1582,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     _ => true,
                 }
             })
-            .cloned());
-
-        EncodedExportedSymbols {
-            len: lazy_seq.len,
-            position: lazy_seq.position,
-        }
+            .cloned())
     }
 
-    fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
+    fn encode_dylib_dependency_formats(&mut self) -> LazySeq<Option<LinkagePreference>> {
         match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) {
             Some(arr) => {
                 self.lazy_seq(arr.iter().map(|slot| {
@@ -1641,7 +1607,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                                     -> Entry<'tcx> {
         let tcx = self.tcx;
 
-        debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id);
+        debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id);
 
         let kind = match nitem.node {
             hir::ForeignItemKind::Fn(_, ref names, _) => {
@@ -1681,33 +1647,29 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
     }
 }
 
-struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> {
-    index: IndexBuilder<'a, 'b, 'tcx>,
-}
-
-impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
+impl Visitor<'tcx> for EncodeContext<'_, 'tcx> {
     fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
-        NestedVisitorMap::OnlyBodies(&self.index.tcx.hir())
+        NestedVisitorMap::OnlyBodies(&self.tcx.hir())
     }
     fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
         intravisit::walk_expr(self, ex);
-        self.index.encode_info_for_expr(ex);
+        self.encode_info_for_expr(ex);
     }
     fn visit_item(&mut self, item: &'tcx hir::Item) {
         intravisit::walk_item(self, item);
-        let def_id = self.index.tcx.hir().local_def_id_from_hir_id(item.hir_id);
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id);
         match item.node {
             hir::ItemKind::ExternCrate(_) |
-            hir::ItemKind::Use(..) => (), // ignore these
-            _ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)),
+            hir::ItemKind::Use(..) => {} // ignore these
+            _ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
         }
-        self.index.encode_addl_info_for_item(item);
+        self.encode_addl_info_for_item(item);
     }
     fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) {
         intravisit::walk_foreign_item(self, ni);
-        let def_id = self.index.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
-        self.index.record(def_id,
-                          IsolatedEncoder::encode_info_for_foreign_item,
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id);
+        self.record(def_id,
+                          EncodeContext::encode_info_for_foreign_item,
                           (def_id, ni));
     }
     fn visit_variant(&mut self,
@@ -1717,32 +1679,32 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> {
         intravisit::walk_variant(self, v, g, id);
 
         if let Some(ref discr) = v.node.disr_expr {
-            let def_id = self.index.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
-            self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
+            let def_id = self.tcx.hir().local_def_id_from_hir_id(discr.hir_id);
+            self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
         }
     }
     fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
         intravisit::walk_generics(self, generics);
-        self.index.encode_info_for_generics(generics);
+        self.encode_info_for_generics(generics);
     }
     fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
         intravisit::walk_ty(self, ty);
-        self.index.encode_info_for_ty(ty);
+        self.encode_info_for_ty(ty);
     }
     fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) {
-        let def_id = self.index.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id);
-        self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def);
+        let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id);
+        self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def);
     }
 }
 
-impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
+impl EncodeContext<'_, 'tcx> {
     fn encode_fields(&mut self, adt_def_id: DefId) {
         let def = self.tcx.adt_def(adt_def_id);
         for (variant_index, variant) in def.variants.iter_enumerated() {
             for (field_index, field) in variant.fields.iter().enumerate() {
                 self.record(field.did,
-                            IsolatedEncoder::encode_field,
-                            (adt_def_id, Untracked((variant_index, field_index))));
+                            EncodeContext::encode_field,
+                            (adt_def_id, variant_index, field_index));
             }
         }
     }
@@ -1755,12 +1717,12 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
                 GenericParamKind::Type { ref default, .. } => {
                     self.record(
                         def_id,
-                        IsolatedEncoder::encode_info_for_ty_param,
-                        (def_id, Untracked(default.is_some())),
+                        EncodeContext::encode_info_for_ty_param,
+                        (def_id, default.is_some()),
                     );
                 }
                 GenericParamKind::Const { .. } => {
-                    self.record(def_id, IsolatedEncoder::encode_info_for_const_param, def_id);
+                    self.record(def_id, EncodeContext::encode_info_for_const_param, def_id);
                 }
             }
         }
@@ -1770,7 +1732,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
         match ty.node {
             hir::TyKind::Array(_, ref length) => {
                 let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id);
-                self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id);
+                self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id);
             }
             _ => {}
         }
@@ -1780,7 +1742,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
         match expr.node {
             hir::ExprKind::Closure(..) => {
                 let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
-                self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id);
+                self.record(def_id, EncodeContext::encode_info_for_closure, def_id);
             }
             _ => {}
         }
@@ -1812,13 +1774,13 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
                 let def = self.tcx.adt_def(def_id);
                 for (i, variant) in def.variants.iter_enumerated() {
                     self.record(variant.def_id,
-                                IsolatedEncoder::encode_enum_variant_info,
-                                (def_id, Untracked(i)));
+                                EncodeContext::encode_enum_variant_info,
+                                (def_id, i));
 
                     if let Some(ctor_def_id) = variant.ctor_def_id {
                         self.record(ctor_def_id,
-                                    IsolatedEncoder::encode_enum_variant_ctor,
-                                    (def_id, Untracked(i)));
+                                    EncodeContext::encode_enum_variant_ctor,
+                                    (def_id, i));
                     }
                 }
             }
@@ -1829,7 +1791,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
                 if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
                     let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id);
                     self.record(ctor_def_id,
-                                IsolatedEncoder::encode_struct_ctor,
+                                EncodeContext::encode_struct_ctor,
                                 (def_id, ctor_def_id));
                 }
             }
@@ -1839,14 +1801,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
             hir::ItemKind::Impl(..) => {
                 for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(trait_item_def_id,
-                                IsolatedEncoder::encode_info_for_impl_item,
+                                EncodeContext::encode_info_for_impl_item,
                                 trait_item_def_id);
                 }
             }
             hir::ItemKind::Trait(..) => {
                 for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(item_def_id,
-                                IsolatedEncoder::encode_info_for_trait_item,
+                                EncodeContext::encode_info_for_trait_item,
                                 item_def_id);
                 }
             }
@@ -1911,10 +1873,13 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
     // Will be filled with the root position after encoding everything.
     encoder.emit_raw_bytes(&[0, 0, 0, 0]);
 
-    let (root, mut result) = {
+    // Since encoding metadata is not in a query, and nothing is cached,
+    // there's no need to do dep-graph tracking for any of it.
+    let (root, mut result) = tcx.dep_graph.with_ignore(move || {
         let mut ecx = EncodeContext {
             opaque: encoder,
             tcx,
+            entries_index: Index::new(tcx.hir().definitions().def_index_count()),
             lazy_state: LazyState::NoNode,
             type_shorthands: Default::default(),
             predicate_shorthands: Default::default(),
@@ -1930,7 +1895,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
         // culminating in the `CrateRoot` which points to all of it.
         let root = ecx.encode_crate_root();
         (root, ecx.opaque.into_inner())
-    };
+    });
 
     // Encode the root position.
     let header = METADATA_HEADER.len();
diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs
index 934e871559c..dd2f59922ef 100644
--- a/src/librustc_metadata/index.rs
+++ b/src/librustc_metadata/index.rs
@@ -2,6 +2,7 @@ use crate::schema::*;
 
 use rustc::hir::def_id::{DefId, DefIndex};
 use rustc_serialize::opaque::Encoder;
+use std::marker::PhantomData;
 use std::u32;
 use log::debug;
 
@@ -74,23 +75,25 @@ impl FixedSizeEncoding for u32 {
 /// `u32::MAX`. Whenever an index is visited, we fill in the
 /// appropriate spot by calling `record_position`. We should never
 /// visit the same index twice.
-pub struct Index {
+pub struct Index<'tcx> {
     positions: Vec<u8>,
+    _marker: PhantomData<&'tcx ()>,
 }
 
-impl Index {
-    pub fn new(max_index: usize) -> Index {
+impl Index<'tcx> {
+    pub fn new(max_index: usize) -> Self {
         Index {
             positions: vec![0xff; max_index * 4],
+            _marker: PhantomData,
         }
     }
 
-    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'_>>) {
+    pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry<'tcx>>) {
         assert!(def_id.is_local());
         self.record_index(def_id.index, entry);
     }
 
-    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'_>>) {
+    pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry<'tcx>>) {
         assert!(entry.position < (u32::MAX as usize));
         let position = entry.position as u32;
         let array_index = item.index();
@@ -105,7 +108,7 @@ impl Index {
         position.write_to_bytes_at(positions, array_index)
     }
 
-    pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Index> {
+    pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Self> {
         let pos = buf.position();
 
         // First we write the length of the lower range ...
@@ -116,7 +119,7 @@ impl Index {
     }
 }
 
-impl<'tcx> LazySeq<Index> {
+impl LazySeq<Index<'tcx>> {
     /// Given the metadata, extract out the offset of a particular
     /// DefIndex (if any).
     #[inline(never)]
diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs
deleted file mode 100644
index e780693a5a9..00000000000
--- a/src/librustc_metadata/index_builder.rs
+++ /dev/null
@@ -1,224 +0,0 @@
-//! Builder types for generating the "item data" section of the
-//! metadata. This section winds up looking like this:
-//!
-//! ```
-//! <common::data> // big list of item-like things...
-//!    <common::data_item> // ...for most `DefId`s, there is an entry.
-//!    </common::data_item>
-//! </common::data>
-//! ```
-//!
-//! As we generate this listing, we collect the offset of each
-//! `data_item` entry and store it in an index. Then, when we load the
-//! metadata, we can skip right to the metadata for a particular item.
-//!
-//! In addition to the offset, we need to track the data that was used
-//! to generate the contents of each `data_item`. This is so that we
-//! can figure out which HIR nodes contributed to that data for
-//! incremental compilation purposes.
-//!
-//! The `IndexBuilder` facilitates both of these. It is created
-//! with an `EncodingContext` (`ecx`), which it encapsulates.
-//! It has one main method, `record()`. You invoke `record`
-//! like so to create a new `data_item` element in the list:
-//!
-//! ```
-//! index.record(some_def_id, callback_fn, data)
-//! ```
-//!
-//! What record will do is to (a) record the current offset, (b) emit
-//! the `common::data_item` tag, and then call `callback_fn` with the
-//! given data as well as the `EncodingContext`. Once `callback_fn`
-//! returns, the `common::data_item` tag will be closed.
-//!
-//! `EncodingContext` does not offer the `record` method, so that we
-//! can ensure that `common::data_item` elements are never nested.
-//!
-//! In addition, while the `callback_fn` is executing, we will push a
-//! task `MetaData(some_def_id)`, which can then observe the
-//! reads/writes that occur in the task. For this reason, the `data`
-//! argument that is given to the `callback_fn` must implement the
-//! trait `DepGraphRead`, which indicates how to register reads on the
-//! data in this new task (note that many types of data, such as
-//! `DefId`, do not currently require any reads to be registered,
-//! since they are not derived from a HIR node). This is also why we
-//! give a callback fn, rather than taking a closure: it allows us to
-//! easily control precisely what data is given to that fn.
-
-use crate::encoder::EncodeContext;
-use crate::index::Index;
-use crate::schema::*;
-use crate::isolated_encoder::IsolatedEncoder;
-
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::ty::TyCtxt;
-use syntax::ast;
-
-use std::ops::{Deref, DerefMut};
-
-/// Builder that can encode new items, adding them into the index.
-/// Item encoding cannot be nested.
-pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> {
-    items: Index,
-    pub ecx: &'a mut EncodeContext<'b, 'tcx>,
-}
-
-impl<'a, 'b, 'tcx> Deref for IndexBuilder<'a, 'b, 'tcx> {
-    type Target = EncodeContext<'b, 'tcx>;
-    fn deref(&self) -> &Self::Target {
-        self.ecx
-    }
-}
-
-impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        self.ecx
-    }
-}
-
-impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
-    pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
-        IndexBuilder {
-            items: Index::new(ecx.tcx.hir().definitions().def_index_count()),
-            ecx,
-        }
-    }
-
-    /// Emit the data for a `DefId` to the metadata. The function to
-    /// emit the data is `op`, and it will be given `data` as
-    /// arguments. This `record` function will call `op` to generate
-    /// the `Entry` (which may point to other encoded information)
-    /// and will then record the `Lazy<Entry>` for use in the index.
-    ///
-    /// In addition, it will setup a dep-graph task to track what data
-    /// `op` accesses to generate the metadata, which is later used by
-    /// incremental compilation to compute a hash for the metadata and
-    /// track changes.
-    ///
-    /// The reason that `op` is a function pointer, and not a closure,
-    /// is that we want to be able to completely track all data it has
-    /// access to, so that we can be sure that `DATA: DepGraphRead`
-    /// holds, and that it is therefore not gaining "secret" access to
-    /// bits of HIR or other state that would not be trackd by the
-    /// content system.
-    pub fn record<'x, DATA>(&'x mut self,
-                            id: DefId,
-                            op: fn(&mut IsolatedEncoder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>,
-                            data: DATA)
-        where DATA: DepGraphRead
-    {
-        assert!(id.is_local());
-
-        // We don't track this since we are explicitly computing the incr. comp.
-        // hashes anyway. In theory we could do some tracking here and use it to
-        // avoid rehashing things (and instead cache the hashes) but it's
-        // unclear whether that would be a win since hashing is cheap enough.
-        self.ecx.tcx.dep_graph.with_ignore(move || {
-            let mut entry_builder = IsolatedEncoder::new(self.ecx);
-            let entry = op(&mut entry_builder, data);
-            let entry = entry_builder.lazy(&entry);
-
-            self.items.record(id, entry);
-        })
-    }
-
-    pub fn into_items(self) -> Index {
-        self.items
-    }
-}
-
-/// Trait used for data that can be passed from outside a dep-graph
-/// task. The data must either be of some safe type, such as a
-/// `DefId` index, or implement the `read` method so that it can add
-/// a read of whatever dep-graph nodes are appropriate.
-pub trait DepGraphRead {
-    fn read(&self, tcx: TyCtxt<'_, '_, '_>);
-}
-
-impl DepGraphRead for DefId {
-    fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
-}
-
-impl DepGraphRead for ast::NodeId {
-    fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
-}
-
-impl<T> DepGraphRead for Option<T>
-    where T: DepGraphRead
-{
-    fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-        match *self {
-            Some(ref v) => v.read(tcx),
-            None => (),
-        }
-    }
-}
-
-impl<T> DepGraphRead for [T]
-    where T: DepGraphRead
-{
-    fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-        for i in self {
-            i.read(tcx);
-        }
-    }
-}
-
-macro_rules! read_tuple {
-    ($($name:ident),*) => {
-        impl<$($name),*> DepGraphRead for ($($name),*)
-            where $($name: DepGraphRead),*
-        {
-            #[allow(non_snake_case)]
-            fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-                let &($(ref $name),*) = self;
-                $($name.read(tcx);)*
-            }
-        }
-    }
-}
-read_tuple!(A, B);
-read_tuple!(A, B, C);
-
-macro_rules! read_hir {
-    ($t:ty) => {
-        impl<'tcx> DepGraphRead for &'tcx $t {
-            fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-                tcx.hir().read(self.hir_id);
-            }
-        }
-    }
-}
-read_hir!(hir::Item);
-read_hir!(hir::ImplItem);
-read_hir!(hir::TraitItem);
-read_hir!(hir::ForeignItem);
-read_hir!(hir::MacroDef);
-
-/// Leaks access to a value of type T without any tracking. This is
-/// suitable for ambiguous types like `usize`, which *could* represent
-/// tracked data (e.g., if you read it out of a HIR node) or might not
-/// (e.g., if it's an index). Adding in an `Untracked` is an
-/// assertion, essentially, that the data does not need to be tracked
-/// (or that read edges will be added by some other way).
-///
-/// A good idea is to add to each use of `Untracked` an explanation of
-/// why this value is ok.
-pub struct Untracked<T>(pub T);
-
-impl<T> DepGraphRead for Untracked<T> {
-    fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {}
-}
-
-/// Newtype that can be used to package up misc data extracted from a
-/// HIR node that doesn't carry its own ID. This will allow an
-/// arbitrary `T` to be passed in, but register a read on the given
-/// `NodeId`.
-pub struct FromId<T>(pub hir::HirId, pub T);
-
-impl<T> DepGraphRead for FromId<T> {
-    fn read(&self, tcx: TyCtxt<'_, '_, '_>) {
-        tcx.hir().read(self.0);
-    }
-}
diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs
deleted file mode 100644
index e879a73e650..00000000000
--- a/src/librustc_metadata/isolated_encoder.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-use crate::encoder::EncodeContext;
-use crate::schema::{Lazy, LazySeq};
-use rustc::ty::TyCtxt;
-use rustc_serialize::Encodable;
-
-/// The IsolatedEncoder provides facilities to write to crate metadata while
-/// making sure that anything going through it is also feed into an ICH hasher.
-pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> {
-    pub tcx: TyCtxt<'b, 'tcx, 'tcx>,
-    ecx: &'a mut EncodeContext<'b, 'tcx>,
-}
-
-impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
-
-    pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self {
-        let tcx = ecx.tcx;
-        IsolatedEncoder {
-            tcx,
-            ecx,
-        }
-    }
-
-    pub fn lazy<T>(&mut self, value: &T) -> Lazy<T>
-        where T: Encodable
-    {
-        self.ecx.lazy(value)
-    }
-
-    pub fn lazy_seq<I, T>(&mut self, iter: I) -> LazySeq<T>
-        where I: IntoIterator<Item = T>,
-              T: Encodable
-    {
-        self.ecx.lazy_seq(iter)
-    }
-
-    pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq<T>
-        where I: IntoIterator<Item = &'x T>,
-              T: 'x + Encodable
-    {
-        self.ecx.lazy_seq_ref(iter)
-    }
-
-    pub fn lazy_seq_from_slice<T>(&mut self, slice: &[T]) -> LazySeq<T>
-        where T: Encodable
-    {
-        self.ecx.lazy_seq_ref(slice.iter())
-    }
-}
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 4f84ca69b7f..e0b92341575 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -2,6 +2,7 @@
 
 #![feature(box_patterns)]
 #![feature(drain_filter)]
+#![feature(in_band_lifetimes)]
 #![feature(libc)]
 #![feature(nll)]
 #![feature(proc_macro_internals)]
@@ -28,12 +29,10 @@ extern crate rustc_data_structures;
 
 mod error_codes;
 
-mod index_builder;
 mod index;
 mod encoder;
 mod decoder;
 mod cstore_impl;
-mod isolated_encoder;
 mod schema;
 mod native_libs;
 mod link_args;
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 504c7da7d6b..0ad32515407 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -2,8 +2,8 @@ use crate::index;
 
 use rustc::hir;
 use rustc::hir::def::{self, CtorKind};
-use rustc::hir::def_id::{DefIndex, DefId, CrateNum};
-use rustc::ich::StableHashingContext;
+use rustc::hir::def_id::{DefIndex, DefId};
+use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
 use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule};
 use rustc::middle::lang_items;
 use rustc::mir;
@@ -19,10 +19,6 @@ use syntax::symbol::Symbol;
 use syntax_pos::{self, Span};
 
 use std::marker::PhantomData;
-use std::mem;
-
-use rustc_data_structures::stable_hasher::{StableHasher, HashStable,
-                                           StableHasherResult};
 
 pub fn rustc_version() -> String {
     format!("rustc {}",
@@ -91,15 +87,6 @@ impl<T> Clone for Lazy<T> {
 impl<T> serialize::UseSpecializedEncodable for Lazy<T> {}
 impl<T> serialize::UseSpecializedDecodable for Lazy<T> {}
 
-impl<CTX, T> HashStable<CTX> for Lazy<T> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut CTX,
-                                          _: &mut StableHasher<W>) {
-        // There's nothing to do. Whatever got encoded within this Lazy<>
-        // wrapper has already been hashed.
-    }
-}
-
 /// A sequence of type T referred to by its absolute position
 /// in the metadata and length, and which can be decoded lazily.
 /// The sequence is a single node for the purposes of `Lazy`.
@@ -148,15 +135,6 @@ impl<T> Clone for LazySeq<T> {
 impl<T> serialize::UseSpecializedEncodable for LazySeq<T> {}
 impl<T> serialize::UseSpecializedDecodable for LazySeq<T> {}
 
-impl<CTX, T> HashStable<CTX> for LazySeq<T> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          _: &mut CTX,
-                                          _: &mut StableHasher<W>) {
-        // There's nothing to do. Whatever got encoded within this Lazy<>
-        // wrapper has already been hashed.
-    }
-}
-
 /// Encoding / decoding state for `Lazy` and `LazySeq`.
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum LazyState {
@@ -174,7 +152,7 @@ pub enum LazyState {
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
-pub struct CrateRoot {
+pub struct CrateRoot<'tcx> {
     pub name: Symbol,
     pub triple: TargetTriple,
     pub extra_filename: String,
@@ -199,10 +177,10 @@ pub struct CrateRoot {
     pub source_map: LazySeq<syntax_pos::SourceFile>,
     pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
     pub impls: LazySeq<TraitImpls>,
-    pub exported_symbols: EncodedExportedSymbols,
+    pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>,
     pub interpret_alloc_index: LazySeq<u32>,
 
-    pub index: LazySeq<index::Index>,
+    pub entries_index: LazySeq<index::Index<'tcx>>,
 
     pub compiler_builtins: bool,
     pub needs_allocator: bool,
@@ -221,36 +199,12 @@ pub struct CrateDep {
     pub extra_filename: String,
 }
 
-impl_stable_hash_for!(struct CrateDep {
-    name,
-    hash,
-    kind,
-    extra_filename
-});
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitImpls {
     pub trait_id: (u32, DefIndex),
     pub impls: LazySeq<DefIndex>,
 }
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TraitImpls {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        let TraitImpls {
-            trait_id: (krate, def_index),
-            ref impls,
-        } = *self;
-
-        DefId {
-            krate: CrateNum::from_u32(krate),
-            index: def_index
-        }.hash_stable(hcx, hasher);
-        impls.hash_stable(hcx, hasher);
-    }
-}
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Entry<'tcx> {
     pub kind: EntryKind<'tcx>,
@@ -271,23 +225,6 @@ pub struct Entry<'tcx> {
     pub mir: Option<Lazy<mir::Mir<'tcx>>>,
 }
 
-impl_stable_hash_for!(struct Entry<'tcx> {
-    kind,
-    visibility,
-    span,
-    attributes,
-    children,
-    stability,
-    deprecation,
-    ty,
-    inherent_impls,
-    variances,
-    generics,
-    predicates,
-    predicates_defined_on,
-    mir
-});
-
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub enum EntryKind<'tcx> {
     Const(ConstQualif, Lazy<RenderedConst>),
@@ -322,82 +259,6 @@ pub enum EntryKind<'tcx> {
     TraitAlias(Lazy<TraitAliasData<'tcx>>),
 }
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-        match *self {
-            EntryKind::ImmStatic        |
-            EntryKind::MutStatic        |
-            EntryKind::ForeignImmStatic |
-            EntryKind::ForeignMutStatic |
-            EntryKind::ForeignMod       |
-            EntryKind::GlobalAsm        |
-            EntryKind::ForeignType      |
-            EntryKind::Field |
-            EntryKind::Existential |
-            EntryKind::Type |
-            EntryKind::TypeParam |
-            EntryKind::ConstParam => {
-                // Nothing else to hash here.
-            }
-            EntryKind::Const(qualif, ref const_data) => {
-                qualif.hash_stable(hcx, hasher);
-                const_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Enum(ref repr_options) => {
-                repr_options.hash_stable(hcx, hasher);
-            }
-            EntryKind::Variant(ref variant_data) => {
-                variant_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Struct(ref variant_data, ref repr_options) |
-            EntryKind::Union(ref variant_data, ref repr_options)  => {
-                variant_data.hash_stable(hcx, hasher);
-                repr_options.hash_stable(hcx, hasher);
-            }
-            EntryKind::Fn(ref fn_data) |
-            EntryKind::ForeignFn(ref fn_data) => {
-                fn_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Mod(ref mod_data) => {
-                mod_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::MacroDef(ref macro_def) => {
-                macro_def.hash_stable(hcx, hasher);
-            }
-            EntryKind::Generator(data) => {
-                data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Closure(closure_data) => {
-                closure_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Trait(ref trait_data) => {
-                trait_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::TraitAlias(ref trait_alias_data) => {
-                trait_alias_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Impl(ref impl_data) => {
-                impl_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::Method(ref method_data) => {
-                method_data.hash_stable(hcx, hasher);
-            }
-            EntryKind::AssociatedExistential(associated_container) |
-            EntryKind::AssociatedType(associated_container) => {
-                associated_container.hash_stable(hcx, hasher);
-            }
-            EntryKind::AssociatedConst(associated_container, qualif, ref const_data) => {
-                associated_container.hash_stable(hcx, hasher);
-                qualif.hash_stable(hcx, hasher);
-                const_data.hash_stable(hcx, hasher);
-            }
-        }
-    }
-}
-
 /// Additional data for EntryKind::Const and EntryKind::AssociatedConst
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable)]
 pub struct ConstQualif {
@@ -405,37 +266,22 @@ pub struct ConstQualif {
     pub ast_promotable: bool,
 }
 
-impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable });
-
 /// Contains a constant which has been rendered to a String.
 /// Used by rustdoc.
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct RenderedConst(pub String);
 
-impl<'a> HashStable<StableHashingContext<'a>> for RenderedConst {
-    #[inline]
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        self.0.hash_stable(hcx, hasher);
-    }
-}
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ModData {
     pub reexports: LazySeq<def::Export<hir::HirId>>,
 }
 
-impl_stable_hash_for!(struct ModData { reexports });
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct MacroDef {
     pub body: String,
     pub legacy: bool,
 }
 
-impl_stable_hash_for!(struct MacroDef { body, legacy });
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct FnData<'tcx> {
     pub constness: hir::Constness,
@@ -443,8 +289,6 @@ pub struct FnData<'tcx> {
     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
 
-impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig });
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct VariantData<'tcx> {
     pub ctor_kind: CtorKind,
@@ -456,13 +300,6 @@ pub struct VariantData<'tcx> {
     pub ctor_sig: Option<Lazy<ty::PolyFnSig<'tcx>>>,
 }
 
-impl_stable_hash_for!(struct VariantData<'tcx> {
-    ctor_kind,
-    discr,
-    ctor,
-    ctor_sig
-});
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitData<'tcx> {
     pub unsafety: hir::Unsafety,
@@ -472,23 +309,11 @@ pub struct TraitData<'tcx> {
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
-impl_stable_hash_for!(struct TraitData<'tcx> {
-    unsafety,
-    paren_sugar,
-    has_auto_impl,
-    is_marker,
-    super_predicates
-});
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct TraitAliasData<'tcx> {
     pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
 }
 
-impl_stable_hash_for!(struct TraitAliasData<'tcx> {
-    super_predicates
-});
-
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ImplData<'tcx> {
     pub polarity: hir::ImplPolarity,
@@ -500,14 +325,6 @@ pub struct ImplData<'tcx> {
     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
 }
 
-impl_stable_hash_for!(struct ImplData<'tcx> {
-    polarity,
-    defaultness,
-    parent_impl,
-    coerce_unsized_info,
-    trait_ref
-});
-
 
 /// Describes whether the container of an associated item
 /// is a trait or an impl and whether, in a trait, it has
@@ -520,13 +337,6 @@ pub enum AssociatedContainer {
     ImplFinal,
 }
 
-impl_stable_hash_for!(enum crate::schema::AssociatedContainer {
-    TraitRequired,
-    TraitWithDefault,
-    ImplDefault,
-    ImplFinal
-});
-
 impl AssociatedContainer {
     pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer {
         match *self {
@@ -560,26 +370,17 @@ pub struct MethodData<'tcx> {
     pub container: AssociatedContainer,
     pub has_self: bool,
 }
-impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self });
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ClosureData<'tcx> {
     pub sig: Lazy<ty::PolyFnSig<'tcx>>,
 }
-impl_stable_hash_for!(struct ClosureData<'tcx> { sig });
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct GeneratorData<'tcx> {
     pub layout: mir::GeneratorLayout<'tcx>,
 }
-impl_stable_hash_for!(struct GeneratorData<'tcx> { layout });
 
 // Tags used for encoding Spans:
 pub const TAG_VALID_SPAN: u8 = 0;
 pub const TAG_INVALID_SPAN: u8 = 1;
-
-#[derive(RustcEncodable, RustcDecodable)]
-pub struct EncodedExportedSymbols {
-    pub position: usize,
-    pub len: usize,
-}
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index fc1f5eb5d5a..cf02878ec82 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -439,10 +439,11 @@ fn downgrade_if_error(diag: &mut Diagnostic) {
         diag.warn(
             "this error has been downgraded to a warning for backwards \
             compatibility with previous releases",
-        );
-        diag.warn(
+        ).warn(
             "this represents potential undefined behavior in your code and \
             this warning will become a hard error in the future",
+        ).note(
+            "for more information, try `rustc --explain E0729`"
         );
     }
 }
diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs
index 74a4278d599..4807782c663 100644
--- a/src/librustc_mir/error_codes.rs
+++ b/src/librustc_mir/error_codes.rs
@@ -2424,6 +2424,38 @@ const fn foo() -> impl T {
 ```
 "##,
 
+E0729: r##"
+Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler
+since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow
+checker for NLL uncovered some bugs in the old borrow checker, which in some
+cases allowed unsound code to compile, resulting in memory safety issues.
+
+### What do I do?
+
+Change your code so the warning does no longer trigger. For backwards
+compatibility, this unsound code may still compile (with a warning) right now.
+However, at some point in the future, the compiler will no longer accept this
+code and will throw a hard error.
+
+### Shouldn't you fix the old borrow checker?
+
+The old borrow checker has known soundness issues that are basically impossible
+to fix. The new NLL-based borrow checker is the fix.
+
+### Can I turn these warnings into errors by denying a lint?
+
+No.
+
+### When are these warnings going to turn into errors?
+
+No formal timeline for turning the warnings into errors has been set. See
+[GitHub issue 58781](https://github.com/rust-lang/rust/issues/58781) for more
+information.
+
+### Why do I get this message with code that doesn't involve borrowing?
+
+There are some known bugs that trigger this message.
+"##,
 }
 
 register_diagnostics! {
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 84e2caec68e..12357cb10a9 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -930,58 +930,60 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                     context: PlaceContext,
                     location: Location) {
         debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
-        self.super_place(place, context, location);
-        match *place {
-            Place::Base(PlaceBase::Local(_)) => {}
-            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. })) => {
-                unreachable!()
-            }
-            Place::Base(PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. })) => {
-                if self.tcx
-                       .get_attrs(def_id)
-                       .iter()
-                       .any(|attr| attr.check_name(sym::thread_local)) {
-                    if self.mode != Mode::Fn {
-                        span_err!(self.tcx.sess, self.span, E0625,
-                                  "thread-local statics cannot be \
-                                   accessed at compile-time");
-                    }
-                    return;
+        place.iterate(|place_base, place_projections| {
+            match place_base {
+                PlaceBase::Local(_) => {}
+                PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => {
+                    unreachable!()
                 }
+                PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => {
+                    if self.tcx
+                           .get_attrs(*def_id)
+                           .iter()
+                           .any(|attr| attr.check_name(sym::thread_local)) {
+                        if self.mode != Mode::Fn {
+                            span_err!(self.tcx.sess, self.span, E0625,
+                                      "thread-local statics cannot be \
+                                       accessed at compile-time");
+                        }
+                        return;
+                    }
 
-                // Only allow statics (not consts) to refer to other statics.
-                if self.mode == Mode::Static || self.mode == Mode::StaticMut {
-                    if self.mode == Mode::Static && context.is_mutating_use() {
-                        // this is not strictly necessary as miri will also bail out
-                        // For interior mutability we can't really catch this statically as that
-                        // goes through raw pointers and intermediate temporaries, so miri has
-                        // to catch this anyway
-                        self.tcx.sess.span_err(
-                            self.span,
-                            "cannot mutate statics in the initializer of another static",
-                        );
+                    // Only allow statics (not consts) to refer to other statics.
+                    if self.mode == Mode::Static || self.mode == Mode::StaticMut {
+                        if self.mode == Mode::Static && context.is_mutating_use() {
+                            // this is not strictly necessary as miri will also bail out
+                            // For interior mutability we can't really catch this statically as that
+                            // goes through raw pointers and intermediate temporaries, so miri has
+                            // to catch this anyway
+                            self.tcx.sess.span_err(
+                                self.span,
+                                "cannot mutate statics in the initializer of another static",
+                            );
+                        }
+                        return;
                     }
-                    return;
-                }
-                unleash_miri!(self);
+                    unleash_miri!(self);
 
-                if self.mode != Mode::Fn {
-                    let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
-                                                   "{}s cannot refer to statics, use \
-                                                    a constant instead", self.mode);
-                    if self.tcx.sess.teach(&err.get_code().unwrap()) {
-                        err.note(
-                            "Static and const variables can refer to other const variables. But a \
-                             const variable cannot refer to a static variable."
-                        );
-                        err.help(
-                            "To fix this, the value can be extracted as a const and then used."
-                        );
+                    if self.mode != Mode::Fn {
+                        let mut err = struct_span_err!(self.tcx.sess, self.span, E0013,
+                                                       "{}s cannot refer to statics, use \
+                                                        a constant instead", self.mode);
+                        if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                            err.note(
+                                "Static and const variables can refer to other const variables. \
+                                 But a const variable cannot refer to a static variable."
+                            );
+                            err.help(
+                                "To fix this, the value can be extracted as a const and then used."
+                            );
+                        }
+                        err.emit()
                     }
-                    err.emit()
                 }
             }
-            Place::Projection(ref proj) => {
+
+            for proj in place_projections {
                 match proj.elem {
                     ProjectionElem::Deref => {
                         if context.is_mutating_use() {
@@ -1041,7 +1043,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
                     }
                 }
             }
-        }
+        });
     }
 
     fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 5b1a9bb739f..b27f5b1495c 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1134,6 +1134,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
             is just used to enable niche optimizations in libcore \
             and will never be stable",
         cfg_fn!(rustc_attrs))),
+    (sym::rustc_nonnull_optimization_guaranteed, Whitelisted, template!(Word),
+    Gated(Stability::Unstable,
+        sym::rustc_attrs,
+        "the `#[rustc_nonnull_optimization_guaranteed]` attribute \
+            is just used to enable niche optimizations in libcore \
+            and will never be stable",
+        cfg_fn!(rustc_attrs))),
     (sym::rustc_regions, Normal, template!(Word), Gated(Stability::Unstable,
                                     sym::rustc_attrs,
                                     "the `#[rustc_regions]` attribute \
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 8b07e81e586..b59244283d7 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -491,6 +491,7 @@ symbols! {
         rustc_layout_scalar_valid_range_end,
         rustc_layout_scalar_valid_range_start,
         rustc_mir,
+        rustc_nonnull_optimization_guaranteed,
         rustc_object_lifetime_default,
         rustc_on_unimplemented,
         rustc_outlives,
diff --git a/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs
new file mode 100644
index 00000000000..6acc8627738
--- /dev/null
+++ b/src/test/rustdoc/issue-60726.rs
@@ -0,0 +1,35 @@
+use std::marker::PhantomData;
+
+pub struct True;
+pub struct False;
+
+pub trait InterfaceType{
+    type Send;
+}
+
+
+pub struct FooInterface<T>(PhantomData<fn()->T>);
+
+impl<T> InterfaceType for FooInterface<T> {
+    type Send=False;
+}
+
+
+pub struct DynTrait<I>{
+    _interface:PhantomData<fn()->I>,
+    _unsync_unsend:PhantomData<::std::rc::Rc<()>>,
+}
+
+unsafe impl<I> Send for DynTrait<I>
+where
+    I:InterfaceType<Send=True>
+{}
+
+// @has issue_60726/struct.IntoIter.html
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Send for \
+// IntoIter<T>"
+// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Sync for \
+// IntoIter<T>"
+pub struct IntoIter<T>{
+    hello:DynTrait<FooInterface<T>>,
+}
diff --git a/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr b/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr
index 5e86dcb1232..e2d3e417ac3 100644
--- a/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr
+++ b/src/test/ui/borrowck/borrowck-anon-fields-variant.stderr
@@ -12,6 +12,7 @@ LL |     *a += 1;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0503]: cannot use `y` because it was mutably borrowed
   --> $DIR/borrowck-anon-fields-variant.rs:37:7
diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
index fb42e5fbca8..14b9b50f0c3 100644
--- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr
@@ -341,6 +341,7 @@ LL |             drop(x);
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:227:33
@@ -355,6 +356,7 @@ LL |             drop(x);
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-describe-lvalue.rs:282:22
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
index 8dba34bd808..461fb7d11a5 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.edition.stderr
@@ -6,4 +6,5 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
diff --git a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
index 8dba34bd808..461fb7d11a5 100644
--- a/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
+++ b/src/test/ui/borrowck/borrowck-migrate-to-nll.zflag.stderr
@@ -6,4 +6,5 @@ LL |                 (|| { let bar = foo; bar.take() })();
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
index d12d751d89b..ac6bed6137f 100644
--- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
+++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr
@@ -28,6 +28,7 @@ LL |         Enum::A(_) if { x = Enum::B(false); false } => 1,
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0510]: cannot mutably borrow `x` in match guard
   --> $DIR/borrowck-mutate-in-guard.rs:15:33
@@ -40,6 +41,7 @@ LL |         Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1,
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/const_let_refutable.stderr b/src/test/ui/consts/const_let_refutable.stderr
index 20433bbf8b5..2ca76667bd1 100644
--- a/src/test/ui/consts/const_let_refutable.stderr
+++ b/src/test/ui/consts/const_let_refutable.stderr
@@ -21,6 +21,7 @@ LL |     a + b
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0381]: use of possibly uninitialized variable: `b`
   --> $DIR/const_let_refutable.rs:4:9
@@ -30,6 +31,7 @@ LL |     a + b
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index 7af37992460..93b57bc24a8 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -297,6 +297,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable
   --> $DIR/min_const_fn.rs:144:41
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
index b6445329db3..9ded93c1672 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr
@@ -27,6 +27,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr
index 6608ad763b2..9911dd4683b 100644
--- a/src/test/ui/empty/empty-never-array.stderr
+++ b/src/test/ui/empty/empty-never-array.stderr
@@ -19,6 +19,7 @@ LL |     u
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-nll.stderr b/src/test/ui/feature-gates/feature-gate-nll.stderr
index ac21241b303..37542d52dc2 100644
--- a/src/test/ui/feature-gates/feature-gate-nll.stderr
+++ b/src/test/ui/feature-gates/feature-gate-nll.stderr
@@ -11,6 +11,7 @@ LL |     m;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/feature-gate-nll.rs:10:1
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs
index f7ff3eb3ac9..9f5c92349e0 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.rs
@@ -4,5 +4,6 @@
 
 #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
 #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
+#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
 
 fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
index 882feb87f42..ed98484e13c 100644
--- a/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
+++ b/src/test/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
@@ -16,6 +16,15 @@ LL | #[rustc_error]
    = note: for more information, see https://github.com/rust-lang/rust/issues/29642
    = help: add #![feature(rustc_attrs)] to the crate attributes to enable
 
-error: aborting due to 2 previous errors
+error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and will never be stable
+  --> $DIR/feature-gate-rustc-attrs-1.rs:7:1
+   |
+LL | #[rustc_nonnull_optimization_guaranteed]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: for more information, see https://github.com/rust-lang/rust/issues/29642
+   = help: add #![feature(rustc_attrs)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-15381.stderr b/src/test/ui/issues/issue-15381.stderr
index 0f44a0f170f..7b11d85ead8 100644
--- a/src/test/ui/issues/issue-15381.stderr
+++ b/src/test/ui/issues/issue-15381.stderr
@@ -12,6 +12,7 @@ LL |         println!("y={}", y);
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-40510-1.migrate.stderr b/src/test/ui/issues/issue-40510-1.migrate.stderr
index 17d1c48d075..28aaa2a797e 100644
--- a/src/test/ui/issues/issue-40510-1.migrate.stderr
+++ b/src/test/ui/issues/issue-40510-1.migrate.stderr
@@ -10,6 +10,7 @@ LL |         &mut x
    = note: ...therefore, they cannot allow references to captured variables to escape
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/issue-40510-1.rs:20:1
diff --git a/src/test/ui/issues/issue-40510-3.migrate.stderr b/src/test/ui/issues/issue-40510-3.migrate.stderr
index 692aa105377..f00690efc31 100644
--- a/src/test/ui/issues/issue-40510-3.migrate.stderr
+++ b/src/test/ui/issues/issue-40510-3.migrate.stderr
@@ -12,6 +12,7 @@ LL | |         }
    = note: ...therefore, they cannot allow references to captured variables to escape
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/issue-40510-3.rs:22:1
diff --git a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
index 8cc9f1eb2a6..479b724ad18 100644
--- a/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
+++ b/src/test/ui/issues/issue-45696-scribble-on-boxed-borrow.migrate.stderr
@@ -11,6 +11,7 @@ LL | }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0713]: borrow may still be in use when destructor runs
   --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:5
@@ -25,6 +26,7 @@ LL | }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 warning[E0713]: borrow may still be in use when destructor runs
   --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
@@ -39,6 +41,7 @@ LL | }
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:80:1
diff --git a/src/test/ui/issues/issue-49824.stderr b/src/test/ui/issues/issue-49824.stderr
index c66ee69cb2b..d5f1af88e13 100644
--- a/src/test/ui/issues/issue-49824.stderr
+++ b/src/test/ui/issues/issue-49824.stderr
@@ -15,6 +15,7 @@ LL | |         }
    = note: ...therefore, they cannot allow references to captured variables to escape
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: compilation successful
   --> $DIR/issue-49824.rs:6:1
diff --git a/src/test/ui/lint/lint-ctypes-enum.rs b/src/test/ui/lint/lint-ctypes-enum.rs
index f347c2761c3..d3e11d2f7ed 100644
--- a/src/test/ui/lint/lint-ctypes-enum.rs
+++ b/src/test/ui/lint/lint-ctypes-enum.rs
@@ -1,6 +1,8 @@
 #![deny(improper_ctypes)]
 #![allow(dead_code)]
 
+use std::num;
+
 enum Z { }
 enum U { A }
 enum B { C, D }
@@ -15,14 +17,39 @@ enum U8 { A, B, C }
 #[repr(isize)]
 enum Isize { A, B, C }
 
+#[repr(transparent)]
+struct Transparent<T>(T, std::marker::PhantomData<Z>);
+
+struct Rust<T>(T);
+
 extern {
    fn zf(x: Z);
    fn uf(x: U); //~ ERROR enum has no representation hint
    fn bf(x: B); //~ ERROR enum has no representation hint
    fn tf(x: T); //~ ERROR enum has no representation hint
-   fn reprc(x: ReprC);
-   fn u8(x: U8);
-   fn isize(x: Isize);
+   fn repr_c(x: ReprC);
+   fn repr_u8(x: U8);
+   fn repr_isize(x: Isize);
+   fn option_ref(x: Option<&'static u8>);
+   fn option_fn(x: Option<extern "C" fn()>);
+   fn nonnull(x: Option<std::ptr::NonNull<u8>>);
+   fn nonzero_u8(x: Option<num::NonZeroU8>);
+   fn nonzero_u16(x: Option<num::NonZeroU16>);
+   fn nonzero_u32(x: Option<num::NonZeroU32>);
+   fn nonzero_u64(x: Option<num::NonZeroU64>);
+   fn nonzero_u128(x: Option<num::NonZeroU128>);
+   //~^ ERROR 128-bit integers don't currently have a known stable ABI
+   fn nonzero_usize(x: Option<num::NonZeroUsize>);
+   fn nonzero_i8(x: Option<num::NonZeroI8>);
+   fn nonzero_i16(x: Option<num::NonZeroI16>);
+   fn nonzero_i32(x: Option<num::NonZeroI32>);
+   fn nonzero_i64(x: Option<num::NonZeroI64>);
+   fn nonzero_i128(x: Option<num::NonZeroI128>);
+   //~^ ERROR 128-bit integers don't currently have a known stable ABI
+   fn nonzero_isize(x: Option<num::NonZeroIsize>);
+   fn repr_transparent(x: Option<Transparent<num::NonZeroU8>>);
+   fn repr_rust(x: Option<Rust<num::NonZeroU8>>); //~ ERROR enum has no representation hint
+   fn no_result(x: Result<(), num::NonZeroI32>); //~ ERROR enum has no representation hint
 }
 
 pub fn main() { }
diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr
index 92f76cfc38a..6b807f48aaa 100644
--- a/src/test/ui/lint/lint-ctypes-enum.stderr
+++ b/src/test/ui/lint/lint-ctypes-enum.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `U` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:20:13
+  --> $DIR/lint-ctypes-enum.rs:27:13
    |
 LL |    fn uf(x: U);
    |             ^
@@ -11,36 +11,64 @@ LL | #![deny(improper_ctypes)]
    |         ^^^^^^^^^^^^^^^
    = help: consider adding a #[repr(...)] attribute to this enum
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:5:1
+  --> $DIR/lint-ctypes-enum.rs:7:1
    |
 LL | enum U { A }
    | ^^^^^^^^^^^^
 
 error: `extern` block uses type `B` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:21:13
+  --> $DIR/lint-ctypes-enum.rs:28:13
    |
 LL |    fn bf(x: B);
    |             ^
    |
    = help: consider adding a #[repr(...)] attribute to this enum
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:6:1
+  --> $DIR/lint-ctypes-enum.rs:8:1
    |
 LL | enum B { C, D }
    | ^^^^^^^^^^^^^^^
 
 error: `extern` block uses type `T` which is not FFI-safe: enum has no representation hint
-  --> $DIR/lint-ctypes-enum.rs:22:13
+  --> $DIR/lint-ctypes-enum.rs:29:13
    |
 LL |    fn tf(x: T);
    |             ^
    |
    = help: consider adding a #[repr(...)] attribute to this enum
 note: type defined here
-  --> $DIR/lint-ctypes-enum.rs:7:1
+  --> $DIR/lint-ctypes-enum.rs:9:1
    |
 LL | enum T { E, F, G }
    | ^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error: `extern` block uses type `u128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+  --> $DIR/lint-ctypes-enum.rs:40:23
+   |
+LL |    fn nonzero_u128(x: Option<num::NonZeroU128>);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `i128` which is not FFI-safe: 128-bit integers don't currently have a known stable ABI
+  --> $DIR/lint-ctypes-enum.rs:47:23
+   |
+LL |    fn nonzero_i128(x: Option<num::NonZeroI128>);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `extern` block uses type `std::option::Option<Rust<std::num::NonZeroU8>>` which is not FFI-safe: enum has no representation hint
+  --> $DIR/lint-ctypes-enum.rs:51:20
+   |
+LL |    fn repr_rust(x: Option<Rust<num::NonZeroU8>>);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a #[repr(...)] attribute to this enum
+
+error: `extern` block uses type `std::result::Result<(), std::num::NonZeroI32>` which is not FFI-safe: enum has no representation hint
+  --> $DIR/lint-ctypes-enum.rs:52:20
+   |
+LL |    fn no_result(x: Result<(), num::NonZeroI32>);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding a #[repr(...)] attribute to this enum
+
+error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/pattern/pattern-bindings-after-at.stderr b/src/test/ui/pattern/pattern-bindings-after-at.stderr
index 3a2cffcbf45..70452a930ee 100644
--- a/src/test/ui/pattern/pattern-bindings-after-at.stderr
+++ b/src/test/ui/pattern/pattern-bindings-after-at.stderr
@@ -18,6 +18,7 @@ LL |             **z = None;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
index 940ab94a613..9203f893fdb 100644
--- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -12,6 +12,7 @@ LL |     x
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/thread-local-in-ctfe.stderr b/src/test/ui/thread-local-in-ctfe.stderr
index bba5b0c74d9..6869109e67f 100644
--- a/src/test/ui/thread-local-in-ctfe.stderr
+++ b/src/test/ui/thread-local-in-ctfe.stderr
@@ -20,6 +20,7 @@ LL | static C: &u32 = &A;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
   --> $DIR/thread-local-in-ctfe.rs:15:16
@@ -43,6 +44,7 @@ LL | const E: &u32 = &A;
    |
    = warning: this error has been downgraded to a warning for backwards compatibility with previous releases
    = warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
+   = note: for more information, try `rustc --explain E0729`
 
 error[E0625]: thread-local statics cannot be accessed at compile-time
   --> $DIR/thread-local-in-ctfe.rs:25:5
diff --git a/src/tools/clippy b/src/tools/clippy
-Subproject 60a609acaed3bf2b3ec6ab995bccf0f03bc2606
+Subproject a8eeb7cdb135da1cd582c6093c1739732727a4a