about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-11-25 06:48:21 +0000
committerbors <bors@rust-lang.org>2018-11-25 06:48:21 +0000
commitabe19a730576cf7ead1bf7995271b53d551ea37f (patch)
treed26fe9c0e33d00119d9f52ee741f6eeded80931e
parent37961dbd2d84a29be49007a5770b96e296f5f349 (diff)
parentb8a30f04cdd129ab89b85d0eda11f1c65058767a (diff)
downloadrust-abe19a730576cf7ead1bf7995271b53d551ea37f.tar.gz
rust-abe19a730576cf7ead1bf7995271b53d551ea37f.zip
Auto merge of #55921 - scalexm:placeholders, r=nikomatsakis
Add placeholder types

Fixes #48696 (handle universes in canonicalization of type inference vars), and fixes #55098.
-rw-r--r--src/librustc/ich/impls_ty.rs9
-rw-r--r--src/librustc/infer/canonical/canonicalizer.rs58
-rw-r--r--src/librustc/infer/canonical/mod.rs42
-rw-r--r--src/librustc/infer/canonical/query_response.rs8
-rw-r--r--src/librustc/infer/freshen.rs6
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs45
-rw-r--r--src/librustc/infer/mod.rs30
-rw-r--r--src/librustc/infer/nll_relate/mod.rs4
-rw-r--r--src/librustc/infer/type_variable.rs2
-rw-r--r--src/librustc/traits/coherence.rs2
-rw-r--r--src/librustc/traits/error_reporting.rs2
-rw-r--r--src/librustc/traits/project.rs6
-rw-r--r--src/librustc/traits/query/dropck_outlives.rs1
-rw-r--r--src/librustc/traits/query/normalize.rs2
-rw-r--r--src/librustc/traits/select.rs19
-rw-r--r--src/librustc/traits/structural_impls.rs2
-rw-r--r--src/librustc/ty/context.rs2
-rw-r--r--src/librustc/ty/error.rs3
-rw-r--r--src/librustc/ty/fast_reject.rs2
-rw-r--r--src/librustc/ty/flags.rs8
-rw-r--r--src/librustc/ty/fold.rs27
-rw-r--r--src/librustc/ty/item_path.rs1
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/mod.rs33
-rw-r--r--src/librustc/ty/outlives.rs1
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc/ty/sty.rs21
-rw-r--r--src/librustc/ty/subst.rs19
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc/ty/walk.rs2
-rw-r--r--src/librustc/ty/wf.rs1
-rw-r--r--src/librustc/util/ppaux.rs13
-rw-r--r--src/librustc_codegen_llvm/debuginfo/type_names.rs1
-rw-r--r--src/librustc_lint/types.rs1
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/values.rs18
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs5
-rw-r--r--src/librustc_mir/monomorphize/item.rs1
-rw-r--r--src/librustc_traits/chalk_context/mod.rs170
-rw-r--r--src/librustc_traits/chalk_context/program_clauses.rs20
-rw-r--r--src/librustc_traits/dropck_outlives.rs2
-rw-r--r--src/librustc_traits/lowering/environment.rs3
-rw-r--r--src/librustc_traits/lowering/mod.rs3
-rw-r--r--src/librustc_typeck/check/cast.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs2
-rw-r--r--src/librustc_typeck/check/writeback.rs4
-rw-r--r--src/librustc_typeck/variance/constraints.rs1
-rw-r--r--src/librustdoc/clean/mod.rs1
-rw-r--r--src/test/run-pass/rustc-rust-log.rs1
-rw-r--r--src/test/ui/nll/user-annotations/dump-fn-method.stderr4
52 files changed, 414 insertions, 212 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 679107160a6..ad317a96590 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -684,9 +684,13 @@ for ty::TyKind<'gcx>
             Param(param_ty) => {
                 param_ty.hash_stable(hcx, hasher);
             }
-            Bound(bound_ty) => {
+            Bound(debruijn, bound_ty) => {
+                debruijn.hash_stable(hcx, hasher);
                 bound_ty.hash_stable(hcx, hasher);
             }
+            ty::Placeholder(placeholder_ty) => {
+                placeholder_ty.hash_stable(hcx, hasher);
+            }
             Foreign(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
@@ -1096,12 +1100,13 @@ impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo {
 
 impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
     Ty(k),
+    PlaceholderTy(placeholder),
     Region(ui),
     PlaceholderRegion(placeholder),
 });
 
 impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
-    General,
+    General(ui),
     Int,
     Float
 });
diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs
index a787eeae663..ddb520775da 100644
--- a/src/librustc/infer/canonical/canonicalizer.rs
+++ b/src/librustc/infer/canonical/canonicalizer.rs
@@ -23,7 +23,7 @@ use infer::InferCtxt;
 use std::sync::atomic::Ordering;
 use ty::fold::{TypeFoldable, TypeFolder};
 use ty::subst::Kind;
-use ty::{self, BoundTy, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
+use ty::{self, BoundVar, Lift, List, Ty, TyCtxt, TypeFlags};
 
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
@@ -339,11 +339,35 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match t.sty {
-            ty::Infer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t),
+            ty::Infer(ty::TyVar(vid)) => {
+                match self.infcx.unwrap().probe_ty_var(vid) {
+                    // `t` could be a float / int variable: canonicalize that instead
+                    Ok(t) => self.fold_ty(t),
+
+                    // `TyVar(vid)` is unresolved, track its universe index in the canonicalized
+                    // result
+                    Err(ui) => self.canonicalize_ty_var(
+                        CanonicalVarInfo {
+                            kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
+                        },
+                        t
+                    )
+                }
+            }
 
-            ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t),
+            ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
+                CanonicalVarInfo {
+                    kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
+                },
+                t
+            ),
 
-            ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t),
+            ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
+                CanonicalVarInfo {
+                    kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
+                },
+                t
+            ),
 
             ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
@@ -351,8 +375,15 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
                 bug!("encountered a fresh type during canonicalization")
             }
 
