]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #55101 - alexreg:trait-aliases, r=nikomatsakis
authorbors <bors@rust-lang.org>
Sat, 3 Nov 2018 17:30:37 +0000 (17:30 +0000)
committerbors <bors@rust-lang.org>
Sat, 3 Nov 2018 17:30:37 +0000 (17:30 +0000)
Implement trait aliases (RFC 1733)

Extends groundwork done in https://github.com/rust-lang/rust/pull/45047, and fully implements https://github.com/rust-lang/rfcs/pull/1733.

CC @durka @nikomatsakis

1  2 
src/librustc/ich/impls_ty.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/select.rs
src/librustc/ty/instance.rs
src/librustc/ty/mod.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/collect.rs

index a93e31480f3bbb5a4b3952e317a5a7caffe36c17,091ea9f52ff6249047c9d446d37e07df53b6f251..7d25ecedb4e046de7389bc32359f47dbd45dfc5f
@@@ -100,6 -100,9 +100,6 @@@ for ty::RegionKind 
              ty::ReEmpty => {
                  // No variant fields to hash for these ...
              }
 -            ty::ReCanonical(c) => {
 -                c.hash_stable(hcx, hasher);
 -            }
              ty::ReLateBound(db, ty::BrAnon(i)) => {
                  db.hash_stable(hcx, hasher);
                  i.hash_stable(hcx, hasher);
@@@ -144,7 -147,7 +144,7 @@@ impl<'a> HashStable<StableHashingContex
      }
  }
  
 -impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundTyIndex {
 +impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::BoundVar {
      #[inline]
      fn hash_stable<W: StableHasherResult>(&self,
                                            hcx: &mut StableHashingContext<'gcx>,
@@@ -849,9 -852,6 +849,9 @@@ for ty::TyKind<'gcx
              Param(param_ty) => {
                  param_ty.hash_stable(hcx, hasher);
              }
 +            Bound(bound_ty) => {
 +                bound_ty.hash_stable(hcx, hasher);
 +            }
              Foreign(def_id) => {
                  def_id.hash_stable(hcx, hasher);
              }
@@@ -869,6 -869,7 +869,6 @@@ impl_stable_hash_for!(enum ty::InferTy 
      FreshTy(a),
      FreshIntTy(a),
      FreshFloatTy(a),
 -    BoundTy(a),
  });
  
  impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
@@@ -1118,6 -1119,7 +1118,7 @@@ for traits::Vtable<'gcx, N> where N: Ha
              &VtableClosure(ref table_closure) => table_closure.hash_stable(hcx, hasher),
              &VtableFnPointer(ref table_fn_pointer) => table_fn_pointer.hash_stable(hcx, hasher),
              &VtableGenerator(ref table_generator) => table_generator.hash_stable(hcx, hasher),
+             &VtableTraitAlias(ref table_alias) => table_alias.hash_stable(hcx, hasher),
          }
      }
  }
@@@ -1226,6 -1228,22 +1227,22 @@@ for traits::VtableGeneratorData<'gcx, N
      }
  }
  
+ impl<'a, 'gcx, N> HashStable<StableHashingContext<'a>>
+ for traits::VtableTraitAliasData<'gcx, N> where N: HashStable<StableHashingContext<'a>> {
+     fn hash_stable<W: StableHasherResult>(&self,
+                                           hcx: &mut StableHashingContext<'a>,
+                                           hasher: &mut StableHasher<W>) {
+         let traits::VtableTraitAliasData {
+             alias_def_id,
+             substs,
+             ref nested,
+         } = *self;
+         alias_def_id.hash_stable(hcx, hasher);
+         substs.hash_stable(hcx, hasher);
+         nested.hash_stable(hcx, hasher);
+     }
+ }
  impl_stable_hash_for!(
      impl<'tcx, V> for struct infer::canonical::Canonical<'tcx, V> {
          max_universe, variables, value
index 5e2f1fe08b90e04acf57fad8aedc764f259a246a,6b8d66c6fc6298f3b48354f494ea9cff07da1515..b7512790bfb6913414c2e4d34c618b56c9012f19
@@@ -352,7 -352,7 +352,7 @@@ impl<'tcx> GoalKind<'tcx> 
          domain_goal: PolyDomainGoal<'tcx>,
          tcx: TyCtxt<'a, 'tcx, 'tcx>,
      ) -> GoalKind<'tcx> {
 -        match domain_goal.no_late_bound_regions() {
 +        match domain_goal.no_bound_vars() {
              Some(p) => p.into_goal(),
              None => GoalKind::Quantified(
                  QuantifierKind::Universal,
@@@ -534,8 -534,11 +534,11 @@@ pub enum Vtable<'tcx, N> 
      /// Same as above, but for a fn pointer type with the given signature.
      VtableFnPointer(VtableFnPointerData<'tcx, N>),
  
-     /// Vtable automatically generated for a generator
+     /// Vtable automatically generated for a generator.
      VtableGenerator(VtableGeneratorData<'tcx, N>),
+     /// Vtable for a trait alias.
+     VtableTraitAlias(VtableTraitAliasData<'tcx, N>),
  }
  
  /// Identifies a particular impl in the source, along with a set of
@@@ -605,6 -608,13 +608,13 @@@ pub struct VtableFnPointerData<'tcx, N
      pub nested: Vec<N>
  }
  
+ #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+ pub struct VtableTraitAliasData<'tcx, N> {
+     pub alias_def_id: DefId,
+     pub substs: &'tcx Substs<'tcx>,
+     pub nested: Vec<N>,
+ }
  /// Creates predicate obligations from the generic bounds.
  pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
                                       param_env: ty::ParamEnv<'tcx>,
@@@ -1067,6 -1077,7 +1077,7 @@@ impl<'tcx, N> Vtable<'tcx, N> 
              VtableGenerator(c) => c.nested,
              VtableObject(d) => d.nested,
              VtableFnPointer(d) => d.nested,
+             VtableTraitAlias(d) => d.nested,
          }
      }
  
                  trait_def_id: d.trait_def_id,
                  nested: d.nested.into_iter().map(f).collect(),
              }),
-             VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
-                 fn_ty: p.fn_ty,
-                 nested: p.nested.into_iter().map(f).collect(),
+             VtableClosure(c) => VtableClosure(VtableClosureData {
+                 closure_def_id: c.closure_def_id,
+                 substs: c.substs,
+                 nested: c.nested.into_iter().map(f).collect(),
              }),
              VtableGenerator(c) => VtableGenerator(VtableGeneratorData {
                  generator_def_id: c.generator_def_id,
                  substs: c.substs,
                  nested: c.nested.into_iter().map(f).collect(),
              }),
