diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index bc0a64ae7c5d8..c9b4b2bb99717 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -120,10 +120,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
         let def_data = match i.node {
             ItemKind::Impl(..) => DefPathData::Impl,
             ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()),
+            ItemKind::TraitAlias(..) => DefPathData::TraitAlias(i.ident.as_interned_str()),
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
-            ItemKind::TraitAlias(..) | ItemKind::Existential(..) |
-            ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
-                DefPathData::TypeNs(i.ident.as_interned_str()),
+            ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
+            ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
                 return visit::walk_item(self, i);
             }
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 6b707dd2dcc80..1b7445199475c 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -373,7 +373,9 @@ pub enum DefPathData {
     /// GlobalMetaData identifies a piece of crate metadata that is global to
     /// a whole crate (as opposed to just one item). GlobalMetaData components
     /// are only supposed to show up right below the crate root.
-    GlobalMetaData(InternedString)
+    GlobalMetaData(InternedString),
+    /// A trait alias.
+    TraitAlias(InternedString),
 }
 
 #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
@@ -615,6 +617,7 @@ impl DefPathData {
         match *self {
             TypeNs(name) |
             Trait(name) |
+            TraitAlias(name) |
             AssocTypeInTrait(name) |
             AssocTypeInImpl(name) |
             AssocExistentialInImpl(name) |
@@ -642,6 +645,7 @@ impl DefPathData {
         let s = match *self {
             TypeNs(name) |
             Trait(name) |
+            TraitAlias(name) |
             AssocTypeInTrait(name) |
             AssocTypeInImpl(name) |
             AssocExistentialInImpl(name) |
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index aaef1c722be96..4fc50bce272fa 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -10,6 +10,7 @@ pub use self::PrimTy::*;
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
 
+use errors::FatalError;
 use hir::def::Def;
 use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
 use util::nodemap::{NodeMap, FxHashSet};
@@ -2055,6 +2056,20 @@ pub struct TraitRef {
     pub hir_ref_id: HirId,
 }
 
+impl TraitRef {
+    /// Get the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias.
+    pub fn trait_def_id(&self) -> DefId {
+        match self.path.def {
+            Def::Trait(did) => did,
+            Def::TraitAlias(did) => did,
+            Def::Err => {
+                FatalError.raise();
+            }
+            _ => unreachable!(),
+        }
+    }
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct PolyTraitRef {
     /// The `'a` in `<'a> Foo<&'a T>`
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 70ec72d73bc6c..de567183a3c05 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -258,7 +258,7 @@ for tokenstream::TokenTree {
             tokenstream::TokenTree::Delimited(span, delim, ref tts) => {
                 span.hash_stable(hcx, hasher);
                 std_hash::Hash::hash(&delim, hasher);
-                for sub_tt in tts.stream().trees() {
+                for sub_tt in tts.trees() {
                     sub_tt.hash_stable(hcx, hasher);
                 }
             }
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index 39ce8cc621b49..545192a1f2113 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -186,34 +186,39 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
     }
 
     fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
-        self.iterate_until_fixed_point("Expansion", |constraint, origin| {
-            debug!("expansion: constraint={:?} origin={:?}", constraint, origin);
-            match *constraint {
+        self.iterate_until_fixed_point("Expansion", |constraint| {
+            debug!("expansion: constraint={:?}", constraint);
+            let (a_region, b_vid, b_data, retain) = match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
                     let b_data = var_values.value_mut(b_vid);
-                    (self.expand_node(a_region, b_vid, b_data), false)
+                    (a_region, b_vid, b_data, false)
                 }
                 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
-                    VarValue::ErrorValue => (false, false),
+                    VarValue::ErrorValue => return (false, false),
                     VarValue::Value(a_region) => {
-                        let b_node = var_values.value_mut(b_vid);
-                        let changed = self.expand_node(a_region, b_vid, b_node);
-                        let retain = match *b_node {
+                        let b_data = var_values.value_mut(b_vid);
+                        let retain = match *b_data {
                             VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
                             _ => true
                         };
-                        (changed, retain)
+                        (a_region, b_vid, b_data, retain)
                     }
                 },
                 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
                     // These constraints are checked after expansion
                     // is done, in `collect_errors`.
-                    (false, false)
+                    return (false, false)
                 }
-            }
+            };
+
+            let changed = self.expand_node(a_region, b_vid, b_data);
+            (changed, retain)
         })
     }
 
+    // This function is very hot in some workloads. There's a single callsite
+    // so always inlining is ok even though it's large.
+    #[inline(always)]
     fn expand_node(
         &self,
         a_region: Region<'tcx>,
@@ -722,18 +727,17 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> {
     }
 
     fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
-    where
-        F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> (bool, bool),
+        where F: FnMut(&Constraint<'tcx>) -> (bool, bool),
     {
-        let mut constraints: SmallVec<[_; 16]> = self.data.constraints.iter().collect();
+        let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect();
         let mut iteration = 0;
         let mut changed = true;
         while changed {
             changed = false;
             iteration += 1;
             debug!("---- {} Iteration {}{}", "#", tag, iteration);
-            constraints.retain(|(constraint, origin)| {
-                let (edge_changed, retain) = body(constraint, origin);
+            constraints.retain(|constraint| {
+                let (edge_changed, retain) = body(constraint);
                 if edge_changed {
                     debug!("Updated due to constraint {:?}", constraint);
                     changed = true;
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 0f14049ef2cca..cdbef568a6005 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1353,10 +1353,15 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
         "Present the input source, unstable (and less-pretty) variants;
         valid types are any of the types for `--pretty`, as well as:
+        `expanded`, `expanded,identified`,
+        `expanded,hygiene` (with internal representations),
         `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+        `flowgraph,unlabelled=<nodeid>` (unlabelled graphviz formatted flowgraph for node),
         `everybody_loops` (all function bodies replaced with `loop {}`),
-        `hir` (the HIR), `hir,identified`, or
-        `hir,typed` (HIR with types for each node)."),
+        `hir` (the HIR), `hir,identified`,
+        `hir,typed` (HIR with types for each node),
+        `hir-tree` (dump the raw HIR),
+        `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
     run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
         "run `dsymutil` and delete intermediate object files"),
     ui_testing: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 05a6cce895d1f..9a0610f45dec2 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2198,7 +2198,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
 
         let def_id = obligation.predicate.def_id();
 
-        if ty::is_trait_alias(self.tcx(), def_id) {
+        if self.tcx().is_trait_alias(def_id) {
             candidates.vec.push(TraitAliasCandidate(def_id.clone()));
         }
 
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 417e14054d24f..9328de4f6a0a1 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -311,6 +311,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             data @ DefPathData::Misc |
             data @ DefPathData::TypeNs(..) |
             data @ DefPathData::Trait(..) |
+            data @ DefPathData::TraitAlias(..) |
             data @ DefPathData::AssocTypeInTrait(..) |
             data @ DefPathData::AssocTypeInImpl(..) |
             data @ DefPathData::AssocExistentialInImpl(..) |
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index f1b36e8def88b..dd315cf42ce7e 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -3170,18 +3170,6 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefI
     None
 }
 
-/// 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)
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index e989ef823e979..75fc0f716a2f6 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -526,6 +526,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
+    /// True if `def_id` refers to a trait alias (i.e., `trait Foo = ...;`).
+    pub fn is_trait_alias(self, def_id: DefId) -> bool {
+        if let DefPathData::TraitAlias(_) = self.def_key(def_id).disambiguated_data.data {
+            true
+        } else {
+            false
+        }
+    }
+
     /// True if this def-id refers to the implicit constructor for
     /// a tuple struct like `struct Foo(u32)`.
     pub fn is_struct_constructor(self, def_id: DefId) -> bool {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 04e571863d42f..51e9192cd290d 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -409,6 +409,7 @@ impl PrintContext {
                     DefPathData::AssocTypeInImpl(_) |
                     DefPathData::AssocExistentialInImpl(_) |
                     DefPathData::Trait(_) |
+                    DefPathData::TraitAlias(_) |
                     DefPathData::Impl |
                     DefPathData::TypeNs(_) => {
                         break;
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index d1108304d11d9..d980c5a3d29c3 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -123,7 +123,8 @@ pub fn parse_pretty(sess: &Session,
                 sess.fatal(&format!("argument to `unpretty` must be one of `normal`, \
                                      `expanded`, `flowgraph[,unlabelled]=<nodeid>`, \
                                      `identified`, `expanded,identified`, `everybody_loops`, \
-                                     `hir`, `hir,identified`, `hir,typed`, or `mir`; got {}",
+                                     `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \
+                                     `mir` or `mir-cfg`; got {}",
                                     name));
             } else {
                 sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 7449b2b758302..736cca6bd64af 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -33,7 +33,11 @@ pub struct DiagnosticBuilder<'a> {
 /// it easy to declare such methods on the builder.
 macro_rules! forward {
     // Forward pattern for &self -> &Self
-    (pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n(&self, $($name: $ty),*) -> &Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -42,7 +46,11 @@ macro_rules! forward {
     };
 
     // Forward pattern for &mut self -> &mut Self
-    (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -52,10 +60,15 @@ macro_rules! forward {
 
     // Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
     // type parameter. No obvious way to make this more generic.
-    (pub fn $n:ident<S: Into<MultiSpan>>(
-                    &mut self,
-                    $($name:ident: $ty:ty),*
-                    $(,)*) -> &mut Self) => {
+    (
+        $(#[$attrs:meta])*
+        pub fn $n:ident<S: Into<MultiSpan>>(
+            &mut self,
+            $($name:ident: $ty:ty),*
+            $(,)*
+        ) -> &mut Self
+    ) => {
+        $(#[$attrs])*
         pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
             #[allow(deprecated)]
             self.diagnostic.$n($($name),*);
@@ -177,34 +190,43 @@ impl<'a> DiagnosticBuilder<'a> {
                                                   msg: &str,
                                                   ) -> &mut Self);
 
-    #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
-    forward!(pub fn span_suggestion_short(
-                                      &mut self,
-                                      sp: Span,
-                                      msg: &str,
-                                      suggestion: String,
-                                      ) -> &mut Self);
-
-    #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
-    forward!(pub fn multipart_suggestion(
-        &mut self,
-        msg: &str,
-        suggestion: Vec<(Span, String)>,
-    ) -> &mut Self);
-
-    #[deprecated(note = "Use `span_suggestion_with_applicability`")]
-    forward!(pub fn span_suggestion(&mut self,
-                                    sp: Span,
-                                    msg: &str,
-                                    suggestion: String,
-                                    ) -> &mut Self);
-
-    #[deprecated(note = "Use `span_suggestions_with_applicability`")]
-    forward!(pub fn span_suggestions(&mut self,
-                                     sp: Span,
-                                     msg: &str,
-                                     suggestions: Vec<String>,
-                                     ) -> &mut Self);
+    forward!(
+        #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
+        pub fn span_suggestion_short(
+            &mut self,
+            sp: Span,
+            msg: &str,
+            suggestion: String,
+        ) -> &mut Self
+    );
+
+    forward!(
+        #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
+        pub fn multipart_suggestion(
+            &mut self,
+            msg: &str,
+            suggestion: Vec<(Span, String)>,
+        ) -> &mut Self
+    );
+
+    forward!(
+        #[deprecated(note = "Use `span_suggestion_with_applicability`")]
+        pub fn span_suggestion(
+            &mut self,
+            sp: Span,
+            msg: &str,
+            suggestion: String,
+        ) -> &mut Self
+    );
+
+    forward!(
+        #[deprecated(note = "Use `span_suggestions_with_applicability`")]
+        pub fn span_suggestions(&mut self,
+            sp: Span,
+            msg: &str,
+            suggestions: Vec<String>,
+        ) -> &mut Self
+    );
 
     pub fn multipart_suggestion_with_applicability(&mut self,
                                               msg: &str,
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index f895542e43ada..f6c381ff74cc9 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1474,7 +1474,7 @@ impl KeywordIdents {
                     _ => {},
                 }
                 TokenTree::Delimited(_, _, tts) => {
-                    self.check_tokens(cx, tts.stream())
+                    self.check_tokens(cx, tts)
                 },
             }
         }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index dc8db5be5820a..1f07e8f478b5a 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -418,6 +418,7 @@ impl<'tcx> EntryKind<'tcx> {
             EntryKind::Mod(_) => Def::Mod(did),
             EntryKind::Variant(_) => Def::Variant(did),
             EntryKind::Trait(_) => Def::Trait(did),
+            EntryKind::TraitAlias(_) => Def::TraitAlias(did),
             EntryKind::Enum(..) => Def::Enum(did),
             EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
             EntryKind::ForeignType => Def::ForeignTy(did),
@@ -520,17 +521,26 @@ impl<'a, 'tcx> CrateMetadata {
     }
 
     pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
-        let data = match self.entry(item_id).kind {
-            EntryKind::Trait(data) => data.decode((self, sess)),
-            _ => bug!(),
-        };
-
-        ty::TraitDef::new(self.local_def_id(item_id),
-                          data.unsafety,
-                          data.paren_sugar,
-                          data.has_auto_impl,
-                          data.is_marker,
-                          self.def_path_table.def_path_hash(item_id))
+        match self.entry(item_id).kind {
+            EntryKind::Trait(data) => {
+                let data = data.decode((self, sess));
+                ty::TraitDef::new(self.local_def_id(item_id),
+                                  data.unsafety,
+                                  data.paren_sugar,
+                                  data.has_auto_impl,
+                                  data.is_marker,
+                                  self.def_path_table.def_path_hash(item_id))
+            },
+            EntryKind::TraitAlias(_) => {
+                ty::TraitDef::new(self.local_def_id(item_id),
+                                  hir::Unsafety::Normal,
+                                  false,
+                                  false,
+                                  false,
+                                  self.def_path_table.def_path_hash(item_id))
+            },
+            _ => bug!("def-index does not refer to trait or trait alias"),
+        }
     }
 
     fn get_variant(&self,
@@ -615,10 +625,13 @@ impl<'a, 'tcx> CrateMetadata {
                                 item_id: DefIndex,
                                 tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                 -> ty::GenericPredicates<'tcx> {
-        match self.entry(item_id).kind {
-            EntryKind::Trait(data) => data.decode(self).super_predicates.decode((self, tcx)),
-            _ => bug!(),
-        }
+        let super_predicates = match self.entry(item_id).kind {
+            EntryKind::Trait(data) => data.decode(self).super_predicates,
+            EntryKind::TraitAlias(data) => data.decode(self).super_predicates,
+            _ => bug!("def-index does not refer to trait or trait alias"),
+        };
+
+        super_predicates.decode((self, tcx))
     }
 
     pub fn get_generics(&self,
@@ -1014,7 +1027,8 @@ impl<'a, 'tcx> CrateMetadata {
         }
         def_key.parent.and_then(|parent_index| {
             match self.entry(parent_index).kind {
-                EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
+                EntryKind::Trait(_) |
+                EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)),
                 _ => None,
             }
         })
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 2de1637fb0d9d..afb0218501d18 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1128,8 +1128,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
                 EntryKind::Impl(self.lazy(&data))
             }
-            hir::ItemKind::Trait(..) |
-            hir::ItemKind::TraitAlias(..) => {
+            hir::ItemKind::Trait(..) => {
                 let trait_def = tcx.trait_def(def_id);
                 let data = TraitData {
                     unsafety: trait_def.unsafety,
@@ -1141,6 +1140,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
 
                 EntryKind::Trait(self.lazy(&data))
             }
+            hir::ItemKind::TraitAlias(..) => {
+                let data = TraitAliasData {
+                    super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
+                };
+
+                EntryKind::TraitAlias(self.lazy(&data))
+            }
             hir::ItemKind::ExternCrate(_) |
             hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
         };
@@ -1214,6 +1220,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 hir::ItemKind::Impl(..) |
                 hir::ItemKind::Existential(..) |
                 hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)),
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)),
                 _ => None,
             },
             predicates: match item.node {
@@ -1226,7 +1233,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 hir::ItemKind::Union(..) |
                 hir::ItemKind::Impl(..) |
                 hir::ItemKind::Existential(..) |
-                hir::ItemKind::Trait(..) => Some(self.encode_predicates(def_id)),
+                hir::ItemKind::Trait(..) |
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)),
                 _ => None,
             },
 
@@ -1236,7 +1244,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
             // hack. (No reason not to expand it in the future if
             // necessary.)
             predicates_defined_on: match item.node {
-                hir::ItemKind::Trait(..) => Some(self.encode_predicates_defined_on(def_id)),
+                hir::ItemKind::Trait(..) |
+                hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)),
                 _ => None, // not *wrong* for other kinds of items, but not needed
             },
 
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 25f499bc31984..f3ff9747625f5 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -316,6 +316,7 @@ pub enum EntryKind<'tcx> {
     AssociatedType(AssociatedContainer),
     AssociatedExistential(AssociatedContainer),
     AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
+    TraitAlias(Lazy<TraitAliasData<'tcx>>),
 }
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
@@ -370,6 +371,9 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
             EntryKind::Trait(ref trait_data) => {
                 trait_data.hash_stable(hcx, hasher);
             }
+            EntryKind::TraitAlias(ref trait_alias_data) => {
+                trait_alias_data.hash_stable(hcx, hasher);
+            }
             EntryKind::Impl(ref impl_data) => {
                 impl_data.hash_stable(hcx, hasher);
             }
@@ -474,6 +478,15 @@ impl_stable_hash_for!(struct TraitData<'tcx> {
     super_predicates
 });
 
+#[derive(RustcEncodable, RustcDecodable)]
+pub struct TraitAliasData<'tcx> {
+    pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
+}
+
+impl_stable_hash_for!(struct TraitAliasData<'tcx> {
+    super_predicates
+});
+
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct ImplData<'tcx> {
     pub polarity: hir::ImplPolarity,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 698037e237101..dcbb9ff4a7576 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -13,7 +13,7 @@ extern crate rustc_typeck;
 extern crate syntax_pos;
 extern crate rustc_data_structures;
 
-use rustc::hir::{self, Node, PatKind};
+use rustc::hir::{self, Node, PatKind, AssociatedItemKind};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -548,7 +548,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
                         let mut reach = self.reach(trait_item_ref.id.node_id, item_level);
                         reach.generics().predicates();
 
-                        if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
+                        if trait_item_ref.kind == AssociatedItemKind::Type &&
                            !trait_item_ref.defaultness.has_value() {
                             // No type to visit.
                         } else {
@@ -1343,11 +1343,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                         if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
                             let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
                             match impl_item_ref.kind {
-                                hir::AssociatedItemKind::Const => {
+                                AssociatedItemKind::Const => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
-                                hir::AssociatedItemKind::Method { has_self: false } => {
+                                AssociatedItemKind::Method { has_self: false } => {
                                     found_pub_static = true;
                                     intravisit::walk_impl_item(self, impl_item);
                                 }
@@ -1568,6 +1568,24 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
             in_assoc_ty: false,
         }
     }
+
+    fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind,
+                                defaultness: hir::Defaultness, vis: ty::Visibility) {
+        let mut check = self.check(node_id, vis);
+
+        let (check_ty, is_assoc_ty) = match assoc_item_kind {
+            AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false),
+            AssociatedItemKind::Type => (defaultness.has_value(), true),
+            // `ty()` for existential types is the underlying type,
+            // it's not a part of interface, so we skip it.
+            AssociatedItemKind::Existential => (false, true),
+        };
+        check.in_assoc_ty = is_assoc_ty;
+        check.generics().predicates();
+        if check_ty {
+            check.ty();
+        }
+    }
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
@@ -1602,16 +1620,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
                 self.check(item.id, item_visibility).generics().predicates();
 
                 for trait_item_ref in trait_item_refs {
-                    let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
-                    check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
-                    check.generics().predicates();
-
-                    if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
-                       !trait_item_ref.defaultness.has_value() {
-                        // No type to visit.
-                    } else {
-                        check.ty();
-                    }
+                    self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind,
+                                                  trait_item_ref.defaultness, item_visibility);
                 }
             }
             hir::ItemKind::TraitAlias(..) => {
@@ -1657,9 +1667,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
                     } else {
                         impl_vis
                     };
-                    let mut check = self.check(impl_item.id, impl_item_vis);
-                    check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
-                    check.generics().predicates().ty();
+                    self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind,
+                                                  impl_item_ref.defaultness, impl_item_vis);
                 }
             }
         }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index a452bbf0c9d54..35616cc03a936 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -21,6 +21,8 @@ use std::cell::Cell;
 use std::ptr;
 use rustc_data_structures::sync::Lrc;
 
+use errors::Applicability;
+
 use syntax::ast::{Name, Ident};
 use syntax::attr;
 
@@ -345,7 +347,12 @@ impl<'a> Resolver<'a> {
                 let module = if orig_name.is_none() && ident.name == keywords::SelfLower.name() {
                     self.session
                         .struct_span_err(item.span, "`extern crate self;` requires renaming")
-                        .span_suggestion(item.span, "try", "extern crate self as name;".into())
+                        .span_suggestion_with_applicability(
+                            item.span,
+                            "try",
+                            "extern crate self as name;".into(),
+                            Applicability::HasPlaceholders,
+                        )
                         .emit();
                     return;
                 } else if orig_name == Some(keywords::SelfLower.name()) {
@@ -673,6 +680,9 @@ impl<'a> Resolver<'a> {
                 }
                 module.populated.set(true);
             }
+            Def::TraitAlias(..) => {
+                self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
+            }
             Def::Struct(..) | Def::Union(..) => {
                 self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index a58d63e1ca28b..1cd44042c1de9 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -4866,8 +4866,13 @@ impl<'a> Resolver<'a> {
                 } else if ident.span.rust_2018() {
                     let msg = "relative paths are not supported in visibilities on 2018 edition";
                     self.session.struct_span_err(ident.span, msg)
-                                .span_suggestion(path.span, "try", format!("crate::{}", path))
-                                .emit();
+                        .span_suggestion_with_applicability(
+                            path.span,
+                            "try",
+                            format!("crate::{}", path),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
                     return ty::Visibility::Public;
                 } else {
                     let ctxt = ident.span.ctxt();
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index 5502a1d186eee..9bdef3051e589 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -158,7 +158,8 @@ crate fn program_clauses_for<'a, 'tcx>(
     def_id: DefId,
 ) -> Clauses<'tcx> {
     match tcx.def_key(def_id).disambiguated_data.data {
-        DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
+        DefPathData::Trait(_) |
+        DefPathData::TraitAlias(_) => program_clauses_for_trait(tcx, def_id),
         DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
         DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
         DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id),
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 534279e981d62..e89506aaf99f9 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -2,7 +2,7 @@
 //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
 //! instance of `AstConv`.
 
-use errors::{Applicability, FatalError, DiagnosticId};
+use errors::{Applicability, DiagnosticId};
 use hir::{self, GenericArg, GenericArgs};
 use hir::def::Def;
 use hir::def_id::DefId;
@@ -690,27 +690,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
     {
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
 
-        let trait_def_id = self.trait_def_id(trait_ref);
         self.ast_path_to_mono_trait_ref(trait_ref.path.span,
-                                        trait_def_id,
+                                        trait_ref.trait_def_id(),
                                         self_ty,
                                         trait_ref.path.segments.last().unwrap())
     }
 
-    /// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
-    fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
-        let path = &trait_ref.path;
-        match path.def {
-            Def::Trait(trait_def_id) => trait_def_id,
-            Def::TraitAlias(alias_def_id) => alias_def_id,
-            Def::Err => {
-                FatalError.raise();
-            }
-            _ => unreachable!(),
-        }
-    }
-
-    /// The given trait ref must actually be a trait.
+    /// The given trait-ref must actually be a trait.
     pub(super) fn instantiate_poly_trait_ref_inner(&self,
         trait_ref: &hir::TraitRef,
         self_ty: Ty<'tcx>,
@@ -718,7 +704,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         speculative: bool)
         -> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
     {
-        let trait_def_id = self.trait_def_id(trait_ref);
+        let trait_def_id = trait_ref.trait_def_id();
 
         debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
 
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 1767af4870d3b..47f258e1aea74 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -1,5 +1,6 @@
 use check::{FnCtxt, Expectation, Diverges, Needs};
 use check::coercion::CoerceMany;
+use errors::Applicability;
 use rustc::hir::{self, PatKind};
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -989,7 +990,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                     let suggested_name =
                         find_best_match_for_name(input, &ident.as_str(), None);
                     if let Some(suggested_name) = suggested_name {
-                        err.span_suggestion(*span, "did you mean", suggested_name.to_string());
+                        err.span_suggestion_with_applicability(
+                            *span,
+                            "did you mean",
+                            suggested_name.to_string(),
+                            Applicability::MaybeIncorrect,
+                        );
+
                         // we don't want to throw `E0027` in case we have thrown `E0026` for them
                         unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
                     }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 3a546f84469e6..93f14a2ea6f64 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -715,7 +715,7 @@ fn super_predicates_of<'a, 'tcx>(
     // 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 is_trait_alias = tcx.is_trait_alias(trait_def_id);
     let superbounds2 = icx.type_parameter_bounds_in_generics(
         generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 99ab9fbcf5fa0..bbcaaacbab523 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -15,7 +15,7 @@ use rustc_target::spec::abi::Abi;
 use source_map::{dummy_spanned, respan, Spanned};
 use symbol::{keywords, Symbol};
 use syntax_pos::{Span, DUMMY_SP};
-use tokenstream::{ThinTokenStream, TokenStream};
+use tokenstream::TokenStream;
 use ThinVec;
 
 use rustc_data_structures::fx::FxHashSet;
@@ -1216,7 +1216,7 @@ pub type Mac = Spanned<Mac_>;
 pub struct Mac_ {
     pub path: Path,
     pub delim: MacDelimiter,
-    pub tts: ThinTokenStream,
+    pub tts: TokenStream,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
@@ -1228,13 +1228,13 @@ pub enum MacDelimiter {
 
 impl Mac_ {
     pub fn stream(&self) -> TokenStream {
-        self.tts.stream()
+        self.tts.clone()
     }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct MacroDef {
-    pub tokens: ThinTokenStream,
+    pub tokens: TokenStream,
     pub legacy: bool,
 }
 
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index f83c1ec145523..f6d7590a7945e 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -570,7 +570,7 @@ impl MetaItemKind {
             }
             Some(TokenTree::Delimited(_, delim, ref tts)) if delim == token::Paren => {
                 tokens.next();
-                tts.stream()
+                tts.clone()
             }
             _ => return Some(MetaItemKind::Word),
         };
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index c3124144009ab..c01e7f538b90d 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -748,7 +748,7 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &TokenTree, quoted: bool) -> Vec<ast::Stmt
         },
         TokenTree::Delimited(span, delim, ref tts) => {
             let mut stmts = statements_mk_tt(cx, &TokenTree::open_tt(span.open, delim), false);
-            stmts.extend(statements_mk_tts(cx, tts.stream()));
+            stmts.extend(statements_mk_tts(cx, tts.clone()));
             stmts.extend(statements_mk_tt(cx, &TokenTree::close_tt(span.close, delim), false));
             stmts
         }
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 8ac103856dcd1..a4c3b38f691ed 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -598,7 +598,7 @@ pub fn noop_fold_tt<T: Folder>(tt: TokenTree, fld: &mut T) -> TokenTree {
         TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
             DelimSpan::from_pair(fld.new_span(span.open), fld.new_span(span.close)),
             delim,
-            fld.fold_tts(tts.stream()).into(),
+            fld.fold_tts(tts).into(),
         ),
     }
 }
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index ea205530ca5cc..ddb350faa546b 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -817,7 +817,7 @@ mod tests {
                 )
                 if name_macro_rules.name == "macro_rules"
                 && name_zip.name == "zip" => {
-                    let tts = &macro_tts.stream().trees().collect::<Vec<_>>();
+                    let tts = &macro_tts.trees().collect::<Vec<_>>();
                     match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
                         (
                             3,
@@ -826,7 +826,7 @@ mod tests {
                             Some(&TokenTree::Delimited(_, second_delim, ref second_tts)),
                         )
                         if macro_delim == token::Paren => {
-                            let tts = &first_tts.stream().trees().collect::<Vec<_>>();
+                            let tts = &first_tts.trees().collect::<Vec<_>>();
                             match (tts.len(), tts.get(0), tts.get(1)) {
                                 (
                                     2,
@@ -836,7 +836,7 @@ mod tests {
                                 if first_delim == token::Paren && ident.name == "a" => {},
                                 _ => panic!("value 3: {:?} {:?}", first_delim, first_tts),
                             }
-                            let tts = &second_tts.stream().trees().collect::<Vec<_>>();
+                            let tts = &second_tts.trees().collect::<Vec<_>>();
                             match (tts.len(), tts.get(0), tts.get(1)) {
                                 (
                                     2,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 5b430d13516b4..7e15b23127655 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -46,7 +46,7 @@ use print::pprust;
 use ptr::P;
 use parse::PResult;
 use ThinVec;
-use tokenstream::{self, DelimSpan, ThinTokenStream, TokenTree, TokenStream};
+use tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
 use symbol::{Symbol, keywords};
 
 use std::borrow::Cow;
@@ -280,17 +280,17 @@ struct TokenCursorFrame {
 /// on the parser.
 #[derive(Clone)]
 enum LastToken {
-    Collecting(Vec<TokenStream>),
-    Was(Option<TokenStream>),
+    Collecting(Vec<TreeAndJoint>),
+    Was(Option<TreeAndJoint>),
 }
 
 impl TokenCursorFrame {
-    fn new(sp: DelimSpan, delim: DelimToken, tts: &ThinTokenStream) -> Self {
+    fn new(sp: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self {
         TokenCursorFrame {
             delim: delim,
             span: sp,
             open_delim: delim == token::NoDelim,
-            tree_cursor: tts.stream().into_trees(),
+            tree_cursor: tts.clone().into_trees(),
             close_delim: delim == token::NoDelim,
             last_token: LastToken::Was(None),
         }
@@ -2330,7 +2330,7 @@ impl<'a> Parser<'a> {
         })
     }
 
-    fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, ThinTokenStream)> {
+    fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> {
         let delim = match self.token {
             token::OpenDelim(delim) => delim,
             _ => {
@@ -2350,7 +2350,7 @@ impl<'a> Parser<'a> {
             token::Brace => MacDelimiter::Brace,
             token::NoDelim => self.bug("unexpected no delimiter"),
         };
-        Ok((delim, tts.stream().into()))
+        Ok((delim, tts.into()))
     }
 
     /// At the bottom (top?) of the precedence hierarchy,
@@ -4063,12 +4063,13 @@ impl<'a> Parser<'a> {
 
         if let Some(mut err) = delayed_err {
             if let Some(etc_span) = etc_span {
-                err.multipart_suggestion(
+                err.multipart_suggestion_with_applicability(
                     "move the `..` to the end of the field list",
                     vec![
                         (etc_span, String::new()),
                         (self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
                     ],
+                    Applicability::MachineApplicable,
                 );
             }
             err.emit();
@@ -4641,7 +4642,7 @@ impl<'a> Parser<'a> {
                 let ident = self.parse_ident()?;
                 let tokens = if self.check(&token::OpenDelim(token::Brace)) {
                     match self.parse_token_tree() {
-                        TokenTree::Delimited(_, _, tts) => tts.stream(),
+                        TokenTree::Delimited(_, _, tts) => tts,
                         _ => unreachable!(),
                     }
                 } else if self.check(&token::OpenDelim(token::Paren)) {
@@ -6904,7 +6905,11 @@ impl<'a> Parser<'a> {
 
             let mut err = self.struct_span_err(fixed_name_sp, error_msg);
             err.span_label(fixed_name_sp, "dash-separated idents are not valid");
-            err.multipart_suggestion(suggestion_msg, replacement);
+            err.multipart_suggestion_with_applicability(
+                suggestion_msg,
+                replacement,
+                Applicability::MachineApplicable,
+            );
             err.emit();
         }
         Ok(ident)
@@ -7757,7 +7762,7 @@ impl<'a> Parser<'a> {
             &mut self.token_cursor.stack[prev].last_token
         };
 
-        // Pull our the toekns that we've collected from the call to `f` above
+        // Pull out the tokens that we've collected from the call to `f` above.
         let mut collected_tokens = match *last_token {
             LastToken::Collecting(ref mut v) => mem::replace(v, Vec::new()),
             LastToken::Was(_) => panic!("our vector went away?"),
@@ -7776,10 +7781,9 @@ impl<'a> Parser<'a> {
         // call. In that case we need to record all the tokens we collected in
         // our parent list as well. To do that we push a clone of our stream
         // onto the previous list.
-        let stream = collected_tokens.into_iter().collect::<TokenStream>();
         match prev_collecting {
             Some(mut list) => {
-                list.push(stream.clone());
+                list.extend(collected_tokens.iter().cloned());
                 list.extend(extra_token);
                 *last_token = LastToken::Collecting(list);
             }
@@ -7788,7 +7792,7 @@ impl<'a> Parser<'a> {
             }
         }
 
-        Ok((ret?, stream))
+        Ok((ret?, TokenStream::new(collected_tokens)))
     }
 
     pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 2ad3d3a6d6487..c53594032a00a 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -807,7 +807,7 @@ pub trait PrintState<'a> {
             TokenTree::Delimited(_, delim, tts) => {
                 self.writer().word(token_to_string(&token::OpenDelim(delim)))?;
                 self.writer().space()?;
-                self.print_tts(tts.stream())?;
+                self.print_tts(tts)?;
                 self.writer().space()?;
                 self.writer().word(token_to_string(&token::CloseDelim(delim)))
             },
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index fb72ef9c956ce..f5d2d6f18ee87 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -41,7 +41,7 @@ pub enum TokenTree {
     /// A single token
     Token(Span, token::Token),
     /// A delimited sequence of token trees
-    Delimited(DelimSpan, DelimToken, ThinTokenStream),
+    Delimited(DelimSpan, DelimToken, TokenStream),
 }
 
 impl TokenTree {
@@ -62,8 +62,7 @@ impl TokenTree {
             (&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => tk == tk2,
             (&TokenTree::Delimited(_, delim, ref tts),
              &TokenTree::Delimited(_, delim2, ref tts2)) => {
-                delim == delim2 &&
-                tts.stream().eq_unspanned(&tts2.stream())
+                delim == delim2 && tts.eq_unspanned(&tts2)
             }
             (_, _) => false,
         }
@@ -81,8 +80,7 @@ impl TokenTree {
             }
             (&TokenTree::Delimited(_, delim, ref tts),
              &TokenTree::Delimited(_, delim2, ref tts2)) => {
-                delim == delim2 &&
-                tts.stream().probably_equal_for_proc_macro(&tts2.stream())
+                delim == delim2 && tts.probably_equal_for_proc_macro(&tts2)
             }
             (_, _) => false,
         }
@@ -113,7 +111,7 @@ impl TokenTree {
     }
 
     pub fn joint(self) -> TokenStream {
-        TokenStream::Tree(self, Joint)
+        TokenStream::new(vec![(self, Joint)])
     }
 
     /// Returns the opening delimiter as a token tree.
@@ -143,18 +141,19 @@ impl TokenTree {
 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
 /// instead of a representation of the abstract syntax tree.
 /// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat.
+///
+/// The use of `Option` is an optimization that avoids the need for an
+/// allocation when the stream is empty. However, it is not guaranteed that an
+/// empty stream is represented with `None`; it may be represented as a `Some`
+/// around an empty `Vec`.
 #[derive(Clone, Debug)]
-pub enum TokenStream {
-    Empty,
-    Tree(TokenTree, IsJoint),
-    Stream(Lrc<Vec<TreeAndJoint>>),
-}
+pub struct TokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
 
 pub type TreeAndJoint = (TokenTree, IsJoint);
 
 // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
 #[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32);
+static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 8);
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum IsJoint {
@@ -169,7 +168,7 @@ impl TokenStream {
     /// separating the two arguments with a comma for diagnostic suggestions.
     pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
         // Used to suggest if a user writes `foo!(a b);`
-        if let TokenStream::Stream(ref stream) = self {
+        if let Some(ref stream) = self.0 {
             let mut suggestion = None;
             let mut iter = stream.iter().enumerate().peekable();
             while let Some((pos, ts)) = iter.next() {
@@ -201,7 +200,7 @@ impl TokenStream {
 
 impl From<TokenTree> for TokenStream {
     fn from(tree: TokenTree) -> TokenStream {
-        TokenStream::Tree(tree, NonJoint)
+        TokenStream::new(vec![(tree, NonJoint)])
     }
 }
 
@@ -233,7 +232,7 @@ impl PartialEq<TokenStream> for TokenStream {
 
 impl TokenStream {
     pub fn len(&self) -> usize {
-        if let TokenStream::Stream(ref slice) = self {
+        if let Some(ref slice) = self.0 {
             slice.len()
         } else {
             0
@@ -241,13 +240,13 @@ impl TokenStream {
     }
 
     pub fn empty() -> TokenStream {
-        TokenStream::Empty
+        TokenStream(None)
     }
 
     pub fn is_empty(&self) -> bool {
-        match self {
-            TokenStream::Empty => true,
-            _ => false,
+        match self.0 {
+            None => true,
+            Some(ref stream) => stream.is_empty(),
         }
     }
 
@@ -258,10 +257,9 @@ impl TokenStream {
             _ => {
                 let mut vec = vec![];
                 for stream in streams {
-                    match stream {
-                        TokenStream::Empty => {},
-                        TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
-                        TokenStream::Stream(stream2) => vec.extend(stream2.iter().cloned()),
+                    match stream.0 {
+                        None => {},
+                        Some(stream2) => vec.extend(stream2.iter().cloned()),
                     }
                 }
                 TokenStream::new(vec)
@@ -269,22 +267,16 @@ impl TokenStream {
         }
     }
 
-    pub fn new(mut streams: Vec<TreeAndJoint>) -> TokenStream {
+    pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
         match streams.len() {
-            0 => TokenStream::empty(),
-            1 => {
-                let (tree, is_joint) = streams.pop().unwrap();
-                TokenStream::Tree(tree, is_joint)
-            }
-            _ => TokenStream::Stream(Lrc::new(streams)),
+            0 => TokenStream(None),
+            _ => TokenStream(Some(Lrc::new(streams))),
         }
     }
 
     pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec<TreeAndJoint>) {
-        match self {
-            TokenStream::Empty => {}
-            TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
-            TokenStream::Stream(stream) => vec.extend(stream.iter().cloned()),
+        if let Some(stream) = self.0 {
+            vec.extend(stream.iter().cloned());
         }
     }
 
@@ -349,51 +341,36 @@ impl TokenStream {
     }
 
     pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        match self {
-            TokenStream::Empty => TokenStream::Empty,
-            TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(0, tree), is_joint),
-            TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+        TokenStream(self.0.map(|stream| {
+            Lrc::new(
                 stream
                     .iter()
                     .enumerate()
                     .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
-                    .collect()
-            )),
-        }
+                    .collect())
+        }))
     }
 
     pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
-        match self {
-            TokenStream::Empty => TokenStream::Empty,
-            TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint),
-            TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+        TokenStream(self.0.map(|stream| {
+            Lrc::new(
                 stream
                     .iter()
                     .map(|(tree, is_joint)| (f(tree.clone()), *is_joint))
-                    .collect()
-            )),
-        }
+                    .collect())
+        }))
     }
 
-    fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> {
-        match self {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, is_joint) => Some((tree.clone(), *is_joint)),
-            TokenStream::Stream(ref stream) => Some(stream.first().unwrap().clone())
-        }
+    fn first_tree_and_joint(&self) -> Option<TreeAndJoint> {
+        self.0.as_ref().map(|stream| {
+            stream.first().unwrap().clone()
+        })
     }
 
     fn last_tree_if_joint(&self) -> Option<TokenTree> {
-        match self {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, is_joint) => {
-                if *is_joint == Joint {
-                    Some(tree.clone())
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) => {
+        match self.0 {
+            None => None,
+            Some(ref stream) => {
                 if let (tree, Joint) = stream.last().unwrap() {
                     Some(tree.clone())
                 } else {
@@ -422,7 +399,7 @@ impl TokenStreamBuilder {
                     self.push_all_but_last_tree(&last_stream);
                     let glued_span = last_span.to(span);
                     let glued_tt = TokenTree::Token(glued_span, glued_tok);
-                    let glued_tokenstream = TokenStream::Tree(glued_tt, is_joint);
+                    let glued_tokenstream = TokenStream::new(vec![(glued_tt, is_joint)]);
                     self.0.push(glued_tokenstream);
                     self.push_all_but_first_tree(&stream);
                     return
@@ -437,23 +414,21 @@ impl TokenStreamBuilder {
     }
 
     fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
-        if let TokenStream::Stream(ref streams) = stream {
+        if let Some(ref streams) = stream.0 {
             let len = streams.len();
             match len {
                 1 => {}
-                2 => self.0.push(TokenStream::Tree(streams[0].0.clone(), streams[0].1)),
-                _ => self.0.push(TokenStream::Stream(Lrc::new(streams[0 .. len - 1].to_vec()))),
+                _ => self.0.push(TokenStream(Some(Lrc::new(streams[0 .. len - 1].to_vec())))),
             }
         }
     }
 
     fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
-        if let TokenStream::Stream(ref streams) = stream {
+        if let Some(ref streams) = stream.0 {
             let len = streams.len();
             match len {
                 1 => {}
-                2 => self.0.push(TokenStream::Tree(streams[1].0.clone(), streams[1].1)),
-                _ => self.0.push(TokenStream::Stream(Lrc::new(streams[1 .. len].to_vec()))),
+                _ => self.0.push(TokenStream(Some(Lrc::new(streams[1 .. len].to_vec())))),
             }
         }
     }
@@ -479,17 +454,9 @@ impl Cursor {
     }
 
     pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
-        match self.stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, ref is_joint) => {
-                if self.index == 0 {
-                    self.index = 1;
-                    Some((tree.clone(), *is_joint))
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) => {
+        match self.stream.0 {
+            None => None,
+            Some(ref stream) => {
                 if self.index < stream.len() {
                     self.index += 1;
                     Some(stream[self.index - 1].clone())
@@ -505,63 +472,19 @@ impl Cursor {
             return;
         }
         let index = self.index;
-        let stream = mem::replace(&mut self.stream, TokenStream::Empty);
+        let stream = mem::replace(&mut self.stream, TokenStream(None));
         *self = TokenStream::from_streams(vec![stream, new_stream]).into_trees();
         self.index = index;
     }
 
     pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
-        match self.stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(ref tree, _) => {
-                if n == 0 && self.index == 0 {
-                    Some(tree.clone())
-                } else {
-                    None
-                }
-            }
-            TokenStream::Stream(ref stream) =>
-                stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
+        match self.stream.0 {
+            None => None,
+            Some(ref stream) => stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
         }
     }
 }
 
-/// The `TokenStream` type is large enough to represent a single `TokenTree` without allocation.
-/// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`.
-/// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion.
-#[derive(Debug, Clone)]
-pub struct ThinTokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
-
-impl ThinTokenStream {
-    pub fn stream(&self) -> TokenStream {
-        self.clone().into()
-    }
-}
-
-impl From<TokenStream> for ThinTokenStream {
-    fn from(stream: TokenStream) -> ThinTokenStream {
-        ThinTokenStream(match stream {
-            TokenStream::Empty => None,
-            TokenStream::Tree(tree, is_joint) => Some(Lrc::new(vec![(tree, is_joint)])),
-            TokenStream::Stream(stream) => Some(stream),
-        })
-    }
-}
-
-impl From<ThinTokenStream> for TokenStream {
-    fn from(stream: ThinTokenStream) -> TokenStream {
-        stream.0.map(TokenStream::Stream).unwrap_or_else(TokenStream::empty)
-    }
-}
-
-impl Eq for ThinTokenStream {}
-
-impl PartialEq<ThinTokenStream> for ThinTokenStream {
-    fn eq(&self, other: &ThinTokenStream) -> bool {
-        TokenStream::from(self.clone()) == TokenStream::from(other.clone())
-    }
-}
-
 impl fmt::Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&pprust::tokens_to_string(self.clone()))
@@ -580,18 +503,6 @@ impl Decodable for TokenStream {
     }
 }
 
-impl Encodable for ThinTokenStream {
-    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
-        TokenStream::from(self.clone()).encode(encoder)
-    }
-}
-
-impl Decodable for ThinTokenStream {
-    fn decode<D: Decoder>(decoder: &mut D) -> Result<ThinTokenStream, D::Error> {
-        TokenStream::decode(decoder).map(Into::into)
-    }
-}
-
 #[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
 pub struct DelimSpan {
     pub open: Span,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 156546bbba94a..8cbd47ca70fde 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -832,7 +832,7 @@ pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute)
 pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) {
     match tt {
         TokenTree::Token(_, tok) => visitor.visit_token(tok),
-        TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts.stream()),
+        TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts),
     }
 }
 
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs
index 158cbc791ef50..7de9b9343a8fa 100644
--- a/src/libsyntax_ext/proc_macro_server.rs
+++ b/src/libsyntax_ext/proc_macro_server.rs
@@ -269,7 +269,7 @@ impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> {
         };
 
         let tree = tokenstream::TokenTree::Token(span, token);
-        TokenStream::Tree(tree, if joint { Joint } else { NonJoint })
+        TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })])
     }
 }
 
diff --git a/src/test/ui/issues/issue-56488.rs b/src/test/ui/issues/issue-56488.rs
new file mode 100644
index 0000000000000..e2f3996927b7f
--- /dev/null
+++ b/src/test/ui/issues/issue-56488.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+mod alpha {
+    pub trait A {}
+    pub trait C = A;
+}
+
+#[allow(unused_imports)]
+use alpha::C;
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
new file mode 100644
index 0000000000000..0d18965ee7338
--- /dev/null
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+trait Foo {}
+
+impl Foo for dyn Send {}
+
+impl Foo for dyn Send + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync {}
+
+impl Foo for dyn Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
new file mode 100644
index 0000000000000..928c92ef91655
--- /dev/null
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
@@ -0,0 +1,39 @@
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:7:1
+   |
+LL | impl Foo for dyn Send {}
+   | --------------------- first implementation here
+LL | 
+LL | impl Foo for dyn Send + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+   |
+   = note: #[deny(order_dependent_trait_objects)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:13:1
+   |
+LL | impl Foo for dyn Send + Sync {}
+   | ---------------------------- first implementation here
+LL | 
+LL | impl Foo for dyn Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+  --> $DIR/lint-incoherent-auto-trait-objects.rs:17:1
+   |
+LL | impl Foo for dyn Sync + Send {}
+   | ---------------------------- first implementation here
+...
+LL | impl Foo for dyn Send + Sync + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
index c6e86ed64ae73..81d23959fd4ad 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.rs
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -1,7 +1,7 @@
 // Private types and traits are not allowed in interfaces of associated types.
 // This test also ensures that the checks are performed even inside private modules.
 
-#![feature(associated_type_defaults)]
+#![feature(associated_type_defaults, existential_type)]
 
 mod m {
     struct Priv;
@@ -23,10 +23,17 @@ mod m {
 
         type Alias4 = Priv;
         //~^ ERROR private type `m::Priv` in public interface
+
+        type Exist;
+        fn infer_exist() -> Self::Exist;
     }
     impl PubTr for u8 {
         type Alias1 = Priv;
         //~^ ERROR private type `m::Priv` in public interface
+
+        existential type Exist: PrivTr;
+        //~^ ERROR private trait `m::PrivTr` in public interface
+        fn infer_exist() -> Self::Exist { Priv }
     }
 }
 
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index 6740277c9a7c1..0e5dab1a08c37 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -6,7 +6,7 @@ LL | |         //~^ WARN private trait `m::PrivTr` in public interface
 LL | |         //~| WARN this was previously accepted
 LL | |         //~| WARN private type `m::Priv` in public interface
 ...  |
-LL | |         //~^ ERROR private type `m::Priv` in public interface
+LL | |         fn infer_exist() -> Self::Exist;
 LL | |     }
    | |_____^
    |
@@ -22,7 +22,7 @@ LL | |         //~^ WARN private trait `m::PrivTr` in public interface
 LL | |         //~| WARN this was previously accepted
 LL | |         //~| WARN private type `m::Priv` in public interface
 ...  |
-LL | |         //~^ ERROR private type `m::Priv` in public interface
+LL | |         fn infer_exist() -> Self::Exist;
 LL | |     }
    | |_____^
    |
@@ -39,7 +39,7 @@ LL |         type Alias4 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `m::Priv` in public interface
-  --> $DIR/private-in-public-assoc-ty.rs:28:9
+  --> $DIR/private-in-public-assoc-ty.rs:31:9
    |
 LL |     struct Priv;
    |     - `m::Priv` declared as private
@@ -47,6 +47,16 @@ LL |     struct Priv;
 LL |         type Alias1 = Priv;
    |         ^^^^^^^^^^^^^^^^^^^ can't leak private type
 
-error: aborting due to 2 previous errors
+error[E0445]: private trait `m::PrivTr` in public interface
+  --> $DIR/private-in-public-assoc-ty.rs:34:9
+   |
+LL |     trait PrivTr {}
+   |     - `m::PrivTr` declared as private
+...
+LL |         existential type Exist: PrivTr;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
+
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0446`.
+Some errors occurred: E0445, E0446.
+For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/privacy/private-in-public-existential.rs b/src/test/ui/privacy/private-in-public-existential.rs
index 95658f45df6f5..61c6130e47019 100644
--- a/src/test/ui/privacy/private-in-public-existential.rs
+++ b/src/test/ui/privacy/private-in-public-existential.rs
@@ -12,4 +12,14 @@ fn check() -> Pub {
     Priv
 }
 
+pub trait Trait {
+    type Pub: Default;
+    fn method() -> Self::Pub;
+}
+
+impl Trait for u8 {
+    existential type Pub: Default;
+    fn method() -> Self::Pub { Priv }
+}
+
 fn main() {}
diff --git a/src/test/ui/traits/auxiliary/trait_alias.rs b/src/test/ui/traits/auxiliary/trait_alias.rs
new file mode 100644
index 0000000000000..9e56b87e08813
--- /dev/null
+++ b/src/test/ui/traits/auxiliary/trait_alias.rs
@@ -0,0 +1,3 @@
+#![feature(trait_alias)]
+
+pub trait SendSync = Send + Sync;
diff --git a/src/test/ui/traits/trait-alias-cross-crate.rs b/src/test/ui/traits/trait-alias-cross-crate.rs
new file mode 100644
index 0000000000000..259fc4fa5d1ce
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-cross-crate.rs
@@ -0,0 +1,17 @@
+// aux-build:trait_alias.rs
+
+#![feature(trait_alias)]
+
+extern crate trait_alias;
+
+use std::rc::Rc;
+use trait_alias::SendSync;
+
+fn use_alias<T: SendSync>() {}
+
+fn main() {
+    use_alias::<u32>();
+    use_alias::<Rc<u32>>();
+    //~^ ERROR `std::rc::Rc<u32>` cannot be sent between threads safely [E0277]
+    //~^^ ERROR `std::rc::Rc<u32>` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/traits/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias-cross-crate.stderr
new file mode 100644
index 0000000000000..972d213ac8f8f
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-cross-crate.stderr
@@ -0,0 +1,29 @@
+error[E0277]: `std::rc::Rc<u32>` cannot be sent between threads safely
+  --> $DIR/trait-alias-cross-crate.rs:14:5
+   |
+LL |     use_alias::<Rc<u32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be sent between threads safely
+   |
+   = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+  --> $DIR/trait-alias-cross-crate.rs:10:1
+   |
+LL | fn use_alias<T: SendSync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Rc<u32>` cannot be shared between threads safely
+  --> $DIR/trait-alias-cross-crate.rs:14:5
+   |
+LL |     use_alias::<Rc<u32>>();
+   |     ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be shared between threads safely
+   |
+   = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+  --> $DIR/trait-alias-cross-crate.rs:10:1
+   |
+LL | fn use_alias<T: SendSync>() {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 8c1baa55bcdca..4ca285b9b1db1 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -95,6 +95,7 @@ static TARGETS: &'static [&'static str] = &[
     "wasm32-unknown-unknown",
     "x86_64-apple-darwin",
     "x86_64-apple-ios",
+    "x86_64-fortanix-unknown-sgx",
     "x86_64-fuchsia",
     "x86_64-linux-android",
     "x86_64-pc-windows-gnu",