-            ty::Bound(bound_ty) => {
-                if bound_ty.index >= self.binder_index {
+            ty::Placeholder(placeholder) => self.canonicalize_ty_var(
+                CanonicalVarInfo {
+                    kind: CanonicalVarKind::PlaceholderTy(placeholder)
+                },
+                t
+            ),
+
+            ty::Bound(debruijn, _) => {
+                if debruijn >= self.binder_index {
                     bug!("escaping bound type during canonicalization")
                 } else {
                     t
@@ -408,9 +439,13 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
         V: TypeFoldable<'tcx> + Lift<'gcx>,
     {
         let needs_canonical_flags = if canonicalize_region_mode.any() {
-            TypeFlags::HAS_FREE_REGIONS | TypeFlags::KEEP_IN_LOCAL_TCX
+            TypeFlags::KEEP_IN_LOCAL_TCX |
+            TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
+            TypeFlags::HAS_TY_PLACEHOLDER
         } else {
-            TypeFlags::KEEP_IN_LOCAL_TCX
+            TypeFlags::KEEP_IN_LOCAL_TCX |
+            TypeFlags::HAS_RE_PLACEHOLDER |
+            TypeFlags::HAS_TY_PLACEHOLDER
         };
 
         let gcx = tcx.global_tcx();
@@ -574,17 +609,14 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
     /// if `ty_var` is bound to anything; if so, canonicalize
     /// *that*. Otherwise, create a new canonical variable for
     /// `ty_var`.
-    fn canonicalize_ty_var(&mut self, ty_kind: CanonicalTyVarKind, ty_var: Ty<'tcx>) -> Ty<'tcx> {
+    fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo, ty_var: Ty<'tcx>) -> Ty<'tcx> {
         let infcx = self.infcx.expect("encountered ty-var without infcx");
         let bound_to = infcx.shallow_resolve(ty_var);
         if bound_to != ty_var {
             self.fold_ty(bound_to)
         } else {
-            let info = CanonicalVarInfo {
-                kind: CanonicalVarKind::Ty(ty_kind),
-            };
             let var = self.canonical_var(info, ty_var.into());
-            self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
+            self.tcx().mk_ty(ty::Bound(self.binder_index, var.into()))
         }
     }
 }
diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs
index f7eb7118f41..230f8958b33 100644
--- a/src/librustc/infer/canonical/mod.rs
+++ b/src/librustc/infer/canonical/mod.rs
@@ -122,6 +122,7 @@ impl CanonicalVarInfo {
     pub fn is_existential(&self) -> bool {
         match self.kind {
             CanonicalVarKind::Ty(_) => true,
+            CanonicalVarKind::PlaceholderTy(_) => false,
             CanonicalVarKind::Region(_) => true,
             CanonicalVarKind::PlaceholderRegion(..) => false,
         }
@@ -136,24 +137,27 @@ pub enum CanonicalVarKind {
     /// Some kind of type inference variable.
     Ty(CanonicalTyVarKind),
 
+    /// A "placeholder" that represents "any type".
+    PlaceholderTy(ty::PlaceholderType),
+
     /// Region variable `'?R`.
     Region(ty::UniverseIndex),
 
     /// A "placeholder" that represents "any region". Created when you
     /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
     /// bound region `'a`.
-    PlaceholderRegion(ty::Placeholder),
+    PlaceholderRegion(ty::PlaceholderRegion),
 }
 
 impl CanonicalVarKind {
     pub fn universe(self) -> ty::UniverseIndex {
         match self {
-            // At present, we don't support higher-ranked
-            // quantification over types, so all type variables are in
-            // the root universe.
-            CanonicalVarKind::Ty(_) => ty::UniverseIndex::ROOT,
+            CanonicalVarKind::Ty(kind) => match kind {
+                CanonicalTyVarKind::General(ui) => ui,
+                CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
+            }
 
-            // Region variables can be created in sub-universes.
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
             CanonicalVarKind::Region(ui) => ui,
             CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
         }
@@ -168,7 +172,7 @@ impl CanonicalVarKind {
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
 pub enum CanonicalTyVarKind {
     /// General type variable `?T` that can be unified with arbitrary types.
-    General,
+    General(ty::UniverseIndex),
 
     /// Integral type variable `?I` (that can only be unified with integral types).
     Int,
@@ -358,8 +362,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         match cv_info.kind {
             CanonicalVarKind::Ty(ty_kind) => {
                 let ty = match ty_kind {
-                    CanonicalTyVarKind::General => {
-                        self.next_ty_var(TypeVariableOrigin::MiscVariable(span))
+                    CanonicalTyVarKind::General(ui) => {
+                        self.next_ty_var_in_universe(
+                            TypeVariableOrigin::MiscVariable(span),
+                            universe_map(ui)
+                        )
                     }
 
                     CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()),
@@ -369,20 +376,27 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
                 ty.into()
             }
 
+            CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => {
+                let universe_mapped = universe_map(universe);
+                let placeholder_mapped = ty::PlaceholderType {
+                    universe: universe_mapped,
+                    name,
+                };
+                self.tcx.mk_ty(ty::Placeholder(placeholder_mapped)).into()
+            }
+
             CanonicalVarKind::Region(ui) => self.next_region_var_in_universe(
                 RegionVariableOrigin::MiscVariable(span),
                 universe_map(ui),
             ).into(),
 
-            CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe, name }) => {
+            CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
                 let universe_mapped = universe_map(universe);
-                let placeholder_mapped = ty::Placeholder {
+                let placeholder_mapped = ty::PlaceholderRegion {
                     universe: universe_mapped,
                     name,
                 };
-                self.tcx
-                    .mk_region(ty::RePlaceholder(placeholder_mapped))
-                    .into()
+                self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
             }
         }
     }
diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs
index 6f3d1026835..d32594ebdf3 100644
--- a/src/librustc/infer/canonical/query_response.rs
+++ b/src/librustc/infer/canonical/query_response.rs
@@ -435,21 +435,21 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
             match result_value.unpack() {
                 UnpackedKind::Type(result_value) => {
                     // e.g., here `result_value` might be `?0` in the example above...
-                    if let ty::Bound(b) = result_value.sty {
+                    if let ty::Bound(debruijn, b) = result_value.sty {
                         // ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
 
                         // We only allow a `ty::INNERMOST` index in substitutions.
-                        assert_eq!(b.index, ty::INNERMOST);
+                        assert_eq!(debruijn, ty::INNERMOST);
                         opt_values[b.var] = Some(*original_value);
                     }
                 }
                 UnpackedKind::Lifetime(result_value) => {
                     // e.g., here `result_value` might be `'?1` in the example above...
-                    if let &ty::RegionKind::ReLateBound(index, br) = result_value {
+                    if let &ty::RegionKind::ReLateBound(debruijn, br) = result_value {
                         // ... in which case we would set `canonical_vars[0]` to `Some('static)`.
 
                         // We only allow a `ty::INNERMOST` index in substitutions.
-                        assert_eq!(index, ty::INNERMOST);
+                        assert_eq!(debruijn, ty::INNERMOST);
                         opt_values[br.assert_bound_var()] = Some(*original_value);
                     }
                 }
diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs
index b53444992fa..d17cf0c7b47 100644
--- a/src/librustc/infer/freshen.rs
+++ b/src/librustc/infer/freshen.rs
@@ -170,9 +170,6 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
                 t
             }
 
-            ty::Bound(..) =>
-                bug!("encountered bound ty during freshening"),
-
             ty::Generator(..) |
             ty::Bool |
             ty::Char |
@@ -200,6 +197,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
             ty::Opaque(..) => {
                 t.super_fold_with(self)
             }
+
+            ty::Placeholder(..) |
+            ty::Bound(..) => bug!("unexpected type {:?}", t),
         }
     }
 }
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index 8172f620c36..5218aa36fac 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -53,7 +53,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
             // First, we instantiate each bound region in the supertype with a
             // fresh placeholder region.
             let (b_prime, placeholder_map) =
-                self.infcx.replace_late_bound_regions_with_placeholders(b);
+                self.infcx.replace_bound_vars_with_placeholders(b);
 
             // Next, we instantiate each bound region in the subtype
             // with a fresh region variable. These region variables --
@@ -115,7 +115,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
             // First, we instantiate each bound region in the matcher
             // with a placeholder region.
             let ((a_match, a_value), placeholder_map) =
-                self.infcx.replace_late_bound_regions_with_placeholders(a_pair);
+                self.infcx.replace_bound_vars_with_placeholders(a_pair);
 
             debug!("higher_ranked_match: a_match={:?}", a_match);
             debug!("higher_ranked_match: placeholder_map={:?}", placeholder_map);
@@ -314,10 +314,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         region_vars
     }
 
-    /// Replace all regions bound by `binder` with placeholder regions and
-    /// return a map indicating which bound-region was replaced with what
-    /// placeholder region. This is the first step of checking subtyping
-    /// when higher-ranked things are involved.
+    /// Replace all regions (resp. types) bound by `binder` with placeholder
+    /// regions (resp. types) and return a map indicating which bound-region
+    /// was replaced with what placeholder region. This is the first step of
+    /// checking subtyping when higher-ranked things are involved.
     ///
     /// **Important:** you must call this function from within a snapshot.
     /// Moreover, before committing the snapshot, you must eventually call
@@ -330,26 +330,37 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// the [rustc guide].
     ///
     /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
-    pub fn replace_late_bound_regions_with_placeholders<T>(
+    pub fn replace_bound_vars_with_placeholders<T>(
         &self,
-        binder: &ty::Binder<T>,
+        binder: &ty::Binder<T>
     ) -> (T, PlaceholderMap<'tcx>)
     where
-        T : TypeFoldable<'tcx>,
+        T: TypeFoldable<'tcx>
     {
         let next_universe = self.create_next_universe();
 
-        let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
-            self.tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
+        let fld_r = |br| {
+            self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
                 universe: next_universe,
                 name: br,
             }))
-        });
+        };
+
+        let fld_t = |bound_ty: ty::BoundTy| {
+            self.tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+                universe: next_universe,
+                name: bound_ty.var,
+            }))
+        };
+
+        let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t);
 
-        debug!("replace_late_bound_regions_with_placeholders(binder={:?}, result={:?}, map={:?})",
-               binder,
-               result,
-               map);
+        debug!(
+            "replace_bound_vars_with_placeholders(binder={:?}, result={:?}, map={:?})",
+            binder,
+            result,
+            map
+        );
 
         (result, map)
     }
@@ -530,7 +541,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
     /// Pops the placeholder regions found in `placeholder_map` from the region
     /// inference context. Whenever you create placeholder regions via
-    /// `replace_late_bound_regions_with_placeholders`, they must be popped before you
+    /// `replace_bound_vars_with_placeholders`, they must be popped before you
     /// commit the enclosing snapshot (if you do not commit, e.g. within a
     /// probe or as a result of an error, then this is not necessary, as
     /// popping happens as part of the rollback).
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 87e32be1a17..a29c85bd2b1 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -227,7 +227,7 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     universe: Cell<ty::UniverseIndex>,
 }
 
-/// A map returned by `replace_late_bound_regions_with_placeholders()`
+/// A map returned by `replace_bound_vars_with_placeholders()`
 /// indicating the placeholder region that each late-bound region was
 /// replaced with.
 pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
@@ -411,7 +411,7 @@ pub enum NLLRegionVariableOrigin {
 
     /// "Universal" instantiation of a higher-ranked region (e.g.,
     /// from a `for<'a> T` binder). Meant to represent "any region".
-    Placeholder(ty::Placeholder),
+    Placeholder(ty::PlaceholderRegion),
 
     Existential,
 }
@@ -935,7 +935,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     b,
                 },
                 placeholder_map,