-             VtableClosure(c) => VtableClosure(VtableClosureData {
-                 closure_def_id: c.closure_def_id,
-                 substs: c.substs,
-                 nested: c.nested.into_iter().map(f).collect(),
-             })
+             VtableFnPointer(p) => VtableFnPointer(VtableFnPointerData {
+                 fn_ty: p.fn_ty,
+                 nested: p.nested.into_iter().map(f).collect(),
+             }),
+             VtableTraitAlias(d) => VtableTraitAlias(VtableTraitAliasData {
+                 alias_def_id: d.alias_def_id,
+                 substs: d.substs,
+                 nested: d.nested.into_iter().map(f).collect(),
+             }),
          }
      }
  }
index 80358294d056c535cadcdf9999b0f9eefeef69ab,b7754ae4fc58df9edeb39e4356b06452f5ebd831..a388c7eeb7e49ede897bbe130ffc07ffd4071d93
@@@ -19,10 -19,7 +19,7 @@@ use super::PredicateObligation
  use super::Selection;
  use super::SelectionContext;
  use super::SelectionError;
- use super::VtableClosureData;
- use super::VtableGeneratorData;
- use super::VtableFnPointerData;
- use super::VtableImplData;
+ use super::{VtableImplData, VtableClosureData, VtableGeneratorData, VtableFnPointerData};
  use super::util;
  
  use hir::def_id::DefId;