-            ) = self.replace_late_bound_regions_with_placeholders(predicate);
+            ) = self.replace_bound_vars_with_placeholders(predicate);
 
             let cause_span = cause.span;
             let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
@@ -952,7 +952,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     ) -> UnitResult<'tcx> {
         self.commit_if_ok(|snapshot| {
             let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) =
-                self.replace_late_bound_regions_with_placeholders(predicate);
+                self.replace_bound_vars_with_placeholders(predicate);
             let origin = SubregionOrigin::from_obligation_cause(cause, || {
                 RelateRegionParamBound(cause.span)
             });
@@ -972,6 +972,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.tcx.mk_var(self.next_ty_var_id(false, origin))
     }
 
+    pub fn next_ty_var_in_universe(
+        &self,
+        origin: TypeVariableOrigin,
+        universe: ty::UniverseIndex
+    ) -> Ty<'tcx> {
+        let vid = self.type_variables
+            .borrow_mut()
+            .new_var(universe, false, origin);
+        self.tcx.mk_var(vid)
+    }
+
     pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
         self.tcx.mk_var(self.next_ty_var_id(true, origin))
     }
@@ -1227,6 +1238,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    /// If `TyVar(vid)` resolves to a type, return that type. Else, return the
+    /// universe index of `TyVar(vid)`.
+    pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
+        use self::type_variable::TypeVariableValue;
+
+        match self.type_variables.borrow_mut().probe(vid) {
+            TypeVariableValue::Known { value } => Ok(value),
+            TypeVariableValue::Unknown { universe } => Err(universe),
+        }
+    }
+
     pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
         self.inlined_shallow_resolve(typ)
     }
diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs
index e003c1989e0..9bdbf77fee0 100644
--- a/src/librustc/infer/nll_relate/mod.rs
+++ b/src/librustc/infer/nll_relate/mod.rs
@@ -95,7 +95,7 @@ pub trait TypeRelatingDelegate<'tcx> {
     /// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then
     /// we will invoke this method to instantiate `'b` with a
     /// placeholder region.
-    fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx>;
+    fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>;
 
     /// Creates a new existential region in the given universe. This
     /// is used when handling subtyping and type variables -- if we
@@ -176,7 +176,7 @@ where
                         universe
                     });
 
-                    let placeholder = ty::Placeholder { universe, name: br };
+                    let placeholder = ty::PlaceholderRegion { universe, name: br };
                     delegate.next_placeholder_region(placeholder)
                 } else {
                     delegate.next_existential_region_var()
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index bec19ba9099..5624961ea6e 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -72,7 +72,7 @@ pub type TypeVariableMap = FxHashMap<ty::TyVid, TypeVariableOrigin>;
 
 struct TypeVariableData {
     origin: TypeVariableOrigin,
-    diverging: bool
+    diverging: bool,
 }
 
 #[derive(Copy, Clone, Debug)]
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 71b77909b82..b7a84c99308 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -455,7 +455,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
             false
         }
 
-        ty::Bound(..) | ty::Infer(..) => match in_crate {
+        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match in_crate {
             InCrate::Local => false,
             // The inference variable might be unified with a local
             // type in that remote crate.
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 48b2b25d6ad..7e97dc3c84a 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -281,7 +281,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 ty::Generator(..) => Some(18),
                 ty::Foreign(..) => Some(19),
                 ty::GeneratorWitness(..) => Some(20),
-                ty::Bound(..) | ty::Infer(..) | ty::Error => None,
+                ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
                 ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
             }
         }
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index b59bd0e2388..e7b5fc3d1ff 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -204,7 +204,7 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>(
     let infcx = selcx.infcx();
     infcx.commit_if_ok(|snapshot| {
         let (placeholder_predicate, placeholder_map) =
-            infcx.replace_late_bound_regions_with_placeholders(&obligation.predicate);
+            infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
 
         let skol_obligation = obligation.with(placeholder_predicate);
         let r = match project_and_unify_type(selcx, &skol_obligation) {
@@ -424,7 +424,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
         if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.selcx.tcx().global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
-                if substs.needs_infer() || substs.has_skol() {
+                if substs.needs_infer() || substs.has_placeholders() {
                     let identity_substs = Substs::identity_for_item(tcx, def_id);
                     let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
                     if let Some(instance) = instance {
@@ -1656,7 +1656,7 @@ impl<'tcx> ProjectionCache<'tcx> {
     }
 
     pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) {
-        self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_skol());
+        self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_placeholders());
     }
 
     pub fn commit(&mut self, snapshot: &ProjectionCacheSnapshot) {
diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs
index 99dc099d577..b8bf0fcc153 100644
--- a/src/librustc/traits/query/dropck_outlives.rs
+++ b/src/librustc/traits/query/dropck_outlives.rs
@@ -251,6 +251,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
         | ty::Projection(..)
         | ty::Param(_)
         | ty::Opaque(..)
+        | ty::Placeholder(..)
         | ty::Infer(_)
         | ty::Bound(..)
         | ty::Generator(..) => false,
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 59b086e35de..91b2ba301c3 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -202,7 +202,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
         if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.infcx.tcx.global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
-                if substs.needs_infer() || substs.has_skol() {
+                if substs.needs_infer() || substs.has_placeholders() {
                     let identity_substs = Substs::identity_for_item(tcx, def_id);
                     let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
                     if let Some(instance) = instance {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 550c27ca0ab..0f59f478cb4 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1726,7 +1726,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let poly_trait_predicate = self.infcx()
             .resolve_type_vars_if_possible(&obligation.predicate);
         let (skol_trait_predicate, placeholder_map) = self.infcx()
-            .replace_late_bound_regions_with_placeholders(&poly_trait_predicate);
+            .replace_bound_vars_with_placeholders(&poly_trait_predicate);
         debug!(
             "match_projection_obligation_against_definition_bounds: \
              skol_trait_predicate={:?} placeholder_map={:?}",
@@ -2470,7 +2470,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
             ty::UnnormalizedProjection(..)
-            | ty::Bound(_)
+            | ty::Placeholder(..)
+            | ty::Bound(..)
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
             | ty::Infer(ty::FreshFloatTy(_)) => {
@@ -2555,7 +2556,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             }
 
             ty::UnnormalizedProjection(..)
-            | ty::Bound(_)
+            | ty::Placeholder(..)
+            | ty::Bound(..)
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
             | ty::Infer(ty::FreshFloatTy(_)) => {
@@ -2594,11 +2596,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             | ty::Char => Vec::new(),
 
             ty::UnnormalizedProjection(..)
+            | ty::Placeholder(..)
             | ty::Dynamic(..)
             | ty::Param(..)
             | ty::Foreign(..)
             | ty::Projection(..)
-            | ty::Bound(_)
+            | ty::Bound(..)
             | ty::Infer(ty::TyVar(_))
             | ty::Infer(ty::FreshTy(_))
             | ty::Infer(ty::FreshIntTy(_))
@@ -2682,7 +2685,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
                 self.in_snapshot(|this, snapshot| {
                     let (skol_ty, placeholder_map) = this.infcx()
-                        .replace_late_bound_regions_with_placeholders(&ty);
+                        .replace_bound_vars_with_placeholders(&ty);
                     let Normalized {
                         value: normalized_ty,
                         mut obligations,
@@ -2916,7 +2919,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         let trait_obligations: Vec<PredicateObligation<'_>> = self.in_snapshot(|this, snapshot| {
             let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
             let (trait_ref, placeholder_map) = this.infcx()
-                .replace_late_bound_regions_with_placeholders(&poly_trait_ref);
+                .replace_bound_vars_with_placeholders(&poly_trait_ref);
             let cause = obligation.derived_cause(ImplDerivedObligation);
             this.impl_or_trait_obligations(
                 cause,
@@ -3119,7 +3122,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         self.in_snapshot(|this, snapshot| {
             let (predicate, placeholder_map) = this.infcx()
-                .replace_late_bound_regions_with_placeholders(&obligation.predicate);
+                .replace_bound_vars_with_placeholders(&obligation.predicate);
             let trait_ref = predicate.trait_ref;
             let trait_def_id = trait_ref.def_id;
             let substs = trait_ref.substs;
@@ -3582,7 +3585,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
         }
 
         let (skol_obligation, placeholder_map) = self.infcx()
-            .replace_late_bound_regions_with_placeholders(&obligation.predicate);
+            .replace_bound_vars_with_placeholders(&obligation.predicate);
         let skol_obligation_trait_ref = skol_obligation.trait_ref;
 
         let impl_substs = self.infcx
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index 3e417f10c44..36538ac0889 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -324,7 +324,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
         use syntax::symbol::Symbol;
 
         match t.sty {
-            ty::Bound(bound_ty) if bound_ty.index == self.binder_index => {
+            ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
                 self.types.insert(
                     bound_ty.var.as_u32(),
                     match bound_ty.kind {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 1b947c276f3..22d5ea6e4bc 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -2243,7 +2243,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
-            Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
+            Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr, Placeholder,
             Generator, GeneratorWitness, Dynamic, Closure, Tuple, Bound,
             Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);
 
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 4737c72b1ef..90022a770c1 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -212,7 +212,8 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
             ty::Infer(ty::TyVar(_)) => "inferred type".into(),
             ty::Infer(ty::IntVar(_)) => "integral variable".into(),
             ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(),
-            ty::Bound(_) |
+            ty::Placeholder(..) => "placeholder type".into(),
+            ty::Bound(..) => "bound type".into(),
             ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
             ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index 380f95993f8..8304e363815 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -122,7 +122,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::Foreign(def_id) => {
             Some(ForeignSimplifiedType(def_id))
         }
-        ty::Bound(..) | ty::Infer(_) | ty::Error => None,
+        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) | ty::Error => None,
     }
 }
 
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 0764f363250..1ea7e27c0dc 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -115,8 +115,12 @@ impl FlagComputation {
                 self.add_substs(&substs.substs);
             }
 
-            &ty::Bound(bound_ty) => {
-                self.add_binder(bound_ty.index);
+            &ty::Bound(debruijn, _) => {
+                self.add_binder(debruijn);
+            }
+
+            &ty::Placeholder(..) => {
+                self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
             }
 
             &ty::Infer(infer) => {
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 2c781483145..6f0e8d4f026 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -102,14 +102,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
     fn needs_infer(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
     }
-    fn has_skol(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_RE_SKOL)
+    fn has_placeholders(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER | TypeFlags::HAS_TY_PLACEHOLDER)
     }
     fn needs_subst(&self) -> bool {
         self.has_type_flags(TypeFlags::NEEDS_SUBST)
     }
-    fn has_re_skol(&self) -> bool {
-        self.has_type_flags(TypeFlags::HAS_RE_SKOL)
+    fn has_re_placeholders(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER)
     }
     fn has_closure_types(&self) -> bool {
         self.has_type_flags(TypeFlags::HAS_TY_CLOSURE)
@@ -460,8 +460,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for BoundVarReplacer<'a, 'gcx, 'tcx>
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match t.sty {
-            ty::Bound(bound_ty) => {
-                if bound_ty.index == self.current_index {
+            ty::Bound(debruijn, bound_ty) => {
+                if debruijn == self.current_index {
                     let fld_t = &mut self.fld_t;
                     let ty = fld_t(bound_ty);
                     ty::fold::shift_vars(
@@ -526,7 +526,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
               T: TypeFoldable<'tcx>
     {
         // identity for bound types
-        let fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
+        let fld_t = |bound_ty| self.mk_ty(ty::Bound(ty::INNERMOST, bound_ty));
         self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t)
     }
 
@@ -722,16 +722,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Shifter<'a, 'gcx, 'tcx> {
 
     fn fold_ty(&mut self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> {
         match ty.sty {
-            ty::Bound(bound_ty) => {
-                if self.amount == 0 || bound_ty.index < self.current_index {
+            ty::Bound(debruijn, bound_ty) => {
+                if self.amount == 0 || debruijn < self.current_index {
                     ty
                 } else {
-                    let shifted = ty::BoundTy {
-                        index: bound_ty.index.shifted_in(self.amount),
-                        var: bound_ty.var,
-                        kind: bound_ty.kind,
-                    };
-                    self.tcx.mk_ty(ty::Bound(shifted))
+                    self.tcx.mk_ty(
+                        ty::Bound(debruijn.shifted_in(self.amount), bound_ty)
+                    )
                 }
             }
 
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index d44ba030841..f6c90ab0a1a 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -515,6 +515,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
         ty::Str |
         ty::FnPtr(_) |
         ty::Projection(_) |
+        ty::Placeholder(..) |
         ty::UnnormalizedProjection(..) |
         ty::Param(_) |
         ty::Opaque(..) |
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index da0a9acede2..5406495226d 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1159,6 +1159,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
             }
 
             ty::Bound(..) |
+            ty::Placeholder(..) |
             ty::UnnormalizedProjection(..) |
             ty::GeneratorWitness(..) |
             ty::Infer(_) => {
@@ -1743,7 +1744,8 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
             }
 
             ty::Projection(_) | ty::UnnormalizedProjection(..) | ty::Bound(..) |
-            ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => {
+            ty::Placeholder(..) | ty::Opaque(..) | ty::Param(_) | ty::Infer(_) |
+            ty::Error => {
                 bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
         })
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index ad200449f89..b371f4532e5 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -432,7 +432,7 @@ bitflags! {
         const HAS_SELF           = 1 << 1;
         const HAS_TY_INFER       = 1 << 2;
         const HAS_RE_INFER       = 1 << 3;
-        const HAS_RE_SKOL        = 1 << 4;
+        const HAS_RE_PLACEHOLDER = 1 << 4;
 
         /// Does this have any `ReEarlyBound` regions? Used to
         /// determine whether substitition is required, since those
@@ -467,6 +467,8 @@ bitflags! {
         /// if a global bound is safe to evaluate.
         const HAS_RE_LATE_BOUND = 1 << 13;
 
+        const HAS_TY_PLACEHOLDER = 1 << 14;
+
         const NEEDS_SUBST        = TypeFlags::HAS_PARAMS.bits |
                                    TypeFlags::HAS_SELF.bits |
                                    TypeFlags::HAS_RE_EARLY_BOUND.bits;
@@ -478,7 +480,7 @@ bitflags! {
                                   TypeFlags::HAS_SELF.bits |
                                   TypeFlags::HAS_TY_INFER.bits |
                                   TypeFlags::HAS_RE_INFER.bits |
-                                  TypeFlags::HAS_RE_SKOL.bits |
+                                  TypeFlags::HAS_RE_PLACEHOLDER.bits |
                                   TypeFlags::HAS_RE_EARLY_BOUND.bits |
                                   TypeFlags::HAS_FREE_REGIONS.bits |
                                   TypeFlags::HAS_TY_ERR.bits |
@@ -486,7 +488,8 @@ bitflags! {
                                   TypeFlags::HAS_TY_CLOSURE.bits |
                                   TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
                                   TypeFlags::KEEP_IN_LOCAL_TCX.bits |
-                                  TypeFlags::HAS_RE_LATE_BOUND.bits;
+                                  TypeFlags::HAS_RE_LATE_BOUND.bits |
+                                  TypeFlags::HAS_TY_PLACEHOLDER.bits;
     }
 }
 
@@ -1587,12 +1590,27 @@ impl UniverseIndex {
 /// universe are just two regions with an unknown relationship to one
 /// another.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
-pub struct Placeholder {
+pub struct Placeholder<T> {
     pub universe: UniverseIndex,
-    pub name: BoundRegion,
+    pub name: T,
+}
+
+impl<'a, 'gcx, T> HashStable<StableHashingContext<'a>> for Placeholder<T>
+    where T: HashStable<StableHashingContext<'a>>
+{
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>
+    ) {
+        self.universe.hash_stable(hcx, hasher);
+        self.name.hash_stable(hcx, hasher);
+    }
 }
 
-impl_stable_hash_for!(struct Placeholder { universe, name });
+pub type PlaceholderRegion = Placeholder<BoundRegion>;
+
+pub type PlaceholderType = Placeholder<BoundVar>;
 
 /// When type checking, we use the `ParamEnv` to track
 /// details about the set of where-clauses that are in scope at this
@@ -1674,7 +1692,7 @@ impl<'tcx> ParamEnv<'tcx> {
             }
 
             Reveal::All => {
-                if value.has_skol()
+                if value.has_placeholders()
                     || value.needs_infer()
                     || value.has_param_types()
                     || value.has_self_ty()
@@ -2430,6 +2448,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                 }
             }
 
+            Placeholder(..) |
             Bound(..) |
             Infer(..) => {
                 bug!("unexpected type `{:?}` in sized_constraint_for_ty",
diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs
index 7fac88a3d78..0e3fc62e4ca 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -155,6 +155,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             ty::FnDef(..) |       // OutlivesFunction (*)
             ty::FnPtr(_) |        // OutlivesFunction (*)
             ty::Dynamic(..) |       // OutlivesObject, OutlivesFragment (*)
+            ty::Placeholder(..) |
             ty::Bound(..) |
             ty::Error => {
                 // (*) Bare functions and traits are both binders. In the
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index e92f92dce63..d6aeb288b5c 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -746,6 +746,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::Infer(_) |
             ty::Param(..) |
             ty::Bound(..) |
+            ty::Placeholder(..) |
             ty::Never |
             ty::Foreign(..) => return self
         };
@@ -792,6 +793,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
             ty::Error |
             ty::Infer(_) |
             ty::Bound(..) |
+            ty::Placeholder(..) |
             ty::Param(..) |
             ty::Never |
             ty::Foreign(..) => false,
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index bd3a34cae90..3056abba956 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -201,7 +201,10 @@ pub enum TyKind<'tcx> {
     Param(ParamTy),
 
     /// Bound type variable, used only when preparing a trait query.
-    Bound(BoundTy),
+    Bound(ty::DebruijnIndex, BoundTy),
+
+    /// A placeholder type - universally quantified higher-ranked type.
+    Placeholder(ty::PlaceholderType),
 
     /// A type variable used during type checking.
     Infer(InferTy),
@@ -1165,7 +1168,7 @@ pub enum RegionKind {
 
     /// A placeholder region - basically the higher-ranked version of ReFree.
     /// Should not exist after typeck.
-    RePlaceholder(ty::Placeholder),
+    RePlaceholder(ty::PlaceholderRegion),
 
     /// Empty lifetime is for data that is never accessed.
     /// Bottom in the region lattice. We treat ReEmpty somewhat
@@ -1242,7 +1245,6 @@ newtype_index! {
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct BoundTy {
-    pub index: DebruijnIndex,
     pub var: BoundVar,
     pub kind: BoundTyKind,
 }
@@ -1253,13 +1255,12 @@ pub enum BoundTyKind {
     Param(InternedString),
 }
 
-impl_stable_hash_for!(struct BoundTy { index, var, kind });
+impl_stable_hash_for!(struct BoundTy { var, kind });
 impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) });
 
-impl BoundTy {
-    pub fn new(index: DebruijnIndex, var: BoundVar) -> Self {
+impl From<BoundVar> for BoundTy {
+    fn from(var: BoundVar) -> Self {
         BoundTy {
-            index,
             var,
             kind: BoundTyKind::Anon,
         }
@@ -1462,7 +1463,7 @@ impl RegionKind {
             }
             ty::RePlaceholder(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
-                flags = flags | TypeFlags::HAS_RE_SKOL;
+                flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
             }
             ty::ReLateBound(..) => {
                 flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
@@ -1890,6 +1891,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
             Foreign(..) |
             Param(_) |
             Bound(..) |
+            Placeholder(..) |
             Infer(_) |
             Error => {}
         }
@@ -1953,7 +1955,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
 
             ty::Infer(ty::TyVar(_)) => false,
 
-            ty::Bound(_) |
+            ty::Bound(..) |
+            ty::Placeholder(..) |
             ty::Infer(ty::FreshTy(_)) |
             ty::Infer(ty::FreshIntTy(_)) |
             ty::Infer(ty::FreshFloatTy(_)) =>
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index b7f1731ba44..34252039898 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -190,11 +190,12 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
         Substs::for_item(tcx, def_id, |param, _| {
             match param.kind {
                 ty::GenericParamDefKind::Type { .. } => {
-                    tcx.mk_ty(ty::Bound(ty::BoundTy {
-                        index: ty::INNERMOST,
-                        var: ty::BoundVar::from(param.index),
-                        kind: ty::BoundTyKind::Param(param.name),
-                    })).into()
+                    tcx.mk_ty(
+                        ty::Bound(ty::INNERMOST, ty::BoundTy {
+                            var: ty::BoundVar::from(param.index),
+                            kind: ty::BoundTyKind::Param(param.name),
+                        })
+                    ).into()
                 }
 
                 ty::GenericParamDefKind::Lifetime => {
@@ -584,18 +585,18 @@ impl CanonicalUserSubsts<'tcx> {
         self.value.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| {
             match kind.unpack() {
                 UnpackedKind::Type(ty) => match ty.sty {
-                    ty::Bound(b) => {
+                    ty::Bound(debruijn, b) => {
                         // We only allow a `ty::INNERMOST` index in substitutions.
-                        assert_eq!(b.index, ty::INNERMOST);
+                        assert_eq!(debruijn, ty::INNERMOST);
                         cvar == b.var
                     }
                     _ => false,
                 },
 
                 UnpackedKind::Lifetime(r) => match r {
-                    ty::ReLateBound(index, br) => {
+                    ty::ReLateBound(debruijn, br) => {
                         // We only allow a `ty::INNERMOST` index in substitutions.
-                        assert_eq!(*index, ty::INNERMOST);
+                        assert_eq!(*debruijn, ty::INNERMOST);
                         cvar == br.assert_bound_var()
                     }
                     _ => false,
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 3d0c54d6b0a..f0885f96051 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -952,7 +952,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Can refer to a type which may drop.
         // FIXME(eddyb) check this against a ParamEnv.
         ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) |
-        ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
+        ty::Placeholder(..) | ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
 
         ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
 
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index 284c595ee2d..82b95b9df60 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -82,7 +82,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
     match parent_ty.sty {
         ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) |
         ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error |
-        ty::Bound(..) | ty::Foreign(..) => {
+        ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => {
         }
         ty::Array(ty, len) => {
             push_const(stack, len);
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 1336eac63f8..6ae0793d924 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -259,6 +259,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
                 ty::Never |
                 ty::Param(_) |
                 ty::Bound(..) |
+                ty::Placeholder(..) |
                 ty::Foreign(..) => {
                     // WfScalar, WfParameter, etc
                 }
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index d53370d242b..eea3b54919d 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -18,7 +18,7 @@ use ty::{Bool, Char, Adt};
 use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
 use ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
 use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
-use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer};
+use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
 use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
 use util::nodemap::FxHashSet;
 
@@ -792,7 +792,7 @@ define_print! {
                 }
                 ty::ReLateBound(_, br) |
                 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
-                ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+                ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
                     write!(f, "{}", br)
                 }
                 ty::ReScope(scope) if cx.identify_regions => {
@@ -1110,13 +1110,13 @@ define_print! {
                 Infer(infer_ty) => write!(f, "{}", infer_ty),
                 Error => write!(f, "[type error]"),
                 Param(ref param_ty) => write!(f, "{}", param_ty),
-                Bound(bound_ty) => {
+                Bound(debruijn, bound_ty) => {
                     match bound_ty.kind {
                         ty::BoundTyKind::Anon => {
-                            if bound_ty.index == ty::INNERMOST {
+                            if debruijn == ty::INNERMOST {
                                 write!(f, "^{}", bound_ty.var.index())
                             } else {
-                                write!(f, "^{}_{}", bound_ty.index.index(), bound_ty.var.index())
+                                write!(f, "^{}_{}", debruijn.index(), bound_ty.var.index())
                             }
                         }
 
@@ -1144,6 +1144,9 @@ define_print! {
                     data.print(f, cx)?;
                     write!(f, ")")
                 }
+                Placeholder(placeholder) => {
+                    write!(f, "Placeholder({:?})", placeholder)
+                }
                 Opaque(def_id, substs) => {
                     if cx.is_verbose {
                         return write!(f, "Opaque({:?}, {:?})", def_id, substs);
diff --git a/src/librustc_codegen_llvm/debuginfo/type_names.rs b/src/librustc_codegen_llvm/debuginfo/type_names.rs
index c3a15ccca0a..60545f9e193 100644
--- a/src/librustc_codegen_llvm/debuginfo/type_names.rs
+++ b/src/librustc_codegen_llvm/debuginfo/type_names.rs
@@ -172,6 +172,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         }
         ty::Error |
         ty::Infer(_) |
+        ty::Placeholder(..) |
         ty::UnnormalizedProjection(..) |
         ty::Projection(..) |
         ty::Bound(..) |
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 0e2d041b1ff..82ace620c8a 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -727,6 +727,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             ty::Closure(..) |
             ty::Generator(..) |
             ty::GeneratorWitness(..) |
+            ty::Placeholder(..) |
             ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
             ty::Opaque(..) |
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 3c4d8e09fc1..4ccd26bee8b 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -2193,7 +2193,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
         match ty.sty {
             ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
             | ty::TyKind::Ref(
-                ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }),
+                ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
                 _,
                 _,
             ) => with_highlight_region_for_bound_region(*br, counter, || ty.to_string()),
@@ -2207,7 +2207,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
         match ty.sty {
             ty::TyKind::Ref(region, _, _) => match region {
                 ty::RegionKind::ReLateBound(_, br)
-                | ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+                | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
                     with_highlight_region_for_bound_region(*br, counter, || region.to_string())
                 }
                 _ => region.to_string(),
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 376f4459242..6a1dc50c67a 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1230,7 +1230,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         mir: &Mir<'tcx>,
         _mir_def_id: DefId,
         longer_fr: RegionVid,
-        placeholder: ty::Placeholder,
+        placeholder: ty::PlaceholderRegion,
     ) {
         debug!(
             "check_bound_universal_region(fr={:?}, placeholder={:?})",
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
index 2b7ef38d3ed..69e2c896d33 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs
@@ -150,7 +150,7 @@ crate enum RegionElement {
 
     /// A placeholder (e.g., instantiated from a `for<'a> fn(&'a u32)`
     /// type).
-    PlaceholderRegion(ty::Placeholder),
+    PlaceholderRegion(ty::PlaceholderRegion),
 }
 
 /// When we initially compute liveness, we use a bit matrix storing
@@ -219,17 +219,17 @@ impl<N: Idx> LivenessValues<N> {
     }
 }
 
-/// Maps from `ty::Placeholder` values that are used in the rest of
+/// Maps from `ty::PlaceholderRegion` values that are used in the rest of
 /// rustc to the internal `PlaceholderIndex` values that are used in
 /// NLL.
 #[derive(Default)]
 crate struct PlaceholderIndices {
-    to_index: FxHashMap<ty::Placeholder, PlaceholderIndex>,
-    from_index: IndexVec<PlaceholderIndex, ty::Placeholder>,
+    to_index: FxHashMap<ty::PlaceholderRegion, PlaceholderIndex>,
+    from_index: IndexVec<PlaceholderIndex, ty::PlaceholderRegion>,
 }
 
 impl PlaceholderIndices {
-    crate fn insert(&mut self, placeholder: ty::Placeholder) -> PlaceholderIndex {
+    crate fn insert(&mut self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex {
         let PlaceholderIndices {
             to_index,
             from_index,
@@ -239,11 +239,11 @@ impl PlaceholderIndices {
             .or_insert_with(|| from_index.push(placeholder))
     }
 
-    crate fn lookup_index(&self, placeholder: ty::Placeholder) -> PlaceholderIndex {
+    crate fn lookup_index(&self, placeholder: ty::PlaceholderRegion) -> PlaceholderIndex {
         self.to_index[&placeholder]
     }
 
-    crate fn lookup_placeholder(&self, placeholder: PlaceholderIndex) -> ty::Placeholder {
+    crate fn lookup_placeholder(&self, placeholder: PlaceholderIndex) -> ty::PlaceholderRegion {
         self.from_index[placeholder]
     }
 
@@ -375,7 +375,7 @@ impl<N: Idx> RegionValues<N> {
     crate fn placeholders_contained_in<'a>(
         &'a self,
         r: N,
-    ) -> impl Iterator<Item = ty::Placeholder> + 'a {
+    ) -> impl Iterator<Item = ty::PlaceholderRegion> + 'a {
         self.placeholders
             .row(r)
             .into_iter()
@@ -432,7 +432,7 @@ impl ToElementIndex for RegionVid {
     }
 }
 
-impl ToElementIndex for ty::Placeholder {
+impl ToElementIndex for ty::PlaceholderRegion {
     fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
         let index = values.placeholder_indices.lookup_index(self);
         values.placeholders.insert(row, index)
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index b978d8c9d0a..5f64dfd931c 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -777,7 +777,7 @@ impl MirTypeckRegionConstraints<'tcx> {
     fn placeholder_region(
         &mut self,
         infcx: &InferCtxt<'_, '_, 'tcx>,
-        placeholder: ty::Placeholder,
+        placeholder: ty::PlaceholderRegion,
     ) -> ty::Region<'tcx> {
         let placeholder_index = self.placeholder_indices.insert(placeholder);
         match self.placeholder_index_to_region.get(placeholder_index) {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
index b82efb29f6e..cf4f9130807 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
@@ -84,7 +84,10 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> {
         }
     }
 
-    fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx> {
+    fn next_placeholder_region(
+        &mut self,
+        placeholder: ty::PlaceholderRegion
+    ) -> ty::Region<'tcx> {
         if let Some(borrowck_context) = &mut self.borrowck_context {
             borrowck_context.constraints.placeholder_region(self.infcx, placeholder)
         } else {
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 9c90e5ffd3c..24de92e79f0 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -378,6 +378,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
             ty::Error |
             ty::Bound(..) |
             ty::Infer(_) |
+            ty::Placeholder(..) |
             ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
             ty::Param(_) |
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
index 0fd9f607a54..25a6af284b5 100644
--- a/src/librustc_traits/chalk_context/mod.rs
+++ b/src/librustc_traits/chalk_context/mod.rs
@@ -11,7 +11,7 @@
 mod program_clauses;
 
 use chalk_engine::fallible::Fallible as ChalkEngineFallible;
-use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause};
+use chalk_engine::{context, hh::HhGoal, DelayedLiteral, Literal, ExClause};
 use rustc::infer::canonical::{
     Canonical, CanonicalVarValues, OriginalQueryValues, QueryRegionConstraint, QueryResponse,
 };
@@ -28,7 +28,7 @@ use rustc::traits::{
     InEnvironment,
 };
 use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use rustc::ty::subst::Kind;
+use rustc::ty::subst::{Kind, UnpackedKind};
 use rustc::ty::{self, TyCtxt};
 
 use std::fmt::{self, Debug};
@@ -44,7 +44,7 @@ crate struct ChalkArenas<'gcx> {
 #[derive(Copy, Clone)]
 crate struct ChalkContext<'cx, 'gcx: 'cx> {
     _arenas: ChalkArenas<'gcx>,
-    _tcx: TyCtxt<'cx, 'gcx, 'gcx>,
+    tcx: TyCtxt<'cx, 'gcx, 'gcx>,
 }
 
 #[derive(Copy, Clone)]
@@ -68,7 +68,7 @@ BraceStructTypeFoldableImpl! {
 }
 
 impl context::Context for ChalkArenas<'tcx> {
-    type CanonicalExClause = Canonical<'tcx, ExClause<Self>>;
+    type CanonicalExClause = Canonical<'tcx, ChalkExClause<'tcx>>;
 
     type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
 
@@ -147,19 +147,29 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
     /// - the environment and goal found by substitution `S` into `arg`
     fn instantiate_ucanonical_goal<R>(
         &self,
-        _arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-        _op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
+        arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+        op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
     ) -> R {
-        unimplemented!()
+        self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, arg, |ref infcx, arg, subst| {
+            let chalk_infcx = &mut ChalkInferenceContext {
+                infcx,
+            };
+            op.with(chalk_infcx, subst, arg.environment, arg.goal)
+        })
     }
 
     fn instantiate_ex_clause<R>(
         &self,
         _num_universes: usize,
-        _canonical_ex_clause: &Canonical<'gcx, ChalkExClause<'gcx>>,
-        _op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
+        arg: &Canonical<'gcx, ChalkExClause<'gcx>>,
+        op: impl context::WithInstantiatedExClause<ChalkArenas<'gcx>, Output = R>,
     ) -> R {
-        unimplemented!()
+        self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &arg.upcast(), |ref infcx, arg, _| {
+            let chalk_infcx = &mut ChalkInferenceContext {
+                infcx,
+            };
+            op.with(chalk_infcx,arg)
+        })
     }
 
     /// True if this solution has no region constraints.
@@ -186,14 +196,33 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
     }
 
     fn is_trivial_substitution(
-        _u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
-        _canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
+        u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
+        canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
     ) -> bool {
-        unimplemented!()
-    }
-
-    fn num_universes(_: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
-        0 // FIXME
+        let subst = &canonical_subst.value.subst;
+        assert_eq!(u_canon.variables.len(), subst.var_values.len());
+        subst.var_values
+            .iter_enumerated()
+            .all(|(cvar, kind)| match kind.unpack() {
+                UnpackedKind::Lifetime(r) => match r {
+                    &ty::ReLateBound(debruijn, br) => {
+                        debug_assert_eq!(debruijn, ty::INNERMOST);
+                        cvar == br.assert_bound_var()
+                    }
+                    _ => false,
+                },
+                UnpackedKind::Type(ty) => match ty.sty {
+                    ty::Bound(debruijn, bound_ty) => {
+                        debug_assert_eq!(debruijn, ty::INNERMOST);
+                        cvar == bound_ty.var
+                    }
+                    _ => false,
+                },
+            })
+    }
+
+    fn num_universes(canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
+        canon.max_universe.index() + 1
     }
 
     /// Convert a goal G *from* the canonical universes *into* our
@@ -214,39 +243,6 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
     }
 }
 
-//impl context::UCanonicalGoalInEnvironment<ChalkContext<'cx, 'gcx>>
-//    for Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>
-//{
-//    fn canonical(&self) -> &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
-//        self
-//    }
-//
-//    fn is_trivial_substitution(
-//        &self,
-//        canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>,
-//    ) -> bool {
-//        let subst = &canonical_subst.value.subst;
-//        assert_eq!(self.canonical.variables.len(), subst.var_values.len());
-//        subst
-//            .var_values
-//            .iter_enumerated()
-//            .all(|(cvar, kind)| match kind.unpack() {
-//                Kind::Lifetime(r) => match r {
-//                    ty::ReCanonical(cvar1) => cvar == cvar1,
-//                    _ => false,
-//                },
-//                Kind::Type(ty) => match ty.sty {
-//                    ty::Infer(ty::InferTy::CanonicalTy(cvar1)) => cvar == cvar1,
-//                    _ => false,
-//                },
-//            })
-//    }
-//
-//    fn num_universes(&self) -> usize {
-//        0 // FIXME
-//    }
-//}
-
 impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
     for ChalkInferenceContext<'cx, 'gcx, 'tcx>
 {
@@ -260,7 +256,10 @@ impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
 
     fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> {
         match *goal {
-            GoalKind::Implies(..) => panic!("FIXME rust-lang-nursery/chalk#94"),
+            GoalKind::Implies(hypotheses, goal) => HhGoal::Implies(
+                hypotheses.iter().cloned().collect(),
+                goal
+            ),
             GoalKind::And(left, right) => HhGoal::And(left, right),
             GoalKind::Not(subgoal) => HhGoal::Not(subgoal),
             GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d),
@@ -338,9 +337,9 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
 
     fn instantiate_binders_universally(
         &mut self,
-        _arg: &ty::Binder<Goal<'tcx>>,
+        arg: &ty::Binder<Goal<'tcx>>,
     ) -> Goal<'tcx> {
-        panic!("FIXME -- universal instantiation needs sgrif's branch")
+        self.infcx.replace_bound_vars_with_placeholders(arg).0
     }
 
     fn instantiate_binders_existentially(
@@ -491,3 +490,68 @@ BraceStructLiftImpl! {
         subst, constraints
     }
 }
+
+trait Upcast<'tcx, 'gcx: 'tcx>: 'gcx {
+    type Upcasted: 'tcx;
+
+    fn upcast(&self) -> Self::Upcasted;
+}
+
+impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for DelayedLiteral<ChalkArenas<'gcx>> {
+    type Upcasted = DelayedLiteral<ChalkArenas<'tcx>>;
+
+    fn upcast(&self) -> Self::Upcasted {
+        match self {
+            &DelayedLiteral::CannotProve(..) => DelayedLiteral::CannotProve(()),
+            &DelayedLiteral::Negative(index) => DelayedLiteral::Negative(index),
+            DelayedLiteral::Positive(index, subst) => DelayedLiteral::Positive(
+                *index,
+                subst.clone()
+            ),
+        }
+    }
+}
+
+impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for Literal<ChalkArenas<'gcx>> {
+    type Upcasted = Literal<ChalkArenas<'tcx>>;
+
+    fn upcast(&self) -> Self::Upcasted {
+        match self {
+            &Literal::Negative(goal) => Literal::Negative(goal),
+            &Literal::Positive(goal) => Literal::Positive(goal),
+        }
+    }
+}
+
+impl<'tcx, 'gcx: 'tcx> Upcast<'tcx, 'gcx> for ExClause<ChalkArenas<'gcx>> {
+    type Upcasted = ExClause<ChalkArenas<'tcx>>;
+
+    fn upcast(&self) -> Self::Upcasted {
+        ExClause {
+            subst: self.subst.clone(),
+            delayed_literals: self.delayed_literals
+                .iter()
+                .map(|l| l.upcast())
+                .collect(),
+            constraints: self.constraints.clone(),
+            subgoals: self.subgoals
+                .iter()
+                .map(|g| g.upcast())
+                .collect(),
+        }
+    }
+}
+
+impl<'tcx, 'gcx: 'tcx, T> Upcast<'tcx, 'gcx> for Canonical<'gcx, T>
+    where T: Upcast<'tcx, 'gcx>
+{
+    type Upcasted = Canonical<'tcx, T::Upcasted>;
+
+    fn upcast(&self) -> Self::Upcasted {
+        Canonical {
+            max_universe: self.max_universe,
+            value: self.value.upcast(),
+            variables: self.variables,
+        }
+    }
+}
diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs
index 31f97b72e19..b8670e5e914 100644
--- a/src/librustc_traits/chalk_context/program_clauses.rs
+++ b/src/librustc_traits/chalk_context/program_clauses.rs
@@ -59,7 +59,8 @@ fn assemble_clauses_from_assoc_ty_values<'tcx>(
 
 fn program_clauses_for_raw_ptr<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
     let ty = ty::Bound(
-        ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+        ty::INNERMOST,
+        ty::BoundVar::from_u32(0).into()
     );
     let ty = tcx.mk_ty(ty);
 
@@ -88,9 +89,9 @@ fn program_clauses_for_fn_ptr<'tcx>(
 ) -> Clauses<'tcx> {
     let inputs_and_output = tcx.mk_type_list(
         (0..arity_and_output).into_iter()
+            .map(|i| ty::BoundVar::from(i))
             // DebruijnIndex(1) because we are going to inject these in a `PolyFnSig`
-            .map(|i| ty::BoundTy::new(ty::DebruijnIndex::from(1usize), ty::BoundVar::from(i)))
-            .map(|t| tcx.mk_ty(ty::Bound(t)))
+            .map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into())))
     );
 
     let fn_sig = ty::Binder::bind(ty::FnSig {
@@ -115,7 +116,8 @@ fn program_clauses_for_fn_ptr<'tcx>(
 
 fn program_clauses_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
     let ty = ty::Bound(
-        ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+        ty::INNERMOST,
+        ty::BoundVar::from_u32(0).into()
     );
     let ty = tcx.mk_ty(ty);
 
@@ -151,7 +153,8 @@ fn program_clauses_for_array<'tcx>(
     length: &'tcx ty::Const<'tcx>
 ) -> Clauses<'tcx> {
     let ty = ty::Bound(
-        ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(0))
+        ty::INNERMOST,
+        ty::BoundVar::from_u32(0).into()
     );
     let ty = tcx.mk_ty(ty);
 
@@ -188,8 +191,8 @@ fn program_clauses_for_tuple<'tcx>(
 ) -> Clauses<'tcx> {
     let type_list = tcx.mk_type_list(
         (0..arity).into_iter()
-            .map(|i| ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from(i)))
-            .map(|t| tcx.mk_ty(ty::Bound(t)))
+            .map(|i| ty::BoundVar::from(i))
+            .map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into())))
     );
 
     let tuple_ty = tcx.mk_ty(ty::Tuple(type_list));
@@ -233,7 +236,7 @@ fn program_clauses_for_ref<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx>
         ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
     );
     let ty = tcx.mk_ty(
-        ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1)))
+        ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into())
     );
 
     let ref_ty = tcx.mk_ref(region, ty::TypeAndMut {
@@ -418,6 +421,7 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
                     }
 
                     ty::GeneratorWitness(..) |
+                    ty::Placeholder(..) |
                     ty::UnnormalizedProjection(..) |
                     ty::Infer(..) |
                     ty::Bound(..) |
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index af64522f183..9ab86daf654 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -274,7 +274,7 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
 
         ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
 
-        ty::Bound(..) | ty::Infer(..) | ty::Error => {
+        ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
             Err(NoSolution)
diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs
index 54f0c6e8da7..519b0ac6105 100644
--- a/src/librustc_traits/lowering/environment.rs
+++ b/src/librustc_traits/lowering/environment.rs
@@ -55,7 +55,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
                     ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))
                 );
                 let ty = self.tcx.mk_ty(
-                    ty::Bound(ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(1)))
+                    ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(1).into())
                 );
 
                 let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
@@ -114,6 +114,7 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
             ty::Tuple(..) |
             ty::Never |
             ty::Infer(..) |
+            ty::Placeholder(..) |
             ty::Bound(..) => (),
 
             ty::GeneratorWitness(..) |
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index cf1bc04dd4e..2d8e5b48aac 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -515,7 +515,8 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
         .unwrap_or(0);
     // Add a new type param after the existing ones (`U` in the comment above).
     let ty_var = ty::Bound(
-        ty::BoundTy::new(ty::INNERMOST, ty::BoundVar::from_u32(offset + 1))
+        ty::INNERMOST,
+        ty::BoundVar::from_u32(offset + 1).into()
     );
 
     // `ProjectionEq(<Self as Trait<P1..Pn>>::AssocType<Pn+1..Pm> = U)`
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 3f0a3531244..c35aee7883f 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
             ty::Param(ref p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
-            ty::Bound(..) | ty::Infer(_) => None,
+            ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None,
 
             ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
             ty::Float(_) | ty::Array(..) | ty::GeneratorWitness(..) |
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 0373bf4e752..5b67116cb51 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1494,7 +1494,7 @@ impl<'tcx> Candidate<'tcx> {
                     // `WhereClausePick`.
                     assert!(
                         !trait_ref.skip_binder().substs.needs_infer()
-                            && !trait_ref.skip_binder().substs.has_skol()
+                            && !trait_ref.skip_binder().substs.has_placeholders()
                     );
 
                     WhereClausePick(trait_ref.clone())
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 50f54bba3fd..669f2bcb77c 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -115,7 +115,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
 
     fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) {
         debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty);
-        assert!(!ty.needs_infer() && !ty.has_skol());
+        assert!(!ty.needs_infer() && !ty.has_placeholders());
         self.tables.node_types_mut().insert(hir_id, ty);
     }
 
@@ -580,7 +580,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) {
             let substs = self.resolve(&substs, &span);
             debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs);
-            assert!(!substs.needs_infer() && !substs.has_skol());
+            assert!(!substs.needs_infer() && !substs.has_placeholders());
             self.tables.node_substs_mut().insert(hir_id, substs);
         }
 
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 47d34c90996..ed32e5a8d9b 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -336,6 +336,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 // types, where we use Error as the Self type
             }
 
+            ty::Placeholder(..) |
             ty::UnnormalizedProjection(..) |
             ty::GeneratorWitness(..) |
             ty::Bound(..) |
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 0518d73e1e3..fd8f70b19e7 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2744,6 +2744,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
 
             ty::Bound(..) => panic!("Bound"),
+            ty::Placeholder(..) => panic!("Placeholder"),
             ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
             ty::Infer(..) => panic!("Infer"),
diff --git a/src/test/run-pass/rustc-rust-log.rs b/src/test/run-pass/rustc-rust-log.rs
index 8c3e4b391e9..10e91e71fe2 100644
--- a/src/test/run-pass/rustc-rust-log.rs
+++ b/src/test/run-pass/rustc-rust-log.rs
@@ -16,6 +16,7 @@
 //
 // dont-check-compiler-stdout
 // dont-check-compiler-stderr
+// compile-flags: --error-format human
 
 // rustc-env:RUST_LOG=debug
 
diff --git a/src/test/ui/nll/user-annotations/dump-fn-method.stderr b/src/test/ui/nll/user-annotations/dump-fn-method.stderr
index 359423d0cfb..c963625c961 100644
--- a/src/test/ui/nll/user-annotations/dump-fn-method.stderr
+++ b/src/test/ui/nll/user-annotations/dump-fn-method.stderr
@@ -4,7 +4,7 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs
 LL |     let x = foo::<u32>; //~ ERROR [u32]
    |             ^^^^^^^^^^
 
-error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } }
+error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General(U0)) }, CanonicalVarInfo { kind: Ty(General(U0)) }], value: UserSubsts { substs: [^0, u32, ^1], user_self_ty: None } }
   --> $DIR/dump-fn-method.rs:42:13
    |
 LL |     let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
@@ -16,7 +16,7 @@ error: user substs: Canonical { max_universe: U0, variables: [], value: UserSubs
 LL |     let x = <u8 as Bazoom<u16>>::method::<u32>; //~ ERROR [u8, u16, u32]
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: user substs: Canonical { max_universe: U0, variables: [CanonicalVarInfo { kind: Ty(General) }, CanonicalVarInfo { kind: Ty(General) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } }
+error: user substs: Canonical { max_universe: U1, variables: [CanonicalVarInfo { kind: Ty(General(U1)) }, CanonicalVarInfo { kind: Ty(General(U1)) }], value: UserSubsts { substs: [^0, ^1, u32], user_self_ty: None } }
   --> $DIR/dump-fn-method.rs:54:5
    |
 LL |     y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]