@@@ -366,7 -363,7 +363,7 @@@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gc
  
          let ty = ty.super_fold_with(self);
          match ty.sty {
 -            ty::Opaque(def_id, substs) if !substs.has_escaping_regions() => { // (*)
 +            ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*)
                  // Only normalize `impl Trait` after type-checking, usually in codegen.
                  match self.param_env.reveal {
                      Reveal::UserFacing => ty,
                  }
              }
  
 -            ty::Projection(ref data) if !data.has_escaping_regions() => { // (*)
 +            ty::Projection(ref data) if !data.has_escaping_bound_vars() => { // (*)
  
                  // (*) This is kind of hacky -- we need to be able to
                  // handle normalization within binders because
@@@ -1073,7 -1070,8 +1070,8 @@@ fn assemble_candidates_from_impls<'cx, 
              super::VtableClosure(_) |
              super::VtableGenerator(_) |
              super::VtableFnPointer(_) |
-             super::VtableObject(_) => {
+             super::VtableObject(_) |
+             super::VtableTraitAlias(_) => {
                  debug!("assemble_candidates_from_impls: vtable={:?}",
                         vtable);
                  true
@@@ -1235,7 -1233,8 +1233,8 @@@ fn confirm_select_candidate<'cx, 'gcx, 
              confirm_object_candidate(selcx, obligation, obligation_trait_ref),
          super::VtableAutoImpl(..) |
          super::VtableParam(..) |
-         super::VtableBuiltin(..) =>
+         super::VtableBuiltin(..) |
+         super::VtableTraitAlias(..) =>
              // we don't create Select candidates with this kind of resolution
              span_bug!(
                  obligation.cause.span,
@@@ -1486,7 -1485,7 +1485,7 @@@ fn confirm_impl_candidate<'cx, 'gcx, 't
      impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>)
      -> Progress<'tcx>
  {
-     let VtableImplData { substs, nested, impl_def_id } = impl_vtable;
+     let VtableImplData { impl_def_id, substs, nested } = impl_vtable;
  
      let tcx = selcx.tcx();
      let param_env = obligation.param_env;
@@@ -1619,7 -1618,7 +1618,7 @@@ impl<'cx, 'gcx, 'tcx> ProjectionCacheKe
          let infcx = selcx.infcx();
          // We don't do cross-snapshot caching of obligations with escaping regions,
          // so there's no cache key to use
 -        predicate.no_late_bound_regions()
 +        predicate.no_bound_vars()
              .map(|predicate| ProjectionCacheKey {
                  // We don't attempt to match up with a specific type-variable state
                  // from a specific call to `opt_normalize_projection_type` - if
index 45dad508af560d9e78c8dafc32604d2031a30309,4b41831afbb3323b667b62655aa796061531f607..312cd66dcc75c229b78b1d9d7a4d2b537b7eb55b
@@@ -30,11 -30,11 +30,11 @@@ use super::{ObligationCause, PredicateO
  use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
  use super::{
      VtableAutoImpl, VtableBuiltin, VtableClosure, VtableFnPointer, VtableGenerator, VtableImpl,
-     VtableObject, VtableParam,
+     VtableObject, VtableParam, VtableTraitAlias,
  };
  use super::{
      VtableAutoImplData, VtableBuiltinData, VtableClosureData, VtableFnPointerData,
-     VtableGeneratorData, VtableImplData, VtableObjectData,
+     VtableGeneratorData, VtableImplData, VtableObjectData, VtableTraitAliasData,
  };
  
  use dep_graph::{DepKind, DepNodeIndex};
@@@ -271,6 -271,8 +271,8 @@@ enum SelectionCandidate<'tcx> 
      /// types generated for a fn pointer type (e.g., `fn(int)->int`)
      FnPointerCandidate,
  
+     TraitAliasCandidate(DefId),
      ObjectCandidate,
  
      BuiltinObjectCandidate,
@@@ -286,12 -288,13 +288,13 @@@ impl<'a, 'tcx> ty::Lift<'tcx> for Selec
              ImplCandidate(def_id) => ImplCandidate(def_id),
              AutoImplCandidate(def_id) => AutoImplCandidate(def_id),
              ProjectionCandidate => ProjectionCandidate,
+             ClosureCandidate => ClosureCandidate,
+             GeneratorCandidate => GeneratorCandidate,
              FnPointerCandidate => FnPointerCandidate,
+             TraitAliasCandidate(def_id) => TraitAliasCandidate(def_id),
              ObjectCandidate => ObjectCandidate,
              BuiltinObjectCandidate => BuiltinObjectCandidate,
              BuiltinUnsizeCandidate => BuiltinUnsizeCandidate,
-             ClosureCandidate => ClosureCandidate,
-             GeneratorCandidate => GeneratorCandidate,
  
              ParamCandidate(ref trait_ref) => {
                  return tcx.lift(trait_ref).map(ParamCandidate);
@@@ -587,7 -590,7 +590,7 @@@ impl<'cx, 'gcx, 'tcx> SelectionContext<
          obligation: &TraitObligation<'tcx>,
      ) -> SelectionResult<'tcx, Selection<'tcx>> {
          debug!("select({:?})", obligation);
 -        debug_assert!(!obligation.predicate.has_escaping_regions());
 +        debug_assert!(!obligation.predicate.has_escaping_bound_vars());
  
          let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
  
  
          match obligation.predicate {
              ty::Predicate::Trait(ref t) => {
 -                debug_assert!(!t.has_escaping_regions());
 +                debug_assert!(!t.has_escaping_bound_vars());
                  let obligation = obligation.with(t.clone());
                  self.evaluate_trait_predicate_recursively(previous_stack, obligation)
              }
              },
  
              ty::Predicate::TypeOutlives(ref binder) => {
 -                assert!(!binder.has_escaping_regions());
 -                // Check if the type has higher-ranked regions.
 -                if binder.skip_binder().0.has_escaping_regions() {
 +                assert!(!binder.has_escaping_bound_vars());
 +                // Check if the type has higher-ranked vars.
 +                if binder.skip_binder().0.has_escaping_bound_vars() {
                      // If so, this obligation is an error (for now). Eventually we should be
                      // able to support additional cases here, like `for<'a> &'a str: 'a`.
  
                          Ok(EvaluatedToErr)
                      }
                  } else {
 -                    // If the type has no late bound regions, then if we assign all
 +                    // If the type has no late bound vars, then if we assign all
                      // the inference variables in it to be 'static, then the type
                      // will be 'static itself.
                      //
              "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
              cache_fresh_trait_pred, stack
          );
 -        debug_assert!(!stack.obligation.predicate.has_escaping_regions());
 +        debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
  
          if let Some(c) =
              self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
          let predicate = self.infcx()
              .resolve_type_vars_if_possible(&obligation.predicate);
  
-         // ok to skip binder because of the nature of the
+         // OK to skip binder because of the nature of the
          // trait-ref-is-knowable check, which does not care about
          // bound regions
          let trait_ref = predicate.skip_binder().trait_ref;
              ambiguous: false,
          };
  
+         self.assemble_candidates_for_trait_alias(obligation, &mut candidates)?;
          // Other bounds. Consider both in-scope bounds from fn decl
          // and applicable impls. There is a certain set of precedence rules here.
          let def_id = obligation.predicate.def_id();
          placeholder_map: &infer::PlaceholderMap<'tcx>,
          snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
      ) -> bool {
 -        debug_assert!(!skol_trait_ref.has_escaping_regions());
 +        debug_assert!(!skol_trait_ref.has_escaping_bound_vars());
          if self.infcx
              .at(&obligation.cause, obligation.param_env)
              .sup(ty::Binder::dummy(skol_trait_ref), trait_bound)
              return Ok(());
          }
  
-         // ok to skip binder because the substs on generator types never
+         // OK to skip binder because the substs on generator types never
          // touch bound regions, they just capture the in-scope
          // type/region parameters
          let self_ty = *obligation.self_ty().skip_binder();
              }
          };
  
-         // ok to skip binder because the substs on closure types never
+         // OK to skip binder because the substs on closure types never
          // touch bound regions, they just capture the in-scope
          // type/region parameters
          match obligation.self_ty().skip_binder().sty {
              return Ok(());
          }
  
-         // ok to skip binder because what we are inspecting doesn't involve bound regions
+         // OK to skip binder because what we are inspecting doesn't involve bound regions
          let self_ty = *obligation.self_ty().skip_binder();
          match self_ty.sty {
              ty::Infer(ty::TyVar(_)) => {
              obligation.self_ty().skip_binder()
          );
  
 -        // Object-safety candidates are only applicable to object-safe
 -        // traits. Including this check is useful because it helps
 -        // inference in cases of traits like `BorrowFrom`, which are
 -        // not object-safe, and which rely on being able to infer the
 -        // self-type from one of the other inputs. Without this check,
 -        // these cases wind up being considered ambiguous due to a
 -        // (spurious) ambiguity introduced here.
 -        let predicate_trait_ref = obligation.predicate.to_poly_trait_ref();
 -        if !self.tcx().is_object_safe(predicate_trait_ref.def_id()) {
 -            return;
 -        }
 -
          self.probe(|this, _snapshot| {
              // the code below doesn't care about regions, and the
              // self-ty here doesn't escape this probe, so just erase
          //     T: Trait
          // so it seems ok if we (conservatively) fail to accept that `Unsize`
          // obligation above. Should be possible to extend this in the future.
 -        let source = match obligation.self_ty().no_late_bound_regions() {
 +        let source = match obligation.self_ty().no_bound_vars() {
              Some(t) => t,
              None => {
                  // Don't add any candidates if there are bound regions.
          }
      }
  
+     fn assemble_candidates_for_trait_alias(
+         &mut self,
+         obligation: &TraitObligation<'tcx>,
+         candidates: &mut SelectionCandidateSet<'tcx>,
+     ) -> Result<(), SelectionError<'tcx>> {
+         // OK to skip binder here because the tests we do below do not involve bound regions
+         let self_ty = *obligation.self_ty().skip_binder();
+         debug!("assemble_candidates_for_trait_alias(self_ty={:?})", self_ty);
+         let def_id = obligation.predicate.def_id();
+         if ty::is_trait_alias(self.tcx(), def_id) {
+             candidates.vec.push(TraitAliasCandidate(def_id.clone()));
+         }
+         Ok(())
+     }
      ///////////////////////////////////////////////////////////////////////////
      // WINNOW
      //
                  | FnPointerCandidate
                  | BuiltinObjectCandidate
                  | BuiltinUnsizeCandidate
-                 | BuiltinCandidate { .. } => {
+                 | BuiltinCandidate { .. }
+                 | TraitAliasCandidate(..) => {
                      // Global bounds from the where clause should be ignored
                      // here (see issue #50825). Otherwise, we have a where
                      // clause so don't go around looking for impls.
                  | FnPointerCandidate
                  | BuiltinObjectCandidate
                  | BuiltinUnsizeCandidate
-                 | BuiltinCandidate { .. } => true,
+                 | BuiltinCandidate { .. }
+                 | TraitAliasCandidate(..) => true,
                  ObjectCandidate | ProjectionCandidate => {
                      // Arbitrarily give param candidates priority
                      // over projection and object candidates.
              ty::Infer(ty::TyVar(_)) => Ambiguous,
  
              ty::UnnormalizedProjection(..)
 -            | ty::Infer(ty::BoundTy(_))
 +            | ty::Bound(_)
              | ty::Infer(ty::FreshTy(_))
              | ty::Infer(ty::FreshIntTy(_))
              | ty::Infer(ty::FreshFloatTy(_)) => {
              }
  
              ty::UnnormalizedProjection(..)
 -            | ty::Infer(ty::BoundTy(_))
 +            | ty::Bound(_)
              | ty::Infer(ty::FreshTy(_))
              | ty::Infer(ty::FreshIntTy(_))
              | ty::Infer(ty::FreshFloatTy(_)) => {
              | ty::Param(..)
              | ty::Foreign(..)
              | ty::Projection(..)
 -            | ty::Infer(ty::BoundTy(_))
 +            | ty::Bound(_)
              | ty::Infer(ty::TyVar(_))
              | ty::Infer(ty::FreshTy(_))
              | ty::Infer(ty::FreshIntTy(_))
                  Ok(VtableParam(obligations))
              }
  
+             ImplCandidate(impl_def_id) => Ok(VtableImpl(self.confirm_impl_candidate(
+                 obligation,
+                 impl_def_id,
+             ))),
              AutoImplCandidate(trait_def_id) => {
                  let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
                  Ok(VtableAutoImpl(data))
              }
  
-             ImplCandidate(impl_def_id) => Ok(VtableImpl(self.confirm_impl_candidate(
-                 obligation,
-                 impl_def_id,
-             ))),
+             ProjectionCandidate => {
+                 self.confirm_projection_candidate(obligation);
+                 Ok(VtableParam(Vec::new()))
+             }
  
              ClosureCandidate => {
                  let vtable_closure = self.confirm_closure_candidate(obligation)?;
                  Ok(VtableGenerator(vtable_generator))
              }
  
-             BuiltinObjectCandidate => {
-                 // This indicates something like `(Trait+Send) :
-                 // Send`. In this case, we know that this holds
-                 // because that's what the object type is telling us,
-                 // and there's really no additional obligations to
-                 // prove and no types in particular to unify etc.
-                 Ok(VtableParam(Vec::new()))
+             FnPointerCandidate => {
+                 let data = self.confirm_fn_pointer_candidate(obligation)?;
+                 Ok(VtableFnPointer(data))
+             }
+             TraitAliasCandidate(alias_def_id) => {
+                 let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
+                 Ok(VtableTraitAlias(data))
              }
  
              ObjectCandidate => {
                  Ok(VtableObject(data))
              }
  
-             FnPointerCandidate => {
-                 let data = self.confirm_fn_pointer_candidate(obligation)?;
-                 Ok(VtableFnPointer(data))
-             }
-             ProjectionCandidate => {
-                 self.confirm_projection_candidate(obligation);
+             BuiltinObjectCandidate => {
+                 // This indicates something like `(Trait+Send) :
+                 // Send`. In this case, we know that this holds
+                 // because that's what the object type is telling us,
+                 // and there's really no additional obligations to
+                 // prove and no types in particular to unify etc.
                  Ok(VtableParam(Vec::new()))
              }
  
          self.vtable_auto_impl(obligation, trait_def_id, types)
      }
  
-     /// See `confirm_auto_impl_candidate`
+     /// See `confirm_auto_impl_candidate`.
      fn vtable_auto_impl(
          &mut self,
          obligation: &TraitObligation<'tcx>,
          // this time not in a probe.
          self.in_snapshot(|this, snapshot| {
              let (substs, placeholder_map) = this.rematch_impl(impl_def_id, obligation, snapshot);
-             debug!("confirm_impl_candidate substs={:?}", substs);
+             debug!("confirm_impl_candidate: substs={:?}", substs);
              let cause = obligation.derived_cause(ImplDerivedObligation);
              this.vtable_impl(
                  impl_def_id,
      ) -> VtableObjectData<'tcx, PredicateObligation<'tcx>> {
          debug!("confirm_object_candidate({:?})", obligation);
  
-         // FIXME skipping binder here seems wrong -- we should
-         // probably flatten the binder from the obligation and the
-         // binder from the object. Have to try to make a broken test
-         // case that results. -nmatsakis
+         // FIXME(nmatsakis) skipping binder here seems wrong -- we should
+         // probably flatten the binder from the obligation and the binder
+         // from the object. Have to try to make a broken test case that
+         // results.
          let self_ty = self.infcx
              .shallow_resolve(*obligation.self_ty().skip_binder());
          let poly_trait_ref = match self_ty.sty {
      ) -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
          debug!("confirm_fn_pointer_candidate({:?})", obligation);
  
-         // ok to skip binder; it is reintroduced below
+         // OK to skip binder; it is reintroduced below
          let self_ty = self.infcx
              .shallow_resolve(*obligation.self_ty().skip_binder());
          let sig = self_ty.fn_sig(self.tcx());
          })
      }
  
+     fn confirm_trait_alias_candidate(
+         &mut self,
+         obligation: &TraitObligation<'tcx>,
+         alias_def_id: DefId,
+     ) -> VtableTraitAliasData<'tcx, PredicateObligation<'tcx>> {
+         debug!(
+             "confirm_trait_alias_candidate({:?}, {:?})",
+             obligation, alias_def_id
+         );
+         self.in_snapshot(|this, snapshot| {
+             let (predicate, placeholder_map) = this.infcx()
+                 .replace_late_bound_regions_with_placeholders(&obligation.predicate);
+             let trait_ref = predicate.trait_ref;
+             let trait_def_id = trait_ref.def_id;
+             let substs = trait_ref.substs;
+             let trait_obligations = this.impl_or_trait_obligations(
+                 obligation.cause.clone(),
+                 obligation.recursion_depth,
+                 obligation.param_env,
+                 trait_def_id,
+                 &substs,
+                 placeholder_map,
+                 snapshot,
+             );
+             debug!(
+                 "confirm_trait_alias_candidate: trait_def_id={:?} trait_obligations={:?}",
+                 trait_def_id, trait_obligations
+             );
+             VtableTraitAliasData {
+                 alias_def_id,
+                 substs: substs,
+                 nested: trait_obligations,
+             }
+         })
+     }
      fn confirm_generator_candidate(
          &mut self,
          obligation: &TraitObligation<'tcx>,
      ) -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
-         // ok to skip binder because the substs on generator types never
+         // OK to skip binder because the substs on generator types never
          // touch bound regions, they just capture the in-scope
          // type/region parameters
          let self_ty = self.infcx
              .fn_trait_kind(obligation.predicate.def_id())
              .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
  
-         // ok to skip binder because the substs on closure types never
+         // OK to skip binder because the substs on closure types never
          // touch bound regions, they just capture the in-scope
          // type/region parameters
          let self_ty = self.infcx
          // assemble_candidates_for_unsizing should ensure there are no late bound
          // regions here. See the comment there for more details.
          let source = self.infcx
 -            .shallow_resolve(obligation.self_ty().no_late_bound_regions().unwrap());
 +            .shallow_resolve(obligation.self_ty().no_bound_vars().unwrap());
          let target = obligation
              .predicate
              .skip_binder()
index 2fc8ef548fa0447fa6b1c5f8e61509bf1fa845e1,1627f9a766c4e02c52c41fbd91e8321cd503a399..b6691df39c120ccebeee7eef6692e609802447ab
@@@ -213,7 -213,7 +213,7 @@@ impl<'tcx> fmt::Display for Instance<'t
  impl<'a, 'b, 'tcx> Instance<'tcx> {
      pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
                 -> Instance<'tcx> {
 -        assert!(!substs.has_escaping_regions(),
 +        assert!(!substs.has_escaping_bound_vars(),
                  "substs of instance {:?} not normalized for codegen: {:?}",
                  def_id, substs);
          Instance { def: InstanceDef::Item(def_id), substs: substs }
@@@ -400,7 -400,9 +400,9 @@@ fn resolve_associated_item<'a, 'tcx>
                  None
              }
          }
-         traits::VtableAutoImpl(..) | traits::VtableParam(..) => None
+         traits::VtableAutoImpl(..) |
+         traits::VtableParam(..) |
+         traits::VtableTraitAlias(..) => None
      }
  }
  
diff --combined src/librustc/ty/mod.rs
index 7d693cd5523df22e2f52e7c894ae1f3d7538167f,3d9ec7245f9d6382badb60bd61dac16ff3e29e24..c7c197d11c03beb112b95d85933d45b9d6acc1ef
@@@ -63,7 -63,7 +63,7 @@@ use rustc_data_structures::stable_hashe
  
  use hir;
  
 -pub use self::sty::{Binder, BoundTy, BoundTyIndex, DebruijnIndex, INNERMOST};
 +pub use self::sty::{Binder, BoundTy, BoundTyKind, BoundVar, DebruijnIndex, INNERMOST};
  pub use self::sty::{FnSig, GenSig, CanonicalPolyFnSig, PolyFnSig, PolyGenSig};
  pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
  pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
@@@ -463,9 -463,13 +463,9 @@@ bitflags! 
          // Currently we can't normalize projections w/ bound regions.
          const HAS_NORMALIZABLE_PROJECTION = 1 << 12;
  
 -        // Set if this includes a "canonical" type or region var --
 -        // ought to be true only for the results of canonicalization.
 -        const HAS_CANONICAL_VARS = 1 << 13;
 -
          /// Does this have any `ReLateBound` regions? Used to check
          /// if a global bound is safe to evaluate.
 -        const HAS_RE_LATE_BOUND = 1 << 14;
 +        const HAS_RE_LATE_BOUND = 1 << 13;
  
          const NEEDS_SUBST        = TypeFlags::HAS_PARAMS.bits |
                                     TypeFlags::HAS_SELF.bits |
                                    TypeFlags::HAS_TY_CLOSURE.bits |
                                    TypeFlags::HAS_FREE_LOCAL_NAMES.bits |
                                    TypeFlags::KEEP_IN_LOCAL_TCX.bits |
 -                                  TypeFlags::HAS_CANONICAL_VARS.bits |
                                    TypeFlags::HAS_RE_LATE_BOUND.bits;
      }
  }
@@@ -1046,24 -1051,24 +1046,24 @@@ pub enum Predicate<'tcx> 
      /// would be the type parameters.
      Trait(PolyTraitPredicate<'tcx>),
  
-     /// where 'a : 'b
+     /// where `'a : 'b`
      RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
  
-     /// where T : 'a
+     /// where `T : 'a`
      TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
  
-     /// where <T as TraitRef>::Name == X, approximately.
-     /// See `ProjectionPredicate` struct for details.
+     /// where `<T as TraitRef>::Name == X`, approximately.
+     /// See the `ProjectionPredicate` struct for details.
      Projection(PolyProjectionPredicate<'tcx>),
  
-     /// no syntax: T WF
+     /// no syntax: `T` well-formed
      WellFormed(Ty<'tcx>),
  
      /// trait must be object-safe
      ObjectSafe(DefId),
  
      /// No direct syntax. May be thought of as `where T : FnFoo<...>`
-     /// for some substitutions `...` and T being a closure type.
+     /// for some substitutions `...` and `T` being a closure type.
      /// Satisfied (or refuted) once we know the closure's kind.
      ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind),
  
@@@ -2373,7 -2378,6 +2373,7 @@@ impl<'a, 'gcx, 'tcx> AdtDef 
                  }
              }
  
 +            Bound(..) |
              Infer(..) => {
                  bug!("unexpected type `{:?}` in sized_constraint_for_ty",
                       ty)
@@@ -2797,7 -2801,7 +2797,7 @@@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '
          }
      }
  
-     /// Determine whether an item is annotated with an attribute
+     /// Determine whether an item is annotated with an attribute.
      pub fn has_attr(self, did: DefId, attr: &str) -> bool {
          attr::contains_name(&self.get_attrs(did), attr)
      }
          self.optimized_mir(def_id).generator_layout.as_ref().unwrap()
      }
  
-     /// Given the def_id of an impl, return the def_id of the trait it implements.
+     /// Given the def-id of an impl, return the def_id of the trait it implements.
      /// If it implements no trait, return `None`.
      pub fn trait_id_of_impl(self, def_id: DefId) -> Option<DefId> {
          self.impl_trait_ref(def_id).map(|tr| tr.def_id)
      }
  
-     /// If the given def ID describes a method belonging to an impl, return the
-     /// ID of the impl that the method belongs to. Otherwise, return `None`.
+     /// If the given defid describes a method belonging to an impl, return the
+     /// def-id of the impl that the method belongs to. Otherwise, return `None`.
      pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
          let item = if def_id.krate != LOCAL_CRATE {
              if let Some(Def::Method(_)) = self.describe_def(def_id) {
@@@ -2983,7 -2987,7 +2983,7 @@@ fn trait_of_item<'a, 'tcx>(tcx: TyCtxt<
          })
  }
  
- /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition
+ /// Yields the parent function's `DefId` if `def_id` is an `impl Trait` definition.
  pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefId> {
      if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
          if let Node::Item(item) = tcx.hir.get(node_id) {
      None
  }
  
- /// See `ParamEnv` struct def'n for details.
+ /// Returns `true` if `def_id` is a trait alias.
+ pub fn is_trait_alias(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
+     if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
+         if let Node::Item(item) = tcx.hir.get(node_id) {
+             if let hir::ItemKind::TraitAlias(..) = item.node {
+                 return true;
+             }
+         }
+     }
+     false
+ }
+ /// See `ParamEnv` struct definition for details.
  fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         def_id: DefId)
                         -> ParamEnv<'tcx>
diff --combined src/librustc/ty/sty.rs
index 6929cb988d0519458cbd50f02d78dada048a82f2,49cd87e2dc54ecc665f64863bc8c55e3ba4f88e2..28b58d62175bc21f270ef57a38d478c2df832c54
@@@ -77,17 -77,6 +77,17 @@@ impl BoundRegion 
              _ => false,
          }
      }
 +
 +    /// When canonicalizing, we replace unbound inference variables and free
 +    /// regions with anonymous late bound regions. This method asserts that
 +    /// we have an anonymous late bound region, which hence may refer to
 +    /// a canonical variable.
 +    pub fn assert_bound_var(&self) -> BoundVar {
 +        match *self {
 +            BoundRegion::BrAnon(var) => BoundVar::from_u32(var),
 +            _ => bug!("bound region is not anonymous"),
 +        }
 +    }
  }
  
  /// N.B., If you change this, you'll probably want to change the corresponding
@@@ -199,9 -188,6 +199,9 @@@ pub enum TyKind<'tcx> 
      /// A type parameter; for example, `T` in `fn f<T>(x: T) {}
      Param(ParamTy),
  
 +    /// Bound type variable, used only when preparing a trait query.
 +    Bound(BoundTy),
 +
      /// A type variable used during type checking.
      Infer(InferTy),
  
@@@ -650,7 -636,7 +650,7 @@@ impl<'tcx> TraitRef<'tcx> 
          TraitRef { def_id: def_id, substs: substs }
      }
  
-     /// Returns a TraitRef of the form `P0: Foo<P1..Pn>` where `Pi`
+     /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
      /// are the parameters defined on trait.
      pub fn identity<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> TraitRef<'tcx> {
          TraitRef {
@@@ -741,8 -727,8 +741,8 @@@ impl<'a, 'gcx, 'tcx> ExistentialTraitRe
      /// or some placeholder type.
      pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
          -> ty::TraitRef<'tcx>  {
 -        // otherwise the escaping regions would be captured by the binder
 -        // debug_assert!(!self_ty.has_escaping_regions());
 +        // otherwise the escaping vars would be captured by the binder
 +        // debug_assert!(!self_ty.has_escaping_bound_vars());
  
          ty::TraitRef {
              def_id: self.def_id,
@@@ -769,11 -755,11 +769,11 @@@ impl<'tcx> PolyExistentialTraitRef<'tcx
      }
  }
  
 -/// Binder is a binder for higher-ranked lifetimes. It is part of the
 +/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
  /// compiler's representation for things like `for<'a> Fn(&'a isize)`
  /// (which would be represented by the type `PolyTraitRef ==
  /// Binder<TraitRef>`). Note that when we instantiate,
 -/// erase, or otherwise "discharge" these bound regions, we change the
 +/// erase, or otherwise "discharge" these bound vars, we change the
  /// type from `Binder<T>` to just `T` (see
  /// e.g. `liberate_late_bound_regions`).
  #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
@@@ -781,28 -767,29 +781,28 @@@ pub struct Binder<T>(T)
  
  impl<T> Binder<T> {
      /// Wraps `value` in a binder, asserting that `value` does not
 -    /// contain any bound regions that would be bound by the
 +    /// contain any bound vars that would be bound by the
      /// binder. This is commonly used to 'inject' a value T into a
      /// different binding level.
      pub fn dummy<'tcx>(value: T) -> Binder<T>
          where T: TypeFoldable<'tcx>
      {
 -        debug_assert!(!value.has_escaping_regions());
 +        debug_assert!(!value.has_escaping_bound_vars());
          Binder(value)
      }
  
 -    /// Wraps `value` in a binder, binding late-bound regions (if any).
 -    pub fn bind<'tcx>(value: T) -> Binder<T>
 -    {
 +    /// Wraps `value` in a binder, binding higher-ranked vars (if any).
 +    pub fn bind<'tcx>(value: T) -> Binder<T> {
          Binder(value)
      }
  
      /// Skips the binder and returns the "bound" value. This is a
      /// risky thing to do because it's easy to get confused about
      /// debruijn indices and the like. It is usually better to
 -    /// discharge the binder using `no_late_bound_regions` or
 +    /// discharge the binder using `no_bound_vars` or
      /// `replace_late_bound_regions` or something like
      /// that. `skip_binder` is only valid when you are either
 -    /// extracting data that has nothing to do with bound regions, you
 +    /// extracting data that has nothing to do with bound vars, you
      /// are doing some sort of test that does not involve bound
      /// regions, or you are being very careful about your depth
      /// accounting.
      ///
      /// - extracting the def-id from a PolyTraitRef;
      /// - comparing the self type of a PolyTraitRef to see if it is equal to
 -    ///   a type parameter `X`, since the type `X`  does not reference any regions
 +    ///   a type parameter `X`, since the type `X` does not reference any regions
      pub fn skip_binder(&self) -> &T {
          &self.0
      }
      }
  
      /// Unwraps and returns the value within, but only if it contains
 -    /// no bound regions at all. (In other words, if this binder --
 +    /// no bound vars at all. (In other words, if this binder --
      /// and indeed any enclosing binder -- doesn't bind anything at
      /// all.) Otherwise, returns `None`.
      ///
      /// (One could imagine having a method that just unwraps a single
 -    /// binder, but permits late-bound regions bound by enclosing
 +    /// binder, but permits late-bound vars bound by enclosing
      /// binders, but that would require adjusting the debruijn
      /// indices, and given the shallow binding structure we often use,
      /// would not be that useful.)
 -    pub fn no_late_bound_regions<'tcx>(self) -> Option<T>
 -        where T : TypeFoldable<'tcx>
 +    pub fn no_bound_vars<'tcx>(self) -> Option<T>
 +        where T: TypeFoldable<'tcx>
      {
 -        if self.skip_binder().has_escaping_regions() {
 +        if self.skip_binder().has_escaping_bound_vars() {
              None
          } else {
              Some(self.skip_binder().clone())
@@@ -1179,6 -1166,9 +1179,6 @@@ pub enum RegionKind 
      /// `ClosureRegionRequirements` that are produced by MIR borrowck.
      /// See `ClosureRegionRequirements` for more details.
      ReClosureBound(RegionVid),
 -
 -    /// Canonicalized region, used only when preparing a trait query.
 -    ReCanonical(BoundTyIndex),
  }
  
  impl<'tcx> serialize::UseSpecializedDecodable for Region<'tcx> {}
@@@ -1229,37 -1219,22 +1229,37 @@@ pub enum InferTy 
      FreshTy(u32),
      FreshIntTy(u32),
      FreshFloatTy(u32),
 -
 -    /// Bound type variable, used only when preparing a trait query.
 -    BoundTy(BoundTy),
  }
  
  newtype_index! {
 -    pub struct BoundTyIndex { .. }
 +    pub struct BoundVar { .. }
  }
  
  #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
  pub struct BoundTy {
 -    pub level: DebruijnIndex,
 -    pub var: BoundTyIndex,
 +    pub index: DebruijnIndex,
 +    pub var: BoundVar,
 +    pub kind: BoundTyKind,
  }
  
 -impl_stable_hash_for!(struct BoundTy { level, var });
 +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
 +pub enum BoundTyKind {
 +    Anon,
 +    Param(InternedString),
 +}
 +
 +impl_stable_hash_for!(struct BoundTy { index, var, kind });
 +impl_stable_hash_for!(enum self::BoundTyKind { Anon, Param(a) });
 +
 +impl BoundTy {
 +    pub fn new(index: DebruijnIndex, var: BoundVar) -> Self {
 +        BoundTy {
 +            index,
 +            var,
 +            kind: BoundTyKind::Anon,
 +        }
 +    }
 +}
  
  /// A `ProjectionPredicate` for an `ExistentialTraitRef`.
  #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
@@@ -1289,7 -1264,7 +1289,7 @@@ impl<'a, 'tcx, 'gcx> ExistentialProject
                          -> ty::ProjectionPredicate<'tcx>
      {
          // otherwise the escaping regions would be captured by the binders
 -        debug_assert!(!self_ty.has_escaping_regions());
 +        debug_assert!(!self_ty.has_escaping_bound_vars());
  
          ty::ProjectionPredicate {
              projection_ty: ty::ProjectionTy {
@@@ -1388,6 -1363,7 +1388,6 @@@ impl RegionKind 
              RegionKind::ReEmpty => false,
              RegionKind::ReErased => false,
              RegionKind::ReClosureBound(..) => false,
 -            RegionKind::ReCanonical(..) => false,
          }
      }
  
              }
              ty::ReErased => {
              }
 -            ty::ReCanonical(..) => {
 -                flags = flags | TypeFlags::HAS_FREE_REGIONS;
 -                flags = flags | TypeFlags::HAS_CANONICAL_VARS;
 -            }
              ty::ReClosureBound(..) => {
                  flags = flags | TypeFlags::HAS_FREE_REGIONS;
              }
@@@ -1885,7 -1865,6 +1885,7 @@@ impl<'a, 'gcx, 'tcx> TyS<'tcx> 
              Tuple(..) |
              Foreign(..) |
              Param(_) |
 +            Bound(..) |
              Infer(_) |
              Error => {
                  vec![]
  
              ty::Infer(ty::TyVar(_)) => false,
  
 -            ty::Infer(ty::BoundTy(_)) |
 +            ty::Bound(_) |
              ty::Infer(ty::FreshTy(_)) |
              ty::Infer(ty::FreshIntTy(_)) |
              ty::Infer(ty::FreshFloatTy(_)) =>
diff --combined src/librustc/ty/util.rs
index 1b1bbfd4deb8b53ea1780846c863fbf2a4f433ca,a6997260784d38e0083b6cf5ce81af24e0167729..9ba5bf9add110292760dd536f0b43b1157632aa5
@@@ -363,7 -363,7 +363,7 @@@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '
                 erased_self_ty,
                 predicates);
  
 -        assert!(!erased_self_ty.has_escaping_regions());
 +        assert!(!erased_self_ty.has_escaping_bound_vars());
  
          traits::elaborate_predicates(self, predicates)
              .filter_map(|predicate| {
                          // construct such an object, but this seems
                          // correct even if that code changes).
                          let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
 -                        if t == &erased_self_ty && !r.has_escaping_regions() {
 +                        if t == &erased_self_ty && !r.has_escaping_bound_vars() {
                              Some(*r)
                          } else {
                              None
          self.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
      }
  
-     /// True if `def_id` refers to a trait (e.g., `trait Foo { ... }`).
+     /// True if `def_id` refers to a trait (i.e., `trait Foo { ... }`).
      pub fn is_trait(self, def_id: DefId) -> bool {
          if let DefPathData::Trait(_) = self.def_key(def_id).disambiguated_data.data {
              true
@@@ -951,7 -951,7 +951,7 @@@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt
  
          // Can refer to a type which may drop.
          // FIXME(eddyb) check this against a ParamEnv.
 -        ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) |
 +        ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) | ty::Bound(..) |
          ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
  
          ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
index 46f2c0c76a0c7b457cb19b140428ed69b92b1cb1,e44cfec82ad642f624d224b6e7920c3f372b0977..18f8473b5b56d7d88fb600878aaa16ff8fbbe0b3
@@@ -8,7 -8,7 +8,7 @@@
  // option. This file may not be copied, modified, or distributed
  // except according to those terms.
  
- //! Conversion from AST representation of types to the ty.rs
+ //! Conversion from AST representation of types to the `ty.rs`
  //! representation.  The main routine here is `ast_ty_to_ty()`: each use
  //! is parameterized by an instance of `AstConv`.
  
@@@ -181,7 -181,6 +181,6 @@@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<
          item_segment: &hir::PathSegment)
          -> &'tcx Substs<'tcx>
      {
          let (substs, assoc_bindings) = item_segment.with_generic_args(|generic_args| {
              self.create_substs_for_ast_path(
                  span,
      }
  
      /// Given the type/region arguments provided to some path (along with
-     /// an implicit Self, if this is a trait reference) returns the complete
+     /// an implicit `Self`, if this is a trait reference) returns the complete
      /// set of substitutions. This may involve applying defaulted type parameters.
      ///
      /// Note that the type listing given here is *exactly* what the user provided.
      {
          let trait_def_id = self.trait_def_id(trait_ref);
  
-         debug!("ast_path_to_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
+         debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
  
          self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
  
              let predicate: Result<_, ErrorReported> =
                  self.ast_type_binding_to_poly_projection_predicate(
                      trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
-             // ok to ignore Err() because ErrorReported (see above)
+             // ok to ignore Err because ErrorReported (see above)
              Some((predicate.ok()?, binding.span))
          }));
  
-         debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}",
+         debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}",
                 trait_ref, poly_projections, poly_trait_ref);
          poly_trait_ref
      }
          )
      }
  
-     /// Transform a PolyTraitRef into a PolyExistentialTraitRef by
-     /// removing the dummy Self type (TRAIT_OBJECT_DUMMY_SELF).
+     /// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
+     /// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
      fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
                                  -> ty::ExistentialTraitRef<'tcx> {
          assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF);
          let principal = self.instantiate_poly_trait_ref(&trait_bounds[0],
                                                          dummy_self,
                                                          &mut projection_bounds);
+         debug!("principal: {:?}", principal);
  
          for trait_bound in trait_bounds[1..].iter() {
-             // Sanity check for non-principal trait bounds
+             // sanity check for non-principal trait bounds
              self.instantiate_poly_trait_ref(trait_bound,
                                              dummy_self,
                                              &mut vec![]);
              })
          });
  
-         // check that there are no gross object safety violations,
+         // Check that there are no gross object safety violations;
          // most importantly, that the supertraits don't contain Self,
-         // to avoid ICE-s.
+         // to avoid ICEs.
          let object_safety_violations =
 -            tcx.astconv_object_safety_violations(principal.def_id());
 +            tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
          if !object_safety_violations.is_empty() {
              tcx.report_object_safety_error(
                  span, principal.def_id(), object_safety_violations)
              return tcx.types.err;
          }
  
-         // use a btreeset to keep output in a more consistent order
+         // Use a BTreeSet to keep output in a more consistent order.
          let mut associated_types = BTreeSet::default();
  
          for tr in traits::supertraits(tcx, principal) {
          v.sort_by(|a, b| a.stable_cmp(tcx, b));
          let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
  
-         // Explicitly specified region bound. Use that.
+         // Use explicitly-specified region bound.
          let region_bound = if !lifetime.is_elided() {
              self.ast_region_to_region(lifetime, None)
          } else {
          err.span_label(span, "associated type not allowed here").emit();
      }
  
-     // Check a type Path and convert it to a Ty.
+     // Check a type `Path` and convert it to a `Ty`.
      pub fn def_to_ty(&self,
                       opt_self_ty: Option<Ty<'tcx>>,
                       path: &hir::Path,
      /// Parses the programmer's textual representation of a type into our
      /// internal notion of a type.
      pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
-         debug!("ast_ty_to_ty(id={:?}, ast_ty={:?})",
-                ast_ty.id, ast_ty);
+         debug!("ast_ty_to_ty(id={:?}, ast_ty={:?} ty_ty={:?})",
+                ast_ty.id, ast_ty, ast_ty.node);
  
          let tcx = self.tcx();
  
@@@ -1748,7 -1748,7 +1748,7 @@@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> 
              self.region_bounds.iter().map(|&(region_bound, span)| {
                  // account for the binder being introduced below; no need to shift `param_ty`
                  // because, at present at least, it can only refer to early-bound regions
 -                let region_bound = tcx.mk_region(ty::fold::shift_region(*region_bound, 1));
 +                let region_bound = ty::fold::shift_region(tcx, region_bound, 1);
                  let outlives = ty::OutlivesPredicate(param_ty, region_bound);
                  (ty::Binder::dummy(outlives).to_predicate(), span)
              }).chain(
index bf3887ee8fcdd398532dfb6e269369747fd25afb,c136d76e358d38b54309450a41c5b8d0597ca20d..74dea7fe411ad0e710a016afd5fabc6bb39089e3
@@@ -58,6 -58,8 +58,8 @@@ use rustc::hir::{self, CodegenFnAttrFla
  
  use std::iter;
  
+ struct OnlySelfBounds(bool);
  ///////////////////////////////////////////////////////////////////////////
  // Main entry point
  
@@@ -208,7 -210,7 +210,7 @@@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for 
          item_def_id: DefId,
          poly_trait_ref: ty::PolyTraitRef<'tcx>,
      ) -> Ty<'tcx> {
 -        if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() {
 +        if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
              self.tcx().mk_projection(item_def_id, trait_ref.substs)
          } else {
              // no late-bound regions, we can just ignore the binder
@@@ -245,8 -247,8 +247,8 @@@ fn type_param_predicates<'a, 'tcx>
      use rustc::hir::*;
  
      // In the AST, bounds can derive from two places. Either
-     // written inline like `<T:Foo>` or in a where clause like
-     // `where T:Foo`.
+     // written inline like `<T : Foo>` or in a where clause like
+     // `where T : Foo`.
  
      let param_id = tcx.hir.as_local_node_id(def_id).unwrap();
      let param_owner = tcx.hir.ty_param_owner(param_id);
      let icx = ItemCtxt::new(tcx, item_def_id);
      result
          .predicates
-         .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty));
+         .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty,
+             OnlySelfBounds(true)));
      result
  }
  
  impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
-     /// Find bounds from hir::Generics. This requires scanning through the
+     /// Find bounds from `hir::Generics`. This requires scanning through the
      /// AST. We do this to avoid having to convert *all* the bounds, which
      /// would create artificial cycles. Instead we can only convert the
      /// bounds for a type parameter `X` if `X::Foo` is used.
          ast_generics: &hir::Generics,
          param_id: ast::NodeId,
          ty: Ty<'tcx>,
+         only_self_bounds: OnlySelfBounds,
      ) -> Vec<(ty::Predicate<'tcx>, Span)> {
          let from_ty_params = ast_generics
              .params
                  hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
                  _ => None,
              })
-             .filter(|bp| is_param(self.tcx, &bp.bounded_ty, param_id))
-             .flat_map(|bp| bp.bounds.iter())
-             .flat_map(|b| predicates_from_bound(self, ty, b));
+             .flat_map(|bp| {
+                 let bt = if is_param(self.tcx, &bp.bounded_ty, param_id) {
+                     Some(ty)
+                 } else if !only_self_bounds.0 {
+                     Some(self.to_ty(&bp.bounded_ty))
+                 } else {
+                     None
+                 };
+                 bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b)))
+             })
+             .flat_map(|(bt, b)| predicates_from_bound(self, bt, b));
  
          from_ty_params.chain(from_where_clauses).collect()
      }
@@@ -419,12 -431,9 +431,9 @@@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'
              tcx.predicates_of(def_id);
          }
          hir::ItemKind::TraitAlias(..) => {
-             span_err!(
-                 tcx.sess,
-                 it.span,
-                 E0645,
-                 "trait aliases are not yet implemented (see issue #41517)"
-             );
+             tcx.generics_of(def_id);
+             tcx.at(it.span).super_predicates_of(def_id);
+             tcx.predicates_of(def_id);
          }
          hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
              tcx.generics_of(def_id);
@@@ -693,15 -702,20 +702,20 @@@ fn super_predicates_of<'a, 'tcx>
  
      let icx = ItemCtxt::new(tcx, trait_def_id);
  
-     // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
+     // Convert the bounds that follow the colon, e.g. `Bar + Zed` in `trait Foo : Bar + Zed`.
      let self_param_ty = tcx.mk_self_type();
      let superbounds1 = compute_bounds(&icx, self_param_ty, bounds, SizedByDefault::No, item.span);
  
      let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
  
      // Convert any explicit superbounds in the where clause,
-     // e.g. `trait Foo where Self : Bar`:
-     let superbounds2 = icx.type_parameter_bounds_in_generics(generics, item.id, self_param_ty);
+     // e.g. `trait Foo where Self : Bar`.
+     // In the case of trait aliases, however, we include all bounds in the where clause,
+     // so e.g. `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
+     // as one of its "superpredicates".
+     let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id);
+     let superbounds2 = icx.type_parameter_bounds_in_generics(
+         generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));
  
      // Combine the two lists to form the complete set of superbounds:
      let superbounds: Vec<_> = superbounds1.into_iter().chain(superbounds2).collect();
      // Now require that immediate supertraits are converted,
      // which will, in turn, reach indirect supertraits.
      for &(pred, span) in &superbounds {
+         debug!("superbound: {:?}", pred);
          if let ty::Predicate::Trait(bound) = pred {
              tcx.at(span).super_predicates_of(bound.def_id());
          }
@@@ -1678,6 -1693,7 +1693,7 @@@ fn explicit_predicates_of<'a, 'tcx>
  
      let icx = ItemCtxt::new(tcx, def_id);
      let no_generics = hir::Generics::empty();
+     let empty_trait_items = HirVec::new();
  
      let mut predicates = UniquePredicates::new();
  
                      is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
                      generics
                  }
+                 ItemKind::TraitAlias(ref generics, _) => {
+                     is_trait = Some((ty::TraitRef::identity(tcx, def_id), &empty_trait_items));
+                     generics
+                 }
                  ItemKind::Existential(ExistTy {
                      ref bounds,
                      impl_trait_fn,
@@@ -2010,10 -2030,10 +2030,10 @@@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>
      }
  }
  
- /// Converts a specific GenericBound from the AST into a set of
+ /// Converts a specific `GenericBound` from the AST into a set of
  /// predicates that apply to the self-type. A vector is returned
- /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
- /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
+ /// because this can be anywhere from zero predicates (`T : ?Sized` adds no
+ /// predicates) to one (`T : Foo`) to many (`T : Bar<X=i32>` adds `T : Bar`
  /// and `<T as Bar>::X == i32`).
  fn predicates_from_bound<'tcx>(
      astconv: &dyn AstConv<'tcx, 'tcx>,