about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <github35764891676564198441@oli-obk.de>2018-07-03 19:38:14 +0200
committerOliver Schneider <github35764891676564198441@oli-obk.de>2018-07-18 10:53:08 +0200
commit53d2ebb0adbe677a811ae130523ebceb285a8029 (patch)
treeaa5bf290ab3240ee1028359cef335f22dc1a2cdb
parent1c84d8187395b641616649a0f16f15a78ea8bbce (diff)
downloadrust-53d2ebb0adbe677a811ae130523ebceb285a8029.tar.gz
rust-53d2ebb0adbe677a811ae130523ebceb285a8029.zip
Implement existential types
-rw-r--r--src/librustc/hir/def.rs7
-rw-r--r--src/librustc/hir/intravisit.rs4
-rw-r--r--src/librustc/hir/lowering.rs15
-rw-r--r--src/librustc/hir/map/def_collector.rs5
-rw-r--r--src/librustc/hir/map/definitions.rs4
-rw-r--r--src/librustc/hir/map/mod.rs6
-rw-r--r--src/librustc/hir/mod.rs6
-rw-r--r--src/librustc/hir/print.rs12
-rw-r--r--src/librustc/ich/impls_hir.rs3
-rw-r--r--src/librustc/ich/impls_ty.rs1
-rw-r--r--src/librustc/infer/anon_types/mod.rs50
-rw-r--r--src/librustc/infer/error_reporting/mod.rs4
-rw-r--r--src/librustc/middle/dead.rs1
-rw-r--r--src/librustc/middle/reachable.rs2
-rw-r--r--src/librustc/middle/resolve_lifetime.rs71
-rw-r--r--src/librustc/ty/item_path.rs1
-rw-r--r--src/librustc/ty/mod.rs19
-rw-r--r--src/librustc/ty/sty.rs6
-rw-r--r--src/librustc/util/ppaux.rs15
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs1
-rw-r--r--src/librustc_lint/builtin.rs1
-rw-r--r--src/librustc_metadata/decoder.rs1
-rw-r--r--src/librustc_metadata/encoder.rs5
-rw-r--r--src/librustc_metadata/schema.rs2
-rw-r--r--src/librustc_privacy/lib.rs7
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs5
-rw-r--r--src/librustc_resolve/lib.rs16
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs40
-rw-r--r--src/librustc_save_analysis/lib.rs1
-rw-r--r--src/librustc_save_analysis/sig.rs12
-rw-r--r--src/librustc_typeck/astconv.rs25
-rw-r--r--src/librustc_typeck/check/method/probe.rs1
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/check/wfcheck.rs97
-rw-r--r--src/librustc_typeck/check/writeback.rs59
-rw-r--r--src/librustc_typeck/collect.rs144
-rw-r--r--src/librustc_typeck/namespace.rs2
-rw-r--r--src/librustdoc/clean/mod.rs32
-rw-r--r--src/librustdoc/doctree.rs13
-rw-r--r--src/librustdoc/html/item_type.rs4
-rw-r--r--src/librustdoc/html/render.rs5
-rw-r--r--src/librustdoc/passes/mod.rs1
-rw-r--r--src/librustdoc/visit_ast.rs16
-rw-r--r--src/libsyntax/ast.rs6
-rw-r--r--src/libsyntax/feature_gate.rs21
-rw-r--r--src/libsyntax/fold.rs7
-rw-r--r--src/libsyntax/parse/parser.rs73
-rw-r--r--src/libsyntax/print/pprust.rs24
-rw-r--r--src/libsyntax/visit.rs7
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/test/parse-fail/issue-20711-2.rs3
-rw-r--r--src/test/parse-fail/issue-20711.rs3
-rw-r--r--src/test/parse-fail/removed-syntax-static-fn.rs3
-rw-r--r--src/test/run-pass/existential_type.rs113
-rw-r--r--src/test/ui/as-ref.rs (renamed from src/test/ui/suggestions/as-ref.rs)0
-rw-r--r--src/test/ui/as-ref.stderr (renamed from src/test/ui/suggestions/as-ref.stderr)0
-rw-r--r--src/test/ui/auxiliary/m1.rs (renamed from src/test/ui/suggestions/auxiliary/m1.rs)0
-rw-r--r--src/test/ui/auxiliary/m2.rs (renamed from src/test/ui/suggestions/auxiliary/m2.rs)0
-rw-r--r--src/test/ui/auxiliary/macro-in-other-crate.rs (renamed from src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs)0
-rw-r--r--src/test/ui/auxiliary/removing-extern-crate.rs (renamed from src/test/ui/suggestions/auxiliary/removing-extern-crate.rs)0
-rw-r--r--src/test/ui/closure-immutable-outer-variable.fixed (renamed from src/test/ui/suggestions/closure-immutable-outer-variable.fixed)0
-rw-r--r--src/test/ui/closure-immutable-outer-variable.nll.stderr (renamed from src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr)0
-rw-r--r--src/test/ui/closure-immutable-outer-variable.rs (renamed from src/test/ui/suggestions/closure-immutable-outer-variable.rs)0
-rw-r--r--src/test/ui/closure-immutable-outer-variable.rs.fixed (renamed from src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed)0
-rw-r--r--src/test/ui/closure-immutable-outer-variable.stderr (renamed from src/test/ui/suggestions/closure-immutable-outer-variable.stderr)0
-rw-r--r--src/test/ui/confuse-field-and-method/issue-18343.rs (renamed from src/test/ui/suggestions/confuse-field-and-method/issue-18343.rs)0
-rw-r--r--src/test/ui/confuse-field-and-method/issue-18343.stderr (renamed from src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr)0
-rw-r--r--src/test/ui/confuse-field-and-method/issue-2392.rs (renamed from src/test/ui/suggestions/confuse-field-and-method/issue-2392.rs)0
-rw-r--r--src/test/ui/confuse-field-and-method/issue-2392.stderr (renamed from src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr)0
-rw-r--r--src/test/ui/confuse-field-and-method/issue-32128.rs (renamed from src/test/ui/suggestions/confuse-field-and-method/issue-32128.rs)0
-rw-r--r--src/test/ui/confuse-field-and-method/issue-32128.stderr (renamed from src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr)0
-rw-r--r--src/test/ui/confuse-field-and-method/issue-33784.rs (renamed from src/test/ui/suggestions/confuse-field-and-method/issue-33784.rs)0
-rw-r--r--src/test/ui/confuse-field-and-method/issue-33784.stderr (renamed from src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr)0
-rw-r--r--src/test/ui/confuse-field-and-method/private-field.rs (renamed from src/test/ui/suggestions/confuse-field-and-method/private-field.rs)0
-rw-r--r--src/test/ui/confuse-field-and-method/private-field.stderr (renamed from src/test/ui/suggestions/confuse-field-and-method/private-field.stderr)0
-rw-r--r--src/test/ui/const-type-mismatch.rs (renamed from src/test/ui/suggestions/const-type-mismatch.rs)0
-rw-r--r--src/test/ui/const-type-mismatch.stderr (renamed from src/test/ui/suggestions/const-type-mismatch.stderr)0
-rw-r--r--src/test/ui/conversion-methods.rs (renamed from src/test/ui/suggestions/conversion-methods.rs)0
-rw-r--r--src/test/ui/conversion-methods.stderr (renamed from src/test/ui/suggestions/conversion-methods.stderr)0
-rw-r--r--src/test/ui/dont-suggest-private-trait-method.rs (renamed from src/test/ui/suggestions/dont-suggest-private-trait-method.rs)0
-rw-r--r--src/test/ui/dont-suggest-private-trait-method.stderr (renamed from src/test/ui/suggestions/dont-suggest-private-trait-method.stderr)0
-rw-r--r--src/test/ui/dotdotdot-expr.rs (renamed from src/test/ui/suggestions/dotdotdot-expr.rs)0
-rw-r--r--src/test/ui/dotdotdot-expr.stderr (renamed from src/test/ui/suggestions/dotdotdot-expr.stderr)0
-rw-r--r--src/test/ui/existential_type.nll.stderr111
-rw-r--r--src/test/ui/existential_type.rs95
-rw-r--r--src/test/ui/existential_type.stderr120
-rw-r--r--src/test/ui/existential_type2.rs30
-rw-r--r--src/test/ui/existential_type2.stderr23
-rw-r--r--src/test/ui/existential_type3.rs21
-rw-r--r--src/test/ui/existential_type3.stderr12
-rw-r--r--src/test/ui/existential_type4.rs (renamed from src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed)17
-rw-r--r--src/test/ui/existential_type4.stderr16
-rw-r--r--src/test/ui/extern-crate-rename.rs (renamed from src/test/ui/suggestions/extern-crate-rename.rs)0
-rw-r--r--src/test/ui/extern-crate-rename.stderr (renamed from src/test/ui/suggestions/extern-crate-rename.stderr)0
-rw-r--r--src/test/ui/feature-gate-existential-type.rs25
-rw-r--r--src/test/ui/feature-gate-existential-type.stderr19
-rw-r--r--src/test/ui/fn-closure-mutable-capture.nll.stderr (renamed from src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr)0
-rw-r--r--src/test/ui/fn-closure-mutable-capture.rs (renamed from src/test/ui/suggestions/fn-closure-mutable-capture.rs)0
-rw-r--r--src/test/ui/fn-closure-mutable-capture.stderr (renamed from src/test/ui/suggestions/fn-closure-mutable-capture.stderr)0
-rw-r--r--src/test/ui/for-c-in-str.rs (renamed from src/test/ui/suggestions/for-c-in-str.rs)0
-rw-r--r--src/test/ui/for-c-in-str.stderr (renamed from src/test/ui/suggestions/for-c-in-str.stderr)0
-rw-r--r--src/test/ui/issue-32354-suggest-import-rename.fixed (renamed from src/test/ui/suggestions/issue-32354-suggest-import-rename.fixed)0
-rw-r--r--src/test/ui/issue-32354-suggest-import-rename.rs (renamed from src/test/ui/suggestions/issue-32354-suggest-import-rename.rs)0
-rw-r--r--src/test/ui/issue-32354-suggest-import-rename.stderr (renamed from src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr)0
-rw-r--r--src/test/ui/issue-43420-no-over-suggest.rs (renamed from src/test/ui/suggestions/issue-43420-no-over-suggest.rs)0
-rw-r--r--src/test/ui/issue-43420-no-over-suggest.stderr (renamed from src/test/ui/suggestions/issue-43420-no-over-suggest.stderr)0
-rw-r--r--src/test/ui/issue-45562.fixed (renamed from src/test/ui/suggestions/issue-45562.fixed)0
-rw-r--r--src/test/ui/issue-45562.rs (renamed from src/test/ui/suggestions/issue-45562.rs)0
-rw-r--r--src/test/ui/issue-45562.stderr (renamed from src/test/ui/suggestions/issue-45562.stderr)0
-rw-r--r--src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed (renamed from src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed)0
-rw-r--r--src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs (renamed from src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs)0
-rw-r--r--src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr (renamed from src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr)0
-rw-r--r--src/test/ui/issue-46302.rs (renamed from src/test/ui/suggestions/issue-46302.rs)0
-rw-r--r--src/test/ui/issue-46302.stderr (renamed from src/test/ui/suggestions/issue-46302.stderr)0
-rw-r--r--src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.fixed (renamed from src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed)0
-rw-r--r--src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.rs (renamed from src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs)0
-rw-r--r--src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.stderr (renamed from src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr)0
-rw-r--r--src/test/ui/issue-48364.rs (renamed from src/test/ui/suggestions/issue-48364.rs)0
-rw-r--r--src/test/ui/issue-48364.stderr (renamed from src/test/ui/suggestions/issue-48364.stderr)0
-rw-r--r--src/test/ui/issue-51244.nll.stderr (renamed from src/test/ui/suggestions/issue-51244.nll.stderr)0
-rw-r--r--src/test/ui/issue-51244.rs (renamed from src/test/ui/suggestions/issue-51244.rs)0
-rw-r--r--src/test/ui/issue-51244.stderr (renamed from src/test/ui/suggestions/issue-51244.stderr)0
-rw-r--r--src/test/ui/issue-51515.rs (renamed from src/test/ui/suggestions/issue-51515.rs)0
-rw-r--r--src/test/ui/issue-51515.stderr (renamed from src/test/ui/suggestions/issue-51515.stderr)0
-rw-r--r--src/test/ui/issue-52049.nll.stderr (renamed from src/test/ui/suggestions/issue-52049.nll.stderr)0
-rw-r--r--src/test/ui/issue-52049.rs (renamed from src/test/ui/suggestions/issue-52049.rs)0
-rw-r--r--src/test/ui/issue-52049.stderr (renamed from src/test/ui/suggestions/issue-52049.stderr)0
-rw-r--r--src/test/ui/method-on-ambiguous-numeric-type.rs (renamed from src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs)0
-rw-r--r--src/test/ui/method-on-ambiguous-numeric-type.stderr (renamed from src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr)0
-rw-r--r--src/test/ui/missing-comma-in-match.fixed (renamed from src/test/ui/suggestions/missing-comma-in-match.fixed)0
-rw-r--r--src/test/ui/missing-comma-in-match.rs (renamed from src/test/ui/suggestions/missing-comma-in-match.rs)0
-rw-r--r--src/test/ui/missing-comma-in-match.stderr (renamed from src/test/ui/suggestions/missing-comma-in-match.stderr)0
-rw-r--r--src/test/ui/numeric-cast-2.rs (renamed from src/test/ui/suggestions/numeric-cast-2.rs)0
-rw-r--r--src/test/ui/numeric-cast-2.stderr (renamed from src/test/ui/suggestions/numeric-cast-2.stderr)0
-rw-r--r--src/test/ui/numeric-cast.rs (renamed from src/test/ui/suggestions/numeric-cast.rs)0
-rw-r--r--src/test/ui/numeric-cast.stderr (renamed from src/test/ui/suggestions/numeric-cast.stderr)0
-rw-r--r--src/test/ui/placement-syntax.rs (renamed from src/test/ui/suggestions/placement-syntax.rs)0
-rw-r--r--src/test/ui/placement-syntax.stderr (renamed from src/test/ui/suggestions/placement-syntax.stderr)0
-rw-r--r--src/test/ui/pub-ident-fn-2.rs (renamed from src/test/ui/suggestions/pub-ident-fn-2.rs)0
-rw-r--r--src/test/ui/pub-ident-fn-2.stderr (renamed from src/test/ui/suggestions/pub-ident-fn-2.stderr)0
-rw-r--r--src/test/ui/pub-ident-fn-or-struct-2.rs (renamed from src/test/ui/suggestions/pub-ident-fn-or-struct-2.rs)0
-rw-r--r--src/test/ui/pub-ident-fn-or-struct-2.stderr (renamed from src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr)0
-rw-r--r--src/test/ui/pub-ident-fn-or-struct.rs (renamed from src/test/ui/suggestions/pub-ident-fn-or-struct.rs)0
-rw-r--r--src/test/ui/pub-ident-fn-or-struct.stderr (renamed from src/test/ui/suggestions/pub-ident-fn-or-struct.stderr)0
-rw-r--r--src/test/ui/pub-ident-fn.fixed (renamed from src/test/ui/suggestions/pub-ident-fn.fixed)0
-rw-r--r--src/test/ui/pub-ident-fn.rs (renamed from src/test/ui/suggestions/pub-ident-fn.rs)0
-rw-r--r--src/test/ui/pub-ident-fn.stderr (renamed from src/test/ui/suggestions/pub-ident-fn.stderr)0
-rw-r--r--src/test/ui/pub-ident-struct.rs (renamed from src/test/ui/suggestions/pub-ident-struct.rs)0
-rw-r--r--src/test/ui/pub-ident-struct.stderr (renamed from src/test/ui/suggestions/pub-ident-struct.stderr)0
-rw-r--r--src/test/ui/removing-extern-crate.fixed (renamed from src/test/ui/suggestions/removing-extern-crate.fixed)0
-rw-r--r--src/test/ui/removing-extern-crate.rs (renamed from src/test/ui/suggestions/removing-extern-crate.rs)0
-rw-r--r--src/test/ui/removing-extern-crate.stderr (renamed from src/test/ui/suggestions/removing-extern-crate.stderr)0
-rw-r--r--src/test/ui/repr.rs (renamed from src/test/ui/suggestions/repr.rs)0
-rw-r--r--src/test/ui/repr.stderr (renamed from src/test/ui/suggestions/repr.stderr)0
-rw-r--r--src/test/ui/return-type.rs (renamed from src/test/ui/suggestions/return-type.rs)0
-rw-r--r--src/test/ui/return-type.stderr (renamed from src/test/ui/suggestions/return-type.stderr)0
-rw-r--r--src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr24
-rw-r--r--src/test/ui/str-array-assignment.rs (renamed from src/test/ui/suggestions/str-array-assignment.rs)0
-rw-r--r--src/test/ui/str-array-assignment.stderr (renamed from src/test/ui/suggestions/str-array-assignment.stderr)0
-rw-r--r--src/test/ui/str-as-char.fixed (renamed from src/test/ui/suggestions/str-as-char.fixed)0
-rw-r--r--src/test/ui/str-as-char.rs (renamed from src/test/ui/suggestions/str-as-char.rs)0
-rw-r--r--src/test/ui/str-as-char.stderr (renamed from src/test/ui/suggestions/str-as-char.stderr)0
-rw-r--r--src/test/ui/suggest-labels.rs (renamed from src/test/ui/suggestions/suggest-labels.rs)0
-rw-r--r--src/test/ui/suggest-labels.stderr (renamed from src/test/ui/suggestions/suggest-labels.stderr)0
-rw-r--r--src/test/ui/suggest-methods.rs (renamed from src/test/ui/suggestions/suggest-methods.rs)0
-rw-r--r--src/test/ui/suggest-methods.stderr (renamed from src/test/ui/suggestions/suggest-methods.stderr)0
-rw-r--r--src/test/ui/suggest-ref-mut.rs (renamed from src/test/ui/suggestions/suggest-ref-mut.rs)0
-rw-r--r--src/test/ui/suggest-ref-mut.stderr (renamed from src/test/ui/suggestions/suggest-ref-mut.stderr)0
-rw-r--r--src/test/ui/token/issue-41155.stderr4
-rw-r--r--src/test/ui/try-on-option.rs (renamed from src/test/ui/suggestions/try-on-option.rs)0
-rw-r--r--src/test/ui/try-on-option.stderr (renamed from src/test/ui/suggestions/try-on-option.stderr)0
-rw-r--r--src/test/ui/try-operator-on-main.rs (renamed from src/test/ui/suggestions/try-operator-on-main.rs)0
-rw-r--r--src/test/ui/try-operator-on-main.stderr (renamed from src/test/ui/suggestions/try-operator-on-main.stderr)0
-rw-r--r--src/test/ui/tuple-float-index.fixed (renamed from src/test/ui/suggestions/tuple-float-index.fixed)0
-rw-r--r--src/test/ui/tuple-float-index.rs (renamed from src/test/ui/suggestions/tuple-float-index.rs)0
-rw-r--r--src/test/ui/tuple-float-index.stderr (renamed from src/test/ui/suggestions/tuple-float-index.stderr)0
-rw-r--r--src/test/ui/type-ascription-instead-of-initializer.rs (renamed from src/test/ui/suggestions/type-ascription-instead-of-initializer.rs)0
-rw-r--r--src/test/ui/type-ascription-instead-of-initializer.stderr (renamed from src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr)0
-rw-r--r--src/test/ui/type-ascription-instead-of-statement-end.rs (renamed from src/test/ui/suggestions/type-ascription-instead-of-statement-end.rs)0
-rw-r--r--src/test/ui/type-ascription-instead-of-statement-end.stderr (renamed from src/test/ui/suggestions/type-ascription-instead-of-statement-end.stderr)0
-rw-r--r--src/test/ui/type-ascription-with-fn-call.rs (renamed from src/test/ui/suggestions/type-ascription-with-fn-call.rs)0
-rw-r--r--src/test/ui/type-ascription-with-fn-call.stderr (renamed from src/test/ui/suggestions/type-ascription-with-fn-call.stderr)0
182 files changed, 1385 insertions, 117 deletions
diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs
index 7a26a239aef..1c355e35fd6 100644
--- a/src/librustc/hir/def.rs
+++ b/src/librustc/hir/def.rs
@@ -37,11 +37,15 @@ pub enum Def {
     Enum(DefId),
     Variant(DefId),
     Trait(DefId),
+    /// `existential type Foo: Bar;`
     Existential(DefId),
+    /// `type Foo = Bar;`
     TyAlias(DefId),
     TyForeign(DefId),
     TraitAlias(DefId),
     AssociatedTy(DefId),
+    /// `existential type Foo: Bar;`
+    AssociatedExistential(DefId),
     PrimTy(hir::PrimTy),
     TyParam(DefId),
     SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
@@ -245,7 +249,7 @@ impl Def {
             Def::AssociatedTy(id) | Def::TyParam(id) | Def::Struct(id) | Def::StructCtor(id, ..) |
             Def::Union(id) | Def::Trait(id) | Def::Method(id) | Def::Const(id) |
             Def::AssociatedConst(id) | Def::Macro(id, ..) |
-            Def::Existential(id) |
+            Def::Existential(id) | Def::AssociatedExistential(id) |
             Def::GlobalAsm(id) | Def::TyForeign(id) => {
                 id
             }
@@ -276,6 +280,7 @@ impl Def {
             Def::TyAlias(..) => "type alias",
             Def::TraitAlias(..) => "trait alias",
             Def::AssociatedTy(..) => "associated type",
+            Def::AssociatedExistential(..) => "associated existential type",
             Def::Struct(..) => "struct",
             Def::StructCtor(.., CtorKind::Fn) => "tuple struct",
             Def::StructCtor(.., CtorKind::Const) => "unit struct",
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 2fefd2b3318..4274cd3a0a6 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -907,6 +907,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
             visitor.visit_id(impl_item.id);
             visitor.visit_ty(ty);
         }
+        ImplItemKind::Existential(ref bounds) => {
+            visitor.visit_id(impl_item.id);
+            walk_list!(visitor, visit_param_bound, bounds);
+        }
     }
 }
 
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 722934ac39a..80e9b4caef5 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -323,6 +323,7 @@ impl<'a> LoweringContext<'a> {
                     | ItemKind::Union(_, ref generics)
                     | ItemKind::Enum(_, ref generics)
                     | ItemKind::Ty(_, ref generics)
+                    | ItemKind::Existential(_, ref generics)
                     | ItemKind::Trait(_, _, ref generics, ..) => {
                         let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
                         let count = generics
@@ -2632,6 +2633,11 @@ impl<'a> LoweringContext<'a> {
                 self.lower_ty(t, ImplTraitContext::Disallowed),
                 self.lower_generics(generics, ImplTraitContext::Disallowed),
             ),
+            ItemKind::Existential(ref b, ref generics) => hir::ItemKind::Existential(hir::ExistTy {
+                generics: self.lower_generics(generics, ImplTraitContext::Disallowed),
+                bounds: self.lower_param_bounds(b, ImplTraitContext::Disallowed),
+                impl_trait_fn: None,
+            }),
             ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum(
                 hir::EnumDef {
                     variants: enum_definition
@@ -3037,6 +3043,12 @@ impl<'a> LoweringContext<'a> {
                 self.lower_generics(&i.generics, ImplTraitContext::Disallowed),
                 hir::ImplItemKind::Type(self.lower_ty(ty, ImplTraitContext::Disallowed)),
             ),
+            ImplItemKind::Existential(ref bounds) => (
+                self.lower_generics(&i.generics, ImplTraitContext::Disallowed),
+                hir::ImplItemKind::Existential(
+                    self.lower_param_bounds(bounds, ImplTraitContext::Disallowed),
+                ),
+            ),
             ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"),
         };
 
@@ -3065,6 +3077,7 @@ impl<'a> LoweringContext<'a> {
             kind: match i.node {
                 ImplItemKind::Const(..) => hir::AssociatedItemKind::Const,
                 ImplItemKind::Type(..) => hir::AssociatedItemKind::Type,
+                ImplItemKind::Existential(..) => hir::AssociatedItemKind::Existential,
                 ImplItemKind::Method(ref sig, _) => hir::AssociatedItemKind::Method {
                     has_self: sig.decl.has_self(),
                 },
@@ -4331,7 +4344,7 @@ impl<'a> LoweringContext<'a> {
         respan(v.span, node)
     }
 
-    fn lower_defaultness(&mut self, d: Defaultness, has_value: bool) -> hir::Defaultness {
+    fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness {
         match d {
             Defaultness::Default => hir::Defaultness::Default {
                 has_value: has_value,
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index c1de6c15d41..cab620aeec5 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -116,7 +116,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             ItemKind::Impl(..) => DefPathData::Impl,
             ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()),
             ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
-            ItemKind::TraitAlias(..) |
+            ItemKind::TraitAlias(..) | ItemKind::Existential(..) |
             ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
                 DefPathData::TypeNs(i.ident.as_interned_str()),
             ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
@@ -250,6 +250,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
             ImplItemKind::Method(..) | ImplItemKind::Const(..) =>
                 DefPathData::ValueNs(ii.ident.as_interned_str()),
             ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.as_interned_str()),
+            ImplItemKind::Existential(..) => {
+                DefPathData::AssocExistentialInImpl(ii.ident.as_interned_str())
+            },
             ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id),
         };
 
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 9b1bb3310f2..c4b28fe2c43 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -330,6 +330,8 @@ pub enum DefPathData {
     AssocTypeInTrait(InternedString),
     /// An associated type **value** (i.e., in an impl)
     AssocTypeInImpl(InternedString),
+    /// An existential associated type **value** (i.e., in an impl)
+    AssocExistentialInImpl(InternedString),
     /// Something in the type NS
     TypeNs(InternedString),
     /// Something in the value NS
@@ -605,6 +607,7 @@ impl DefPathData {
             Trait(name) |
             AssocTypeInTrait(name) |
             AssocTypeInImpl(name) |
+            AssocExistentialInImpl(name) |
             ValueNs(name) |
             Module(name) |
             MacroDef(name) |
@@ -631,6 +634,7 @@ impl DefPathData {
             Trait(name) |
             AssocTypeInTrait(name) |
             AssocTypeInImpl(name) |
+            AssocExistentialInImpl(name) |
             ValueNs(name) |
             Module(name) |
             MacroDef(name) |
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index d413a544c4e..49231e58cf0 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -470,6 +470,7 @@ impl<'hir> Map<'hir> {
                     ImplItemKind::Const(..) => Some(Def::AssociatedConst(def_id)),
                     ImplItemKind::Method(..) => Some(Def::Method(def_id)),
                     ImplItemKind::Type(..) => Some(Def::AssociatedTy(def_id)),
+                    ImplItemKind::Existential(..) => Some(Def::AssociatedExistential(def_id)),
                 }
             }
             NodeVariant(variant) => {
@@ -1323,7 +1324,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ItemKind::ForeignMod(..) => "foreign mod",
                 ItemKind::GlobalAsm(..) => "global asm",
                 ItemKind::Ty(..) => "ty",
-                ItemKind::Existential(..) => "existential",
+                ItemKind::Existential(..) => "existential type",
                 ItemKind::Enum(..) => "enum",
                 ItemKind::Struct(..) => "struct",
                 ItemKind::Union(..) => "union",
@@ -1347,6 +1348,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ImplItemKind::Type(_) => {
                     format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
                 }
+                ImplItemKind::Existential(_) => {
+                    format!("assoc existential type {} in {}{}", ii.ident, path_str(), id_str)
+                }
             }
         }
         Some(NodeTraitItem(ti)) => {
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index c1a885d80bf..b16c97172f1 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1620,6 +1620,8 @@ pub enum ImplItemKind {
     Method(MethodSig, BodyId),
     /// An associated type
     Type(P<Ty>),
+    /// An associated existential type
+    Existential(GenericBounds),
 }
 
 // Bind a type to an associated type: `A=Foo`.
@@ -2080,7 +2082,7 @@ pub enum ItemKind {
     GlobalAsm(P<GlobalAsm>),
     /// A type alias, e.g. `type Foo = Bar<u8>`
     Ty(P<Ty>, Generics),
-    /// A type alias, e.g. `type Foo = Bar<u8>`
+    /// An existential type definition, e.g. `existential type Foo: Bar;`
     Existential(ExistTy),
     /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
     Enum(EnumDef, Generics),
@@ -2138,6 +2140,7 @@ impl ItemKind {
         Some(match *self {
             ItemKind::Fn(_, _, ref generics, _) |
             ItemKind::Ty(_, ref generics) |
+            ItemKind::Existential(ExistTy { ref generics, impl_trait_fn: None, .. }) |
             ItemKind::Enum(_, ref generics) |
             ItemKind::Struct(_, ref generics) |
             ItemKind::Union(_, ref generics) |
@@ -2184,6 +2187,7 @@ pub enum AssociatedItemKind {
     Const,
     Method { has_self: bool },
     Type,
+    Existential,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index e637a18d1cd..4499a378be2 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -627,9 +627,7 @@ impl<'a> State<'a> {
                 self.end()?
             }
             hir::ItemKind::Ty(ref ty, ref generics) => {
-                self.ibox(indent_unit)?;
-                self.ibox(0)?;
-                self.word_nbsp(&visibility_qualified(&item.vis, "type"))?;
+                self.head(&visibility_qualified(&item.vis, "type"))?;
                 self.print_name(item.name)?;
                 self.print_generic_params(&generics.params)?;
                 self.end()?; // end the inner ibox
@@ -642,9 +640,7 @@ impl<'a> State<'a> {
                 self.end()?; // end the outer ibox
             }
             hir::ItemKind::Existential(ref exist) => {
-                self.ibox(indent_unit)?;
-                self.ibox(0)?;
-                self.word_nbsp(&visibility_qualified(&item.vis, "existential type"))?;
+                self.head(&visibility_qualified(&item.vis, "existential type"))?;
                 self.print_name(item.name)?;
                 self.print_generic_params(&exist.generics.params)?;
                 self.end()?; // end the inner ibox
@@ -994,6 +990,10 @@ impl<'a> State<'a> {
             hir::ImplItemKind::Type(ref ty) => {
                 self.print_associated_type(ii.ident, None, Some(ty))?;
             }
+            hir::ImplItemKind::Existential(ref bounds) => {
+                self.word_space("existential")?;
+                self.print_associated_type(ii.ident, Some(bounds), None)?;
+            }
         }
         self.ann.post(self, NodeSubItem(ii.id))
     }
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index d1fb05ceafb..2ce7749172b 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -701,6 +701,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::ImplItem {
 impl_stable_hash_for!(enum hir::ImplItemKind {
     Const(t, body),
     Method(sig, body),
+    Existential(bounds),
     Type(t)
 });
 
@@ -890,6 +891,7 @@ impl<'a> HashStable<StableHashingContext<'a>> for hir::AssociatedItemKind {
         mem::discriminant(self).hash_stable(hcx, hasher);
         match *self {
             hir::AssociatedItemKind::Const |
+            hir::AssociatedItemKind::Existential |
             hir::AssociatedItemKind::Type => {
                 // No fields to hash.
             }
@@ -997,6 +999,7 @@ impl_stable_hash_for!(enum hir::def::Def {
     TyAlias(def_id),
     TraitAlias(def_id),
     AssociatedTy(def_id),
+    AssociatedExistential(def_id),
     PrimTy(prim_ty),
     TyParam(def_id),
     SelfTy(trait_def_id, impl_def_id),
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index a3600c04800..cb685f83aba 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -1055,6 +1055,7 @@ impl_stable_hash_for!(struct ty::AssociatedItem {
 impl_stable_hash_for!(enum ty::AssociatedKind {
     Const,
     Method,
+    Existential,
     Type
 });
 
diff --git a/src/librustc/infer/anon_types/mod.rs b/src/librustc/infer/anon_types/mod.rs
index 2924016670b..5e731871e28 100644
--- a/src/librustc/infer/anon_types/mod.rs
+++ b/src/librustc/infer/anon_types/mod.rs
@@ -691,10 +691,22 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
                     // ```
                     if let Some(anon_node_id) = tcx.hir.as_local_node_id(def_id) {
                         let anon_parent_def_id = match tcx.hir.expect_item(anon_node_id).node {
+                            // impl trait
                             hir::ItemKind::Existential(hir::ExistTy {
                                 impl_trait_fn: Some(parent),
                                 ..
                             }) => parent,
+                            // named existential types
+                            hir::ItemKind::Existential(hir::ExistTy {
+                                impl_trait_fn: None,
+                                ..
+                            }) if may_define_existential_type(
+                                tcx,
+                                self.parent_def_id,
+                                anon_node_id,
+                            ) => {
+                                return self.fold_anon_ty(ty, def_id, substs);
+                            },
                             _ => {
                                 let anon_parent_node_id = tcx.hir.get_parent(anon_node_id);
                                 tcx.hir.local_def_id(anon_parent_node_id)
@@ -742,6 +754,10 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
         let ty_var = infcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
 
         let predicates_of = tcx.predicates_of(def_id);
+        debug!(
+            "instantiate_anon_types: predicates: {:#?}",
+            predicates_of,
+        );
         let bounds = predicates_of.instantiate(tcx, substs);
         debug!("instantiate_anon_types: bounds={:?}", bounds);
 
@@ -751,6 +767,18 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
             required_region_bounds
         );
 
+        // make sure that we are in fact defining the *entire* type
+        // e.g. `existential type Foo<T: Bound>: Bar;` needs to be
+        // defined by a function like `fn foo<T: Bound>() -> Foo<T>`.
+        debug!(
+            "instantiate_anon_types: param_env: {:#?}",
+            self.param_env,
+        );
+        debug!(
+            "instantiate_anon_types: generics: {:#?}",
+            tcx.generics_of(def_id),
+        );
+
         self.anon_types.insert(
             def_id,
             AnonTypeDecl {
@@ -778,3 +806,25 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
         ty_var
     }
 }
+
+/// Whether `anon_node_id` is a sibling or a child of a sibling of `def_id`
+pub fn may_define_existential_type(
+    tcx: TyCtxt,
+    def_id: DefId,
+    anon_node_id: ast::NodeId,
+) -> bool {
+    let mut node_id = tcx
+        .hir
+        .as_local_node_id(def_id)
+        .unwrap();
+    // named existential types can be defined by any siblings or
+    // children of siblings
+    let mod_id = tcx.hir.get_parent(anon_node_id);
+    // so we walk up the node tree until we hit the root or the parent
+    // of the anon type
+    while node_id != mod_id && node_id != ast::CRATE_NODE_ID {
+        node_id = tcx.hir.get_parent(node_id);
+    }
+    // syntactically we are allowed to define the concrete type
+    node_id == mod_id
+}
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 8da0dc365b0..1ec9c9489e9 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -279,7 +279,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str {
         match item.node {
             hir::ImplItemKind::Method(..) => "method body",
-            hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) => "associated item",
+            hir::ImplItemKind::Const(..) |
+            hir::ImplItemKind::Existential(..) |
+            hir::ImplItemKind::Type(..) => "associated item",
         }
     }
 
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index da59bced760..aa1951efba3 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -622,6 +622,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
                 }
                 self.visit_nested_body(body_id)
             }
+            hir::ImplItemKind::Existential(..) |
             hir::ImplItemKind::Type(..) => {}
         }
     }
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index a504697008e..7f4b0bb126b 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -210,6 +210,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                             }
                         }
                     }
+                    hir::ImplItemKind::Existential(..) |
                     hir::ImplItemKind::Type(_) => false,
                 }
             }
@@ -319,6 +320,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                             self.visit_nested_body(body)
                         }
                     }
+                    hir::ImplItemKind::Existential(..) |
                     hir::ImplItemKind::Type(_) => {}
                 }
             }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 05a6cd9c243..39a57e985e8 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -627,6 +627,30 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
             }
             hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
                 if let Def::Existential(exist_ty_did) = path.def {
+                    let id = self.tcx.hir.as_local_node_id(exist_ty_did).unwrap();
+
+                    // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
+                    // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
+                    // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
+                    //                          ^            ^ this gets resolved in the scope of
+                    //                                         the exist_ty generics
+                    let (generics, bounds) = match self.tcx.hir.expect_item(id).node {
+                        // named existential types don't need these hacks
+                        hir::ItemKind::Existential(hir::ExistTy{ impl_trait_fn: None, .. }) => {
+                            intravisit::walk_ty(self, ty);
+                            return;
+                        },
+                        hir::ItemKind::Existential(hir::ExistTy{
+                            ref generics,
+                            ref bounds,
+                            ..
+                        }) => (
+                            generics,
+                            bounds,
+                        ),
+                        ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
+                    };
+
                     assert!(exist_ty_did.is_local());
                     // Resolve the lifetimes that are applied to the existential type.
                     // These are resolved in the current scope.
@@ -667,23 +691,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                         }
                     }
 
-                    let id = self.tcx.hir.as_local_node_id(exist_ty_did).unwrap();
-
-                    // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
-                    // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
-                    // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
-                    //                          ^            ^ this gets resolved in the scope of
-                    //                                         the exist_ty generics
-                    let (generics, bounds) = match self.tcx.hir.expect_item(id).node {
-                        hir::ItemKind::Existential(
-                            hir::ExistTy { ref generics, ref bounds, .. }
-                        ) => (
-                            generics,
-                            bounds,
-                        ),
-                        ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
-                    };
-
                     // We want to start our early-bound indices at the end of the parent scope,
                     // not including any parent `impl Trait`s.
                     let mut index = self.next_early_index_for_abstract_type();
@@ -847,6 +854,35 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
                     this.visit_ty(ty);
                 });
             }
+            Existential(ref bounds) => {
+                let generics = &impl_item.generics;
+                let mut index = self.next_early_index();
+                let mut next_early_index = index;
+                debug!("visit_ty: index = {}", index);
+                let lifetimes = generics.params.iter().filter_map(|param| match param.kind {
+                    GenericParamKind::Lifetime { .. } => {
+                        Some(Region::early(&self.tcx.hir, &mut index, param))
+                    }
+                    GenericParamKind::Type { .. } => {
+                        next_early_index += 1;
+                        None
+                    }
+                }).collect();
+
+                let scope = Scope::Binder {
+                    lifetimes,
+                    next_early_index,
+                    s: self.scope,
+                    track_lifetime_uses: true,
+                    abstract_type_parent: true,
+                };
+                self.with(scope, |_old_scope, this| {
+                    this.visit_generics(generics);
+                    for bound in bounds {
+                        this.visit_param_bound(bound);
+                    }
+                });
+            }
             Const(_, _) => {
                 // Only methods and types support generics.
                 assert!(impl_item.generics.params.is_empty());
@@ -1213,6 +1249,7 @@ fn compute_object_lifetime_defaults(
             hir::ItemKind::Struct(_, ref generics)
             | hir::ItemKind::Union(_, ref generics)
             | hir::ItemKind::Enum(_, ref generics)
+            | hir::ItemKind::Existential(hir::ExistTy { ref generics, impl_trait_fn: None, .. })
             | hir::ItemKind::Ty(_, ref generics)
             | hir::ItemKind::Trait(_, _, ref generics, ..) => {
                 let result = object_lifetime_defaults_for_item(tcx, generics);
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 95da68bc9ff..a44962c77b5 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -212,6 +212,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             data @ DefPathData::Trait(..) |
             data @ DefPathData::AssocTypeInTrait(..) |
             data @ DefPathData::AssocTypeInImpl(..) |
+            data @ DefPathData::AssocExistentialInImpl(..) |
             data @ DefPathData::ValueNs(..) |
             data @ DefPathData::Module(..) |
             data @ DefPathData::TypeParam(..) |
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 5aa6542a027..2e221424e3c 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -192,6 +192,7 @@ pub struct AssociatedItem {
 pub enum AssociatedKind {
     Const,
     Method,
+    Existential,
     Type
 }
 
@@ -201,6 +202,7 @@ impl AssociatedItem {
             AssociatedKind::Const => Def::AssociatedConst(self.def_id),
             AssociatedKind::Method => Def::Method(self.def_id),
             AssociatedKind::Type => Def::AssociatedTy(self.def_id),
+            AssociatedKind::Existential => Def::AssociatedExistential(self.def_id),
         }
     }
 
@@ -208,7 +210,8 @@ impl AssociatedItem {
     /// for !
     pub fn relevant_for_never<'tcx>(&self) -> bool {
         match self.kind {
-            AssociatedKind::Const => true,
+            AssociatedKind::Existential |
+            AssociatedKind::Const |
             AssociatedKind::Type => true,
             // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited.
             AssociatedKind::Method => !self.method_has_self_argument,
@@ -225,6 +228,7 @@ impl AssociatedItem {
                 format!("{}", tcx.fn_sig(self.def_id).skip_binder())
             }
             ty::AssociatedKind::Type => format!("type {};", self.ident),
+            ty::AssociatedKind::Existential => format!("existential type {};", self.ident),
             ty::AssociatedKind::Const => {
                 format!("const {}: {:?};", self.ident, tcx.type_of(self.def_id))
             }
@@ -2491,6 +2495,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 (ty::AssociatedKind::Method, has_self)
             }
             hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
+            hir::AssociatedItemKind::Existential => bug!("only impls can have existentials"),
         };
 
         AssociatedItem {
@@ -2516,6 +2521,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 (ty::AssociatedKind::Method, has_self)
             }
             hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
+            hir::AssociatedItemKind::Existential => (ty::AssociatedKind::Existential, false),
         };
 
         AssociatedItem {
@@ -2857,8 +2863,15 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // The param_env of an existential type is its parent's param_env
     if let Some(Def::Existential(_)) = tcx.describe_def(def_id) {
-        let parent = tcx.parent_def_id(def_id).expect("impl trait item w/o a parent");
-        return param_env(tcx, parent);
+        if let Some(node_id) = tcx.hir.as_local_node_id(def_id) {
+            if let hir::map::NodeItem(item) = tcx.hir.get(node_id) {
+                if let hir::ItemKind::Existential(ref exist_ty) = item.node {
+                    if let Some(parent) = exist_ty.impl_trait_fn {
+                        return param_env(tcx, parent);
+                    }
+                }
+            }
+        }
     }
     // Compute the bounds on Self and the type parameters.
 
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 934bf9a416a..dd381888243 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -158,8 +158,10 @@ pub enum TypeVariants<'tcx> {
     TyProjection(ProjectionTy<'tcx>),
 
     /// Anonymized (`impl Trait`) type found in a return type.
-    /// The DefId comes from the `impl Trait` ast::Ty node, and the
-    /// substitutions are for the generics of the function in question.
+    /// The DefId comes either from
+    /// * the `impl Trait` ast::Ty node,
+    /// * or the `existential type` declaration
+    /// The substitutions are for the generics of the function in question.
     /// After typeck, the concrete type can be found in the `types` map.
     TyAnon(DefId, &'tcx Substs<'tcx>),
 
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index c17fd79df2a..c67453d2b20 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -271,6 +271,7 @@ impl PrintContext {
                 match key.disambiguated_data.data {
                     DefPathData::AssocTypeInTrait(_) |
                     DefPathData::AssocTypeInImpl(_) |
+                    DefPathData::AssocExistentialInImpl(_) |
                     DefPathData::Trait(_) |
                     DefPathData::TypeNs(_) => {
                         break;
@@ -1081,6 +1082,20 @@ define_print! {
                     }
 
                     ty::tls::with(|tcx| {
+                        let def_key = tcx.def_key(def_id);
+                        if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
+                            write!(f, "{}", name)?;
+                            let mut substs = substs.iter();
+                            if let Some(first) = substs.next() {
+                                write!(f, "::<")?;
+                                write!(f, "{}", first)?;
+                                for subst in substs {
+                                    write!(f, ", {}", subst)?;
+                                }
+                                write!(f, ">")?;
+                            }
+                            return Ok(());
+                        }
                         // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
                         // by looking up the projections associated with the def_id.
                         let predicates_of = tcx.predicates_of(def_id);
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 39e674a6095..7f2da5a326a 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -417,6 +417,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> {
                     ImplItemKind::Method(..) => ("NodeImplItem", LABELS_FN_IN_IMPL),
                     ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
                     ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
+                    ImplItemKind::Existential(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
                 }
             },
             _ => self.tcx.sess.span_fatal(
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 8a674449880..af40f3c64ed 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -461,6 +461,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
             hir::ImplItemKind::Const(..) => "an associated constant",
             hir::ImplItemKind::Method(..) => "a method",
             hir::ImplItemKind::Type(_) => "an associated type",
+            hir::ImplItemKind::Existential(_) => "an associated existential type",
         };
         self.check_missing_docs_attrs(cx,
                                       Some(impl_item.id),
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index b8c64383950..ab566654c38 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -421,6 +421,7 @@ impl<'tcx> EntryKind<'tcx> {
             EntryKind::Type => Def::TyAlias(did),
             EntryKind::Existential => Def::Existential(did),
             EntryKind::AssociatedType(_) => Def::AssociatedTy(did),
+            EntryKind::AssociatedExistential(_) => Def::AssociatedExistential(did),
             EntryKind::Mod(_) => Def::Mod(did),
             EntryKind::Variant(_) => Def::Variant(did),
             EntryKind::Trait(_) => Def::Trait(did),
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index b9cb97ed7d0..7ed991e0de3 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -840,6 +840,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                 }))
             }
             ty::AssociatedKind::Type => EntryKind::AssociatedType(container),
+            ty::AssociatedKind::Existential =>
+                span_bug!(ast_item.span, "existential type in trait"),
         };
 
         Entry {
@@ -863,6 +865,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                         None
                     }
                 }
+                ty::AssociatedKind::Existential => unreachable!(),
             },
             inherent_impls: LazySeq::empty(),
             variances: if trait_item.kind == ty::AssociatedKind::Method {
@@ -933,6 +936,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     has_self: impl_item.method_has_self_argument,
                 }))
             }
+            ty::AssociatedKind::Existential => EntryKind::AssociatedExistential(container),
             ty::AssociatedKind::Type => EntryKind::AssociatedType(container)
         };
 
@@ -948,6 +952,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
                     let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
                     needs_inline || is_const_fn || always_encode_mir
                 },
+                hir::ImplItemKind::Existential(..) |
                 hir::ImplItemKind::Type(..) => false,
             };
 
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 430cbf9b529..d7c54cbc81d 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -321,6 +321,7 @@ pub enum EntryKind<'tcx> {
     Impl(Lazy<ImplData<'tcx>>),
     Method(Lazy<MethodData<'tcx>>),
     AssociatedType(AssociatedContainer),
+    AssociatedExistential(AssociatedContainer),
     AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
 }
 
@@ -382,6 +383,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
             EntryKind::Method(ref method_data) => {
                 method_data.hash_stable(hcx, hasher);
             }
+            EntryKind::AssociatedExistential(associated_container) |
             EntryKind::AssociatedType(associated_container) => {
                 associated_container.hash_stable(hcx, hasher);
             }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index ab383287773..7b13c98b31d 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -237,7 +237,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             hir::ItemKind::Use(..) => {}
             // The interface is empty
             hir::ItemKind::GlobalAsm(..) => {}
-            hir::ItemKind::Existential(..) => {
+            hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => {
                 if item_level.is_some() {
                     // Reach the (potentially private) type and the API being exposed
                     self.reach(item.id).ty().predicates();
@@ -245,6 +245,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
             }
             // Visit everything
             hir::ItemKind::Const(..) | hir::ItemKind::Static(..) |
+            hir::ItemKind::Existential(..) |
             hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) => {
                 if item_level.is_some() {
                     self.reach(item.id).generics().predicates().ty();
@@ -1165,6 +1166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
                                          hir::ImplItemKind::Method(..) => {
                                              self.access_levels.is_reachable(impl_item.id)
                                          }
+                                         hir::ImplItemKind::Existential(..) |
                                          hir::ImplItemKind::Type(_) => false,
                                      }
                                  });
@@ -1566,7 +1568,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             hir::ItemKind::Use(..) => {}
             // No subitems
             hir::ItemKind::GlobalAsm(..) => {}
-            hir::ItemKind::Existential(..) => {
+            hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => {
                 // Check the traits being exposed, as they're separate,
                 // e.g. `impl Iterator<Item=T>` has two predicates,
                 // `X: Iterator` and `<X as Iterator>::Item == T`,
@@ -1577,6 +1579,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
             }
             // Subitems of these items have inherited publicity
             hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | hir::ItemKind::Fn(..) |
+            hir::ItemKind::Existential(..) |
             hir::ItemKind::Ty(..) => {
                 self.check(item.id, item_visibility).generics().predicates().ty();
 
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 29312912a24..e00919547fc 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -361,6 +361,11 @@ impl<'a> Resolver<'a> {
                 self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
             }
 
+            ItemKind::Existential(_, _) => {
+                let def = Def::Existential(self.definitions.local_def_id(item.id));
+                self.define(parent, ident, TypeNS, (def, vis, sp, expansion));
+            }
+
             ItemKind::Enum(ref enum_definition, _) => {
                 let def = Def::Enum(self.definitions.local_def_id(item.id));
                 let module_kind = ModuleKind::Def(def, ident.name);
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index f388b911feb..617ae4b787f 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -207,7 +207,7 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                 Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) |
                 Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) |
                 Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) |
-                Def::Existential(..) |
+                Def::Existential(..) | Def::AssociatedExistential(..) |
                 Def::Macro(..) | Def::GlobalAsm(..) | Def::Err =>
                     bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \
                          Def::TyParam")
@@ -535,6 +535,7 @@ impl<'a> PathSource<'a> {
                 Def::Struct(..) | Def::Union(..) | Def::Enum(..) |
                 Def::Trait(..) | Def::TyAlias(..) | Def::AssociatedTy(..) |
                 Def::PrimTy(..) | Def::TyParam(..) | Def::SelfTy(..) |
+                Def::Existential(..) |
                 Def::TyForeign(..) => true,
                 _ => false,
             },
@@ -2148,6 +2149,7 @@ impl<'a> Resolver<'a> {
         match item.node {
             ItemKind::Enum(_, ref generics) |
             ItemKind::Ty(_, ref generics) |
+            ItemKind::Existential(_, ref generics) |
             ItemKind::Struct(_, ref generics) |
             ItemKind::Union(_, ref generics) |
             ItemKind::Fn(_, _, ref generics, _) => {
@@ -2486,6 +2488,18 @@ impl<'a> Resolver<'a> {
 
                                             this.visit_ty(ty);
                                         }
+                                        ImplItemKind::Existential(ref bounds) => {
+                                            // If this is a trait impl, ensure the type
+                                            // exists in trait
+                                            this.check_trait_item(impl_item.ident,
+                                                                TypeNS,
+                                                                impl_item.span,
+                                                |n, s| TypeNotMemberOfTrait(n, s));
+
+                                            for bound in bounds {
+                                                this.visit_param_bound(bound);
+                                            }
+                                        }
                                         ImplItemKind::Macro(_) =>
                                             panic!("unexpanded macro in resolve!"),
                                     }
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 34dcdfb757f..58189ee0a2f 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1238,6 +1238,16 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
                 // trait.
                 self.visit_ty(ty)
             }
+            ast::ImplItemKind::Existential(ref bounds) => {
+                // FIXME uses of the assoc type should ideally point to this
+                // 'def' and the name here should be a ref to the def in the
+                // trait.
+                for bound in bounds.iter() {
+                    if let ast::GenericBound::Trait(ref trait_ref, _) = *bound {
+                        self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path)
+                    }
+                }
+            }
             ast::ImplItemKind::Macro(_) => {}
         }
     }
@@ -1477,6 +1487,36 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
                 self.visit_ty(&ty);
                 self.process_generic_params(ty_params, item.span, &qualname, item.id);
             }
+            Existential(ref _bounds, ref ty_params) => {
+                let qualname = format!("::{}", self.tcx.node_path_str(item.id));
+                // FIXME do something with _bounds
+                let value = String::new();
+                let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
+                if !self.span.filter_generated(sub_span, item.span) {
+                    let span = self.span_from_span(sub_span.expect("No span found for typedef"));
+                    let id = ::id_from_node_id(item.id, &self.save_ctxt);
+
+                    self.dumper.dump_def(
+                        &access_from!(self.save_ctxt, item),
+                        Def {
+                            kind: DefKind::Type,
+                            id,
+                            span,
+                            name: item.ident.to_string(),
+                            qualname: qualname.clone(),
+                            value,
+                            parent: None,
+                            children: vec![],
+                            decl_id: None,
+                            docs: self.save_ctxt.docs_for_attrs(&item.attrs),
+                            sig: sig::item_signature(item, &self.save_ctxt),
+                            attributes: lower_attributes(item.attrs.clone(), &self.save_ctxt),
+                        },
+                    );
+                }
+
+                self.process_generic_params(ty_params, item.span, &qualname, item.id);
+            }
             Mac(_) => (),
             _ => visit::walk_item(self, item),
         }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index f2620c04754..c84f194f023 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -749,6 +749,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             HirDef::TyAlias(def_id) |
             HirDef::TyForeign(def_id) |
             HirDef::TraitAlias(def_id) |
+            HirDef::AssociatedExistential(def_id) |
             HirDef::AssociatedTy(def_id) |
             HirDef::Trait(def_id) |
             HirDef::Existential(def_id) |
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index 70feba1eff8..13032562879 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -444,6 +444,18 @@ impl Sig for ast::Item {
                     refs: vec![],
                 })
             }
+            ast::ItemKind::Existential(ref bounds, ref generics) => {
+                let text = "existential type ".to_owned();
+                let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
+
+                if !bounds.is_empty() {
+                    sig.text.push_str(": ");
+                    sig.text.push_str(&pprust::bounds_to_string(bounds));
+                }
+                sig.text.push(';');
+
+                Ok(sig)
+            }
             ast::ItemKind::Ty(ref ty, ref generics) => {
                 let text = "type ".to_owned();
                 let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?;
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index f85e7b06858..60aea074f24 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1035,6 +1035,26 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
 
         let span = path.span;
         match path.def {
+            Def::Existential(did) => {
+                // check for desugared impl trait
+                if let Some(node_id) = tcx.hir.as_local_node_id(did) {
+                    if let hir::map::NodeItem(item) = tcx.hir.get(node_id) {
+                        if let hir::ItemKind::Existential(ref exist_ty) = item.node {
+                            if exist_ty.impl_trait_fn.is_some() {
+                                let lifetimes = &path.segments[0].args.as_ref().unwrap().args;
+                                return self.impl_trait_ty_to_ty(did, lifetimes);
+                            }
+                        }
+                    }
+                }
+                let item_segment = path.segments.split_last().unwrap();
+                self.prohibit_generics(item_segment.1);
+                let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
+                self.normalize_ty(
+                    span,
+                    tcx.mk_anon(did, substs),
+                )
+            }
             Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) |
             Def::Union(did) | Def::TyForeign(did) => {
                 assert_eq!(opt_self_ty, None);
@@ -1095,11 +1115,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx>+'o {
                     hir::TyStr => tcx.mk_str()
                 }
             }
-            Def::Existential(exist_ty_did) => {
-                assert!(exist_ty_did.is_local());
-                let lifetimes = &path.segments[0].args.as_ref().unwrap().args;
-                self.impl_trait_ty_to_ty(exist_ty_did, lifetimes)
-            }
             Def::Err => {
                 self.set_tainted_by_errors();
                 return self.tcx().types.err;
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index bee866db9e4..301072778d0 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -1332,6 +1332,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
         match self.mode {
             Mode::MethodCall => item.method_has_self_argument,
             Mode::Path => match item.kind {
+                ty::AssociatedKind::Existential |
                 ty::AssociatedKind::Type => false,
                 ty::AssociatedKind::Method | ty::AssociatedKind::Const => true
             },
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 9f83f8a00b1..e74652ff932 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1410,6 +1410,7 @@ fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let kind = match impl_item.node {
         hir::ImplItemKind::Const(..) => ty::AssociatedKind::Const,
         hir::ImplItemKind::Method(..) => ty::AssociatedKind::Method,
+        hir::ImplItemKind::Existential(..) => ty::AssociatedKind::Existential,
         hir::ImplItemKind::Type(_) => ty::AssociatedKind::Type
     };
 
@@ -1503,6 +1504,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          err.emit()
                     }
                 }
+                hir::ImplItemKind::Existential(..) |
                 hir::ImplItemKind::Type(_) => {
                     if ty_trait_item.kind == ty::AssociatedKind::Type {
                         if ty_trait_item.defaultness.has_value() {
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index d876f41ce13..df8323f8513 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -13,11 +13,12 @@ use constrained_type_params::{identify_constrained_type_params, Parameter};
 
 use hir::def_id::DefId;
 use rustc::traits::{self, ObligationCauseCode};
-use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind};
-use rustc::ty::subst::Substs;
+use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
+use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::util::ExplicitSelf;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::middle::lang_items;
+use rustc::infer::anon_types::may_define_existential_type;
 
 use syntax::ast;
 use syntax::feature_gate::{self, GateIssue};
@@ -209,6 +210,10 @@ fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     fcx.register_wf_obligation(ty, span, code.clone());
                 }
             }
+            ty::AssociatedKind::Existential => {
+                // FIXME(oli-obk) implement existential types in trait impls
+                unimplemented!()
+            }
         }
 
         implied_bounds
@@ -282,7 +287,7 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         }
 
-        check_where_clauses(tcx, fcx, item.span, def_id);
+        check_where_clauses(tcx, fcx, item.span, def_id, None);
 
         vec![] // no implied bounds in a struct def'n
     });
@@ -291,7 +296,7 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
     let trait_def_id = tcx.hir.local_def_id(item.id);
     for_item(tcx, item).with_fcx(|fcx, _| {
-        check_where_clauses(tcx, fcx, item.span, trait_def_id);
+        check_where_clauses(tcx, fcx, item.span, trait_def_id, None);
         vec![]
     });
 }
@@ -357,7 +362,7 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         }
 
-        check_where_clauses(tcx, fcx, item.span, item_def_id);
+        check_where_clauses(tcx, fcx, item.span, item_def_id, None);
 
         fcx.impl_implied_bounds(item_def_id, item.span)
     });
@@ -369,6 +374,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
     fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
     span: Span,
     def_id: DefId,
+    return_ty: Option<Ty<'tcx>>,
 ) {
     use ty::subst::Subst;
     use rustc::ty::TypeFoldable;
@@ -482,7 +488,12 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
         traits::Obligation::new(cause, fcx.param_env, pred)
     });
 
-    let predicates = predicates.instantiate_identity(fcx.tcx);
+    let mut predicates = predicates.instantiate_identity(fcx.tcx);
+
+    if let Some(return_ty) = return_ty {
+        predicates.predicates.extend(check_existential_types(tcx, fcx, def_id, span, return_ty));
+    }
+
     let predicates = fcx.normalize_associated_types_in(span, &predicates);
 
     debug!("check_where_clauses: predicates={:?}", predicates.predicates);
@@ -521,7 +532,79 @@ fn check_fn_or_method<'a, 'fcx, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
     // FIXME(#25759) return types should not be implied bounds
     implied_bounds.push(sig.output());
 
-    check_where_clauses(tcx, fcx, span, def_id);
+    check_where_clauses(tcx, fcx, span, def_id, Some(sig.output()));
+}
+
+fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
+    tcx: TyCtxt<'a, 'gcx, 'gcx>,
+    fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
+    fn_def_id: DefId,
+    span: Span,
+    ty: Ty<'tcx>,
+) -> Vec<ty::Predicate<'tcx>> {
+    trace!("check_existential_types: {:?}, {:?}", ty, ty.sty);
+    let mut substituted_predicates = Vec::new();
+    ty.fold_with(&mut ty::fold::BottomUpFolder {
+        tcx: fcx.tcx,
+        fldop: |ty| {
+            if let ty::TyAnon(def_id, substs) = ty.sty {
+                trace!("check_existential_types: anon_ty, {:?}, {:?}", def_id, substs);
+                let anon_node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+                if may_define_existential_type(tcx, fn_def_id, anon_node_id) {
+                    let generics = tcx.generics_of(def_id);
+                    trace!("check_existential_types may define. Generics: {:#?}", generics);
+                    for (subst, param) in substs.iter().zip(&generics.params) {
+                        if let ty::subst::UnpackedKind::Type(ty) = subst.unpack() {
+                            match ty.sty {
+                                ty::TyParam(..) => {},
+                                // prevent `fn foo() -> Foo<u32>` from being defining
+                                _ => {
+                                    tcx
+                                        .sess
+                                        .struct_span_err(
+                                            span,
+                                            "non-defining existential type use in defining scope",
+                                        )
+                                        .span_note(
+                                            tcx.def_span(param.def_id),
+                                            &format!(
+                                                "used non-generic type {} for generic parameter",
+                                                ty,
+                                            ),
+                                        )
+                                        .emit();
+                                    return tcx.types.err;
+                                },
+                            } // match ty
+                        } // if let Type = subst
+                    } // for (subst, param)
+                } // if may_define_existential_type
+
+                // now register the bounds on the parameters of the existential type
+                // so the parameters given by the function need to fulfil them
+                // ```rust
+                // existential type Foo<T: Bar>: 'static;
+                // fn foo<U>() -> Foo<U> { .. *}
+                // ```
+                // becomes
+                // ```rust
+                // existential type Foo<T: Bar>: 'static;
+                // fn foo<U: Bar>() -> Foo<U> { .. *}
+                // ```
+                let predicates = tcx.predicates_of(def_id);
+                trace!("check_existential_types may define. adding predicates: {:#?}", predicates);
+                for &pred in predicates.predicates.iter() {
+                    let substituted_pred = pred.subst(fcx.tcx, substs);
+                    // Avoid duplication of predicates that contain no parameters, for example.
+                    if !predicates.predicates.contains(&substituted_pred) {
+                        substituted_predicates.push(substituted_pred);
+                    }
+                }
+            } // if let TyAnon
+            ty
+        },
+    });
+    substituted_predicates
 }
 
 fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 3207ac44948..d82ad0d180b 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -17,9 +17,10 @@ use rustc::hir;
 use rustc::hir::def_id::{DefId, DefIndex};
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::infer::InferCtxt;
+use rustc::ty::subst::UnpackedKind;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::adjustment::{Adjust, Adjustment};
-use rustc::ty::fold::{TypeFoldable, TypeFolder};
+use rustc::ty::fold::{TypeFoldable, TypeFolder, BottomUpFolder};
 use rustc::util::nodemap::DefIdSet;
 use syntax::ast;
 use syntax_pos::Span;
@@ -388,11 +389,65 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
         for (&def_id, anon_defn) in self.fcx.anon_types.borrow().iter() {
             let node_id = self.tcx().hir.as_local_node_id(def_id).unwrap();
             let instantiated_ty = self.resolve(&anon_defn.concrete_ty, &node_id);
-            let definition_ty = self.fcx.infer_anon_definition_from_instantiation(
+            let mut definition_ty = self.fcx.infer_anon_definition_from_instantiation(
                 def_id,
                 anon_defn,
                 instantiated_ty,
             );
+
+            let generics = self.tcx().generics_of(def_id);
+
+            // named existential type, not an impl trait
+            if generics.parent.is_none() {
+                // prevent
+                // * `fn foo<T>() -> Foo<T>`
+                // * `fn foo<T: Bound + Other>() -> Foo<T>`
+                // from being defining
+
+                // Also replace all generic params with the ones from the existential type
+                // definition so
+                // ```rust
+                // existential type Foo<T>: 'static;
+                // fn foo<U>() -> Foo<U> { .. }
+                // ```
+                // figures out the concrete type with `U`, but the stored type is with `T`
+                definition_ty = definition_ty.fold_with(&mut BottomUpFolder {
+                    tcx: self.tcx().global_tcx(),
+                    fldop: |ty| {
+                        // find a type parameter
+                        if let ty::TyParam(..) = ty.sty {
+                            // look it up in the substitution list
+                            assert_eq!(anon_defn.substs.len(), generics.params.len());
+                            for (subst, param) in anon_defn.substs.iter().zip(&generics.params) {
+                                if let UnpackedKind::Type(subst) = subst.unpack() {
+                                    if subst == ty {
+                                        // found it in the substitution list, replace with the
+                                        // parameter from the existential type
+                                        return self
+                                            .tcx()
+                                            .global_tcx()
+                                            .mk_ty_param(param.index, param.name);
+                                    }
+                                }
+                            }
+                            self.tcx()
+                                .sess
+                                .struct_span_err(
+                                    span,
+                                    &format!(
+                                        "type parameter `{}` is part of concrete type but not used \
+                                        in parameter list for existential type",
+                                        ty,
+                                    ),
+                                )
+                                .emit();
+                            return self.tcx().types.err;
+                        }
+                        ty
+                    },
+                });
+            }
+
             let old = self.tables.concrete_existential_types.insert(def_id, definition_ty);
             if let Some(old) = old {
                 if old != definition_ty {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 4b628d6ffad..ab81cb8788f 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -269,6 +269,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 ItemKind::Fn(.., ref generics, _) |
                 ItemKind::Impl(_, _, _, ref generics, ..) |
                 ItemKind::Ty(_, ref generics) |
+                ItemKind::Existential(ExistTy { ref generics, impl_trait_fn: None, ..}) |
                 ItemKind::Enum(_, ref generics) |
                 ItemKind::Struct(_, ref generics) |
                 ItemKind::Union(_, ref generics) => generics,
@@ -419,7 +420,11 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
                 convert_variant_ctor(tcx, struct_def.id());
             }
         },
-        hir::ItemKind::Existential(..) => {}
+
+        // Desugared from `impl Trait` -> visited by the function's return type
+        hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => {}
+
+        hir::ItemKind::Existential(..) |
         hir::ItemKind::Ty(..) |
         hir::ItemKind::Static(..) |
         hir::ItemKind::Const(..) |
@@ -1002,6 +1007,13 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     })
 }
 
+fn report_assoc_ty_on_inherent_impl<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    span: Span,
+) {
+    span_err!(tcx.sess, span, E0202, "associated types are not allowed in inherent impls");
+}
+
 fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                      def_id: DefId)
                      -> Ty<'tcx> {
@@ -1034,10 +1046,16 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     tcx.mk_fn_def(def_id, substs)
                 }
                 ImplItemKind::Const(ref ty, _) => icx.to_ty(ty),
+                ImplItemKind::Existential(ref _bounds) => {
+                    if tcx.impl_trait_ref(tcx.hir.get_parent_did(node_id)).is_none() {
+                        report_assoc_ty_on_inherent_impl(tcx, item.span);
+                    }
+                    // FIXME(oli-obk) implement existential types in trait impls
+                    unimplemented!()
+                }
                 ImplItemKind::Type(ref ty) => {
                     if tcx.impl_trait_ref(tcx.hir.get_parent_did(node_id)).is_none() {
-                        span_err!(tcx.sess, item.span, E0202,
-                                  "associated types are not allowed in inherent impls");
+                        report_assoc_ty_on_inherent_impl(tcx, item.span);
                     }
 
                     icx.to_ty(ty)
@@ -1062,8 +1080,9 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     let substs = Substs::identity_for_item(tcx, def_id);
                     tcx.mk_adt(def, substs)
                 }
-                // this is only reachable once we have named existential types
-                ItemKind::Existential(hir::ExistTy { impl_trait_fn: None, .. }) => unimplemented!(),
+                ItemKind::Existential(hir::ExistTy { impl_trait_fn: None, .. }) => {
+                    find_existential_constraints(tcx, def_id)
+                },
                 // existential types desugared from impl Trait
                 ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(owner), .. }) => {
                     tcx.typeck_tables_of(owner).concrete_existential_types[&def_id]
@@ -1153,6 +1172,95 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+fn find_existential_constraints<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    def_id: DefId,
+) -> ty::Ty<'tcx> {
+    use rustc::hir::map::*;
+    use rustc::hir::*;
+
+    struct ConstraintLocator<'a, 'tcx: 'a> {
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        def_id: DefId,
+        found: Option<(Span, ty::Ty<'tcx>)>,
+    }
+    impl<'a, 'tcx> ConstraintLocator<'a, 'tcx> {
+        fn check(&mut self, node_id: ast::NodeId) {
+            let def_id = self.tcx.hir.local_def_id(node_id);
+            // don't try to check items that cannot possibly constrain the type
+            if !self.tcx.has_typeck_tables(def_id) {
+                return;
+            }
+            let ty = self
+                .tcx
+                .typeck_tables_of(def_id)
+                .concrete_existential_types
+                .get(&self.def_id)
+                .cloned();
+            if let Some(ty) = ty {
+                // FIXME(oli-obk): trace the actual span from inference to improve errors
+                let span = self.tcx.def_span(def_id);
+                if let Some((prev_span, prev_ty)) = self.found {
+                    if ty != prev_ty {
+                        // found different concrete types for the existential type
+                        let mut err = self.tcx.sess.struct_span_err(
+                            span,
+                            "defining existential type use differs from previous",
+                        );
+                        err.span_note(prev_span, "previous use here");
+                        err.emit();
+                    }
+                } else {
+                    self.found = Some((span, ty));
+                }
+            }
+        }
+    }
+    impl<'a, 'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'a, 'tcx> {
+        fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
+            intravisit::NestedVisitorMap::All(&self.tcx.hir)
+        }
+        fn visit_item(&mut self, it: &'tcx Item) {
+            // the existential type itself or its children are not within its reveal scope
+            if self.tcx.hir.local_def_id(it.id) != self.def_id {
+                self.check(it.id);
+                intravisit::walk_item(self, it);
+            }
+        }
+        fn visit_impl_item(&mut self, it: &'tcx ImplItem) {
+            // the existential type itself or its children are not within its reveal scope
+            if self.tcx.hir.local_def_id(it.id) != self.def_id {
+                self.check(it.id);
+                intravisit::walk_impl_item(self, it);
+            }
+        }
+        fn visit_trait_item(&mut self, it: &'tcx TraitItem) {
+            self.check(it.id);
+            intravisit::walk_trait_item(self, it);
+        }
+    }
+    let mut locator = ConstraintLocator { def_id, tcx, found: None };
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let parent = tcx.hir.get_parent(node_id);
+    if parent == ast::CRATE_NODE_ID {
+        intravisit::walk_crate(&mut locator, tcx.hir.krate());
+    } else {
+        match tcx.hir.get(parent) {
+            NodeItem(ref it) => intravisit::walk_item(&mut locator, it),
+            NodeImplItem(ref it) => intravisit::walk_impl_item(&mut locator, it),
+            other => bug!("{:?} is not a valid parent of an existential type item", other),
+        }
+    }
+    match locator.found {
+        Some((_, ty)) => ty,
+        None => {
+            let span = tcx.def_span(def_id);
+            tcx.sess.span_err(span, "could not find defining uses");
+            tcx.types.err
+        }
+    }
+}
+
 fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     def_id: DefId)
                     -> ty::PolyFnSig<'tcx> {
@@ -1366,6 +1474,9 @@ fn explicit_predicates_of<'a, 'tcx>(
 
     let icx = ItemCtxt::new(tcx, def_id);
     let no_generics = hir::Generics::empty();
+
+    let mut predicates = vec![];
+
     let ast_generics = match node {
         NodeTraitItem(item) => {
             &item.generics
@@ -1391,23 +1502,28 @@ fn explicit_predicates_of<'a, 'tcx>(
                     is_trait = Some((ty::TraitRef::identity(tcx, def_id), items));
                     generics
                 }
-                ItemKind::Existential(ref exist_ty) => {
+                ItemKind::Existential(ExistTy { ref bounds, impl_trait_fn, ref generics }) => {
                     let substs = Substs::identity_for_item(tcx, def_id);
                     let anon_ty = tcx.mk_anon(def_id, substs);
 
                     // Collect the bounds, i.e. the `A+B+'c` in `impl A+B+'c`.
                     let bounds = compute_bounds(&icx,
                                                 anon_ty,
-                                                &exist_ty.bounds,
+                                                bounds,
                                                 SizedByDefault::Yes,
                                                 tcx.def_span(def_id));
 
-                    let predicates = bounds.predicates(tcx, anon_ty);
-
-                    return ty::GenericPredicates {
-                        parent: None,
-                        predicates: predicates
-                    };
+                    if impl_trait_fn.is_some() {
+                        // impl Trait
+                        return ty::GenericPredicates {
+                            parent: None,
+                            predicates: bounds.predicates(tcx, anon_ty),
+                        };
+                    } else {
+                        // named existential types
+                        predicates.extend(bounds.predicates(tcx, anon_ty));
+                        generics
+                    }
                 }
 
                 _ => &no_generics,
@@ -1429,8 +1545,6 @@ fn explicit_predicates_of<'a, 'tcx>(
     let parent_count = generics.parent_count as u32;
     let has_own_self = generics.has_self && parent_count == 0;
 
-    let mut predicates = vec![];
-
     // Below we'll consider the bounds on the type parameters (including `Self`)
     // and the explicit where-clauses, but to get the full set of predicates
     // on a trait we need to add in the supertrait bounds and bounds found on
diff --git a/src/librustc_typeck/namespace.rs b/src/librustc_typeck/namespace.rs
index 6f0e46b3afe..690bf1c550c 100644
--- a/src/librustc_typeck/namespace.rs
+++ b/src/librustc_typeck/namespace.rs
@@ -21,6 +21,7 @@ pub enum Namespace {
 impl From<ty::AssociatedKind> for Namespace {
     fn from(a_kind: ty::AssociatedKind) -> Self {
         match a_kind {
+            ty::AssociatedKind::Existential |
             ty::AssociatedKind::Type => Namespace::Type,
             ty::AssociatedKind::Const |
             ty::AssociatedKind::Method => Namespace::Value,
@@ -31,6 +32,7 @@ impl From<ty::AssociatedKind> for Namespace {
 impl<'a> From <&'a hir::ImplItemKind> for Namespace {
     fn from(impl_kind: &'a hir::ImplItemKind) -> Self {
         match *impl_kind {
+            hir::ImplItemKind::Existential(..) |
             hir::ImplItemKind::Type(..) => Namespace::Type,
             hir::ImplItemKind::Const(..) |
             hir::ImplItemKind::Method(..) => Namespace::Value,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2bf1f6e553f..cf4eec97d8c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -512,6 +512,7 @@ pub enum ItemEnum {
     FunctionItem(Function),
     ModuleItem(Module),
     TypedefItem(Typedef, bool /* is associated type */),
+    ExistentialItem(Existential, bool /* is associated type */),
     StaticItem(Static),
     ConstantItem(Constant),
     TraitItem(Trait),
@@ -545,6 +546,7 @@ impl ItemEnum {
             ItemEnum::EnumItem(ref e) => &e.generics,
             ItemEnum::FunctionItem(ref f) => &f.generics,
             ItemEnum::TypedefItem(ref t, _) => &t.generics,
+            ItemEnum::ExistentialItem(ref t, _) => &t.generics,
             ItemEnum::TraitItem(ref t) => &t.generics,
             ItemEnum::ImplItem(ref i) => &i.generics,
             ItemEnum::TyMethodItem(ref i) => &i.generics,
@@ -596,6 +598,7 @@ impl Clean<Item> for doctree::Module {
         items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
         items.extend(self.mods.iter().map(|x| x.clean(cx)));
         items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
+        items.extend(self.existentials.iter().map(|x| x.clean(cx)));
         items.extend(self.statics.iter().map(|x| x.clean(cx)));
         items.extend(self.constants.iter().map(|x| x.clean(cx)));
         items.extend(self.traits.iter().map(|x| x.clean(cx)));
@@ -2411,6 +2414,10 @@ impl Clean<Item> for hir::ImplItem {
                 type_: ty.clean(cx),
                 generics: Generics::default(),
             }, true),
+            hir::ImplItemKind::Existential(ref bounds) => ExistentialItem(Existential {
+                bounds: bounds.clean(cx),
+                generics: Generics::default(),
+            }, true),
         };
         Item {
             name: Some(self.ident.name.clean(cx)),
@@ -2554,6 +2561,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
                     }, true)
                 }
             }
+            ty::AssociatedKind::Existential => unimplemented!(),
         };
 
         let visibility = match self.container {
@@ -3696,6 +3704,30 @@ impl Clean<Item> for doctree::Typedef {
     }
 }
 
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub struct Existential {
+    pub bounds: Vec<GenericBound>,
+    pub generics: Generics,
+}
+
+impl Clean<Item> for doctree::Existential {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            name: Some(self.name.clean(cx)),
+            attrs: self.attrs.clean(cx),
+            source: self.whence.clean(cx),
+            def_id: cx.tcx.hir.local_def_id(self.id.clone()),
+            visibility: self.vis.clean(cx),
+            stability: self.stab.clean(cx),
+            deprecation: self.depr.clean(cx),
+            inner: ExistentialItem(Existential {
+                bounds: self.exist_ty.bounds.clean(cx),
+                generics: self.exist_ty.generics.clean(cx),
+            }, false),
+        }
+    }
+}
+
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
 pub struct BareFunctionDecl {
     pub unsafety: hir::Unsafety,
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 6fd9ef234f4..591c660138a 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -37,6 +37,7 @@ pub struct Module {
     pub mods: Vec<Module>,
     pub id: NodeId,
     pub typedefs: Vec<Typedef>,
+    pub existentials: Vec<Existential>,
     pub statics: Vec<Static>,
     pub constants: Vec<Constant>,
     pub traits: Vec<Trait>,
@@ -68,6 +69,7 @@ impl Module {
             fns        : Vec::new(),
             mods       : Vec::new(),
             typedefs   : Vec::new(),
+            existentials: Vec::new(),
             statics    : Vec::new(),
             constants  : Vec::new(),
             traits     : Vec::new(),
@@ -167,6 +169,17 @@ pub struct Typedef {
     pub depr: Option<attr::Deprecation>,
 }
 
+pub struct Existential {
+    pub exist_ty: hir::ExistTy,
+    pub name: Name,
+    pub id: ast::NodeId,
+    pub attrs: hir::HirVec<ast::Attribute>,
+    pub whence: Span,
+    pub vis: hir::Visibility,
+    pub stab: Option<attr::Stability>,
+    pub depr: Option<attr::Deprecation>,
+}
+
 #[derive(Debug)]
 pub struct Static {
     pub type_: P<hir::Ty>,
diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs
index 9b8ada1f6e6..a5131e327e0 100644
--- a/src/librustdoc/html/item_type.rs
+++ b/src/librustdoc/html/item_type.rs
@@ -43,6 +43,7 @@ pub enum ItemType {
     Union           = 19,
     ForeignType     = 20,
     Keyword         = 21,
+    Existential     = 22,
 }
 
 
@@ -70,6 +71,7 @@ impl<'a> From<&'a clean::Item> for ItemType {
             clean::EnumItem(..)            => ItemType::Enum,
             clean::FunctionItem(..)        => ItemType::Function,
             clean::TypedefItem(..)         => ItemType::Typedef,
+            clean::ExistentialItem(..)     => ItemType::Existential,
             clean::StaticItem(..)          => ItemType::Static,
             clean::ConstantItem(..)        => ItemType::Constant,
             clean::TraitItem(..)           => ItemType::Trait,
@@ -135,6 +137,7 @@ impl ItemType {
             ItemType::AssociatedConst => "associatedconstant",
             ItemType::ForeignType     => "foreigntype",
             ItemType::Keyword         => "keyword",
+            ItemType::Existential     => "existential",
         }
     }
 
@@ -148,6 +151,7 @@ impl ItemType {
             ItemType::Trait |
             ItemType::Primitive |
             ItemType::AssociatedType |
+            ItemType::Existential |
             ItemType::ForeignType => NameSpace::Type,
 
             ItemType::ExternCrate |
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 41c08dbf4ab..928d7d38351 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1570,6 +1570,7 @@ struct AllTypes {
     macros: HashSet<ItemEntry>,
     functions: HashSet<ItemEntry>,
     typedefs: HashSet<ItemEntry>,
+    existentials: HashSet<ItemEntry>,
     statics: HashSet<ItemEntry>,
     constants: HashSet<ItemEntry>,
     keywords: HashSet<ItemEntry>,
@@ -1586,6 +1587,7 @@ impl AllTypes {
             macros: HashSet::with_capacity(100),
             functions: HashSet::with_capacity(100),
             typedefs: HashSet::with_capacity(100),
+            existentials: HashSet::with_capacity(100),
             statics: HashSet::with_capacity(100),
             constants: HashSet::with_capacity(100),
             keywords: HashSet::with_capacity(100),
@@ -1607,6 +1609,7 @@ impl AllTypes {
                 ItemType::Macro => self.macros.insert(ItemEntry::new(new_url, name)),
                 ItemType::Function => self.functions.insert(ItemEntry::new(new_url, name)),
                 ItemType::Typedef => self.typedefs.insert(ItemEntry::new(new_url, name)),
+                ItemType::Existential => self.existentials.insert(ItemEntry::new(new_url, name)),
                 ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
                 ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
                 _ => true,
@@ -1650,6 +1653,7 @@ impl fmt::Display for AllTypes {
         print_entries(f, &self.macros, "Macros", "macros")?;
         print_entries(f, &self.functions, "Functions", "functions")?;
         print_entries(f, &self.typedefs, "Typedefs", "typedefs")?;
+        print_entries(f, &self.existentials, "Existentials", "existentials")?;
         print_entries(f, &self.statics, "Statics", "statics")?;
         print_entries(f, &self.constants, "Constants", "constants")
     }
@@ -4400,6 +4404,7 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) {
         ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
         ItemType::ForeignType     => ("foreign-types", "Foreign Types"),
         ItemType::Keyword         => ("keywords", "Keywords"),
+        ItemType::Existential     => ("existentials", "Existentials"),
     }
 }
 
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index fe116a22ecc..699ee25436a 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -84,6 +84,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
                 return ret;
             }
             // These items can all get re-exported
+            clean::ExistentialItem(..) |
             clean::TypedefItem(..) | clean::StaticItem(..) |
             clean::StructItem(..) | clean::EnumItem(..) |
             clean::TraitItem(..) | clean::FunctionItem(..) |
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 875ba111ec0..267b7000948 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -439,6 +439,19 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
                 };
                 om.typedefs.push(t);
             },
+            hir::ItemKind::Existential(ref exist_ty) => {
+                let t = Existential {
+                    exist_ty: exist_ty.clone(),
+                    name,
+                    id: item.id,
+                    attrs: item.attrs.clone(),
+                    whence: item.span,
+                    vis: item.vis.clone(),
+                    stab: self.stability(item.id),
+                    depr: self.deprecation(item.id),
+                };
+                om.existentials.push(t);
+            },
             hir::ItemKind::Static(ref ty, ref mut_, ref exp) => {
                 let s = Static {
                     type_: ty.clone(),
@@ -523,9 +536,6 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
                     om.impls.push(i);
                 }
             },
-            hir::ItemKind::Existential(_) => {
-                // FIXME(oli-obk): actually generate docs for real existential items
-            }
         }
     }
 
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bcdad92bc32..1b6b47f5489 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1394,6 +1394,7 @@ pub enum ImplItemKind {
     Const(P<Ty>, P<Expr>),
     Method(MethodSig, P<Block>),
     Type(P<Ty>),
+    Existential(GenericBounds),
     Macro(Mac),
 }
 
@@ -2132,6 +2133,10 @@ pub enum ItemKind {
     ///
     /// E.g. `type Foo = Bar<u8>;`
     Ty(P<Ty>, Generics),
+    /// An existential type declaration (`existential type`).
+    ///
+    /// E.g. `existential type Foo: Bar + Boo;`
+    Existential(GenericBounds, Generics),
     /// An enum definition (`enum` or `pub enum`).
     ///
     /// E.g. `enum Foo<A, B> { C<A>, D<B> }`
@@ -2183,6 +2188,7 @@ impl ItemKind {
             ItemKind::ForeignMod(..) => "foreign module",
             ItemKind::GlobalAsm(..) => "global asm",
             ItemKind::Ty(..) => "type alias",
+            ItemKind::Existential(..) => "existential type",
             ItemKind::Enum(..) => "enum",
             ItemKind::Struct(..) => "struct",
             ItemKind::Union(..) => "union",
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 1a73096505f..aef6b8ba5a8 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -419,6 +419,9 @@ declare_features! (
     // Allows macro invocations in `extern {}` blocks
     (active, macros_in_extern, "1.27.0", Some(49476), None),
 
+    // `existential type`
+    (active, existential_type, "1.28.0", Some(34511), None),
+
     // unstable #[target_feature] directives
     (active, arm_target_feature, "1.27.0", Some(44839), None),
     (active, aarch64_target_feature, "1.27.0", Some(44839), None),
@@ -1643,6 +1646,15 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, decl_macro, i.span, msg);
             }
 
+            ast::ItemKind::Existential(..) => {
+                gate_feature_post!(
+                    &self,
+                    existential_type,
+                    i.span,
+                    "existential types are unstable"
+                );
+            }
+
             _ => {}
         }
 
@@ -1842,6 +1854,15 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                     gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable");
                 }
             }
+            ast::ImplItemKind::Existential(..) => {
+                gate_feature_post!(
+                    &self,
+                    existential_type,
+                    ii.span,
+                    "existential types are unstable"
+                );
+            }
+
             ast::ImplItemKind::Type(_) if !ii.generics.params.is_empty() => {
                 gate_feature_post!(&self, generic_associated_types, ii.span,
                                    "generic associated types are unstable");
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index d9d3febc4fe..9d5982c1e28 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -912,6 +912,10 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
         ItemKind::Ty(t, generics) => {
             ItemKind::Ty(folder.fold_ty(t), folder.fold_generics(generics))
         }
+        ItemKind::Existential(bounds, generics) => ItemKind::Existential(
+            folder.fold_bounds(bounds),
+            folder.fold_generics(generics),
+        ),
         ItemKind::Enum(enum_definition, generics) => {
             let generics = folder.fold_generics(generics);
             let variants = enum_definition.variants.move_map(|x| folder.fold_variant(x));
@@ -1002,6 +1006,9 @@ pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T)
                                folder.fold_block(body))
             }
             ast::ImplItemKind::Type(ty) => ast::ImplItemKind::Type(folder.fold_ty(ty)),
+            ast::ImplItemKind::Existential(bounds) => {
+                ast::ImplItemKind::Existential(folder.fold_bounds(bounds))
+            },
             ast::ImplItemKind::Macro(mac) => ast::ImplItemKind::Macro(folder.fold_mac(mac))
         },
         span: folder.new_span(i.span),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 62bb5fbd04f..2eaa56ebeb8 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -63,6 +63,15 @@ use std::mem;
 use std::path::{self, Path, PathBuf};
 use std::slice;
 
+#[derive(Debug)]
+/// Whether the type alias or associated type is a concrete type or an existential type
+pub enum AliasKind {
+    /// Just a new name for the same type
+    Weak(P<Ty>),
+    /// Only trait impls of the type will be usable, not the actual type itself
+    Existential(GenericBounds),
+}
+
 bitflags! {
     struct Restrictions: u8 {
         const STMT_EXPR         = 1 << 0;
@@ -5502,16 +5511,13 @@ impl<'a> Parser<'a> {
         let lo = self.span;
         let vis = self.parse_visibility(false)?;
         let defaultness = self.parse_defaultness();
-        let (name, node, generics) = if self.eat_keyword(keywords::Type) {
-            // This parses the grammar:
-            //     ImplItemAssocTy = Ident ["<"...">"] ["where" ...] "=" Ty ";"
-            let name = self.parse_ident()?;
-            let mut generics = self.parse_generics()?;
-            generics.where_clause = self.parse_where_clause()?;
-            self.expect(&token::Eq)?;
-            let typ = self.parse_ty()?;
-            self.expect(&token::Semi)?;
-            (name, ast::ImplItemKind::Type(typ), generics)
+        let (name, node, generics) = if let Some(type_) = self.eat_type() {
+            let (name, alias, generics) = type_?;
+            let kind = match alias {
+                AliasKind::Weak(typ) => ast::ImplItemKind::Type(typ),
+                AliasKind::Existential(bounds) => ast::ImplItemKind::Existential(bounds),
+            };
+            (name, kind, generics)
         } else if self.is_const_item() {
             // This parses the grammar:
             //     ImplItemConst = "const" Ident ":" Ty "=" Expr ";"
@@ -6563,14 +6569,43 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse type Foo = Bar;
-    fn parse_item_type(&mut self) -> PResult<'a, ItemInfo> {
+    /// or
+    /// existential type Foo: Bar;
+    /// or
+    /// return None without modifying the parser state
+    fn eat_type(&mut self) -> Option<PResult<'a, (Ident, AliasKind, ast::Generics)>> {
+        // This parses the grammar:
+        //     Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";"
+        if self.check_keyword(keywords::Type) ||
+           self.check_keyword(keywords::Existential) &&
+                self.look_ahead(1, |t| t.is_keyword(keywords::Type)) {
+            let existential = self.eat_keyword(keywords::Existential);
+            assert!(self.eat_keyword(keywords::Type));
+            Some(self.parse_existential_or_alias(existential))
+        } else {
+            None
+        }
+    }
+
+    /// Parse type alias or existential type
+    fn parse_existential_or_alias(
+        &mut self,
+        existential: bool,
+    ) -> PResult<'a, (Ident, AliasKind, ast::Generics)> {
         let ident = self.parse_ident()?;
         let mut tps = self.parse_generics()?;
         tps.where_clause = self.parse_where_clause()?;
-        self.expect(&token::Eq)?;
-        let ty = self.parse_ty()?;
+        let alias = if existential {
+            self.expect(&token::Colon)?;
+            let bounds = self.parse_generic_bounds()?;
+            AliasKind::Existential(bounds)
+        } else {
+            self.expect(&token::Eq)?;
+            let ty = self.parse_ty()?;
+            AliasKind::Weak(ty)
+        };
         self.expect(&token::Semi)?;
-        Ok((ident, ItemKind::Ty(ty, tps), None))
+        Ok((ident, alias, tps))
     }
 
     /// Parse the part of an "enum" decl following the '{'
@@ -6926,15 +6961,19 @@ impl<'a> Parser<'a> {
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
-        if self.eat_keyword(keywords::Type) {
+        if let Some(type_) = self.eat_type() {
+            let (ident, alias, generics) = type_?;
             // TYPE ITEM
-            let (ident, item_, extra_attrs) = self.parse_item_type()?;
+            let item_ = match alias {
+                AliasKind::Weak(ty) => ItemKind::Ty(ty, generics),
+                AliasKind::Existential(bounds) => ItemKind::Existential(bounds, generics),
+            };
             let prev_span = self.prev_span;
             let item = self.mk_item(lo.to(prev_span),
                                     ident,
                                     item_,
                                     visibility,
-                                    maybe_append(attrs, extra_attrs));
+                                    attrs);
             return Ok(Some(item));
         }
         if self.eat_keyword(keywords::Enum) {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index b0a9003a456..de68780ef2c 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1280,9 +1280,7 @@ impl<'a> State<'a> {
                 self.end()?;
             }
             ast::ItemKind::Ty(ref ty, ref generics) => {
-                self.ibox(INDENT_UNIT)?;
-                self.ibox(0)?;
-                self.word_nbsp(&visibility_qualified(&item.vis, "type"))?;
+                self.head(&visibility_qualified(&item.vis, "type"))?;
                 self.print_ident(item.ident)?;
                 self.print_generic_params(&generics.params)?;
                 self.end()?; // end the inner ibox
@@ -1294,6 +1292,18 @@ impl<'a> State<'a> {
                 self.s.word(";")?;
                 self.end()?; // end the outer ibox
             }
+            ast::ItemKind::Existential(ref bounds, ref generics) => {
+                self.head(&visibility_qualified(&item.vis, "existential type"))?;
+                self.print_ident(item.ident)?;
+                self.print_generic_params(&generics.params)?;
+                self.end()?; // end the inner ibox
+
+                self.print_where_clause(&generics.where_clause)?;
+                self.s.space()?;
+                self.print_type_bounds(":", bounds)?;
+                self.s.word(";")?;
+                self.end()?; // end the outer ibox
+            }
             ast::ItemKind::Enum(ref enum_definition, ref params) => {
                 self.print_enum_def(
                     enum_definition,
@@ -1501,8 +1511,8 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_defaultness(&mut self, defatulness: ast::Defaultness) -> io::Result<()> {
-        if let ast::Defaultness::Default = defatulness {
+    pub fn print_defaultness(&mut self, defaultness: ast::Defaultness) -> io::Result<()> {
+        if let ast::Defaultness::Default = defaultness {
             try!(self.word_nbsp("default"));
         }
         Ok(())
@@ -1650,6 +1660,10 @@ impl<'a> State<'a> {
             ast::ImplItemKind::Type(ref ty) => {
                 self.print_associated_type(ii.ident, None, Some(ty))?;
             }
+            ast::ImplItemKind::Existential(ref bounds) => {
+                self.word_space("existential")?;
+                self.print_associated_type(ii.ident, Some(bounds), None)?;
+            }
             ast::ImplItemKind::Macro(ref mac) => {
                 self.print_mac(mac)?;
                 match mac.node.delim {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 9211a2383b6..51be129737e 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -252,6 +252,10 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_ty(typ);
             visitor.visit_generics(type_parameters)
         }
+        ItemKind::Existential(ref bounds, ref type_parameters) => {
+            walk_list!(visitor, visit_param_bound, bounds);
+            visitor.visit_generics(type_parameters)
+        }
         ItemKind::Enum(ref enum_definition, ref type_parameters) => {
             visitor.visit_generics(type_parameters);
             visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
@@ -600,6 +604,9 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt
         ImplItemKind::Type(ref ty) => {
             visitor.visit_ty(ty);
         }
+        ImplItemKind::Existential(ref bounds) => {
+            walk_list!(visitor, visit_param_bound, bounds);
+        }
         ImplItemKind::Macro(ref mac) => {
             visitor.visit_mac(mac);
         }
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 9a0c92f6793..62f22475e7d 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -426,6 +426,7 @@ declare_keywords! {
     (56, Default,            "default")
     (57, Dyn,                "dyn")
     (58, Union,              "union")
+    (59, Existential,        "existential")
 }
 
 impl Symbol {
diff --git a/src/test/parse-fail/issue-20711-2.rs b/src/test/parse-fail/issue-20711-2.rs
index 05df16d21d8..d0836d4af97 100644
--- a/src/test/parse-fail/issue-20711-2.rs
+++ b/src/test/parse-fail/issue-20711-2.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // compile-flags: -Z parse-only
+// ignore-tidy-linelength
 
 struct Foo;
 
@@ -16,6 +17,6 @@ impl Foo {
     fn foo() {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
-} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or
+} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, or
 
 fn main() {}
diff --git a/src/test/parse-fail/issue-20711.rs b/src/test/parse-fail/issue-20711.rs
index f30e20ad7db..d9442247988 100644
--- a/src/test/parse-fail/issue-20711.rs
+++ b/src/test/parse-fail/issue-20711.rs
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 // compile-flags: -Z parse-only
+// ignore-tidy-linelength
 
 struct Foo;
 
 impl Foo {
     #[stable(feature = "rust1", since = "1.0.0")]
-} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or
+} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`, or
 
 fn main() {}
diff --git a/src/test/parse-fail/removed-syntax-static-fn.rs b/src/test/parse-fail/removed-syntax-static-fn.rs
index fbc6848f372..4c0cd3358dd 100644
--- a/src/test/parse-fail/removed-syntax-static-fn.rs
+++ b/src/test/parse-fail/removed-syntax-static-fn.rs
@@ -9,10 +9,11 @@
 // except according to those terms.
 
 // compile-flags: -Z parse-only
+// ignore-tidy-linelength
 
 struct S;
 
 impl S {
     static fn f() {}
 }
-//~^^ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`,
+//~^^ ERROR expected one of `async`, `const`, `crate`, `default`, `existential`, `extern`, `fn`, `pub`, `type`,
diff --git a/src/test/run-pass/existential_type.rs b/src/test/run-pass/existential_type.rs
new file mode 100644
index 00000000000..d2cecd83036
--- /dev/null
+++ b/src/test/run-pass/existential_type.rs
@@ -0,0 +1,113 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(existential_type)]
+
+fn main() {
+    assert_eq!(foo().to_string(), "foo");
+    assert_eq!(bar1().to_string(), "bar1");
+    assert_eq!(bar2().to_string(), "bar2");
+    let mut x = bar1();
+    x = bar2();
+    assert_eq!(boo::boo().to_string(), "boo");
+    assert_eq!(my_iter(42u8).collect::<Vec<u8>>(), vec![42u8]);
+}
+
+// single definition
+existential type Foo: std::fmt::Display;
+
+fn foo() -> Foo {
+    "foo"
+}
+
+// two definitions
+existential type Bar: std::fmt::Display;
+
+fn bar1() -> Bar {
+    "bar1"
+}
+
+fn bar2() -> Bar {
+    "bar2"
+}
+
+// definition in submodule
+existential type Boo: std::fmt::Display;
+
+mod boo {
+    pub fn boo() -> super::Boo {
+        "boo"
+    }
+}
+
+existential type MyIter<T>: Iterator<Item = T>;
+
+fn my_iter<T>(t: T) -> MyIter<T> {
+    std::iter::once(t)
+}
+
+fn my_iter2<T>(t: T) -> MyIter<T> {
+    std::iter::once(t)
+}
+
+// param names should not have an effect!
+fn my_iter3<U>(u: U) -> MyIter<U> {
+    std::iter::once(u)
+}
+
+// param position should not have an effect!
+fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> {
+    std::iter::once(v)
+}
+
+// param names should not have an effect!
+existential type MyOtherIter<T>: Iterator<Item = T>;
+
+fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
+    std::iter::once(u)
+}
+
+trait Trait {}
+existential type GenericBound<T: Trait>: 'static;
+
+fn generic_bound<T: Trait>(_: T) -> GenericBound<T> {
+    unimplemented!()
+}
+
+mod pass_through {
+    pub existential type Passthrough<T>: 'static;
+
+    fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
+        t
+    }
+}
+
+fn use_passthrough(x: pass_through::Passthrough<u32>) -> pass_through::Passthrough<u32> {
+    x
+}
+
+existential type PartiallyDefined<T>: 'static;
+
+// doesn't declare all PartiallyDefined for all possible `T`, but since it's the only
+// function producing the value, noone can ever get a value that is problematic
+fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> {
+    4u32
+}
+
+existential type PartiallyDefined2<T>: 'static;
+
+fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> {
+    4u32
+}
+
+// fully defines PartiallyDefine2
+fn partially_defined22<T>(_: T) -> PartiallyDefined2<T> {
+    4u32
+}
diff --git a/src/test/ui/suggestions/as-ref.rs b/src/test/ui/as-ref.rs
index ae1c98c8564..ae1c98c8564 100644
--- a/src/test/ui/suggestions/as-ref.rs
+++ b/src/test/ui/as-ref.rs
diff --git a/src/test/ui/suggestions/as-ref.stderr b/src/test/ui/as-ref.stderr
index 27016445ec5..27016445ec5 100644
--- a/src/test/ui/suggestions/as-ref.stderr
+++ b/src/test/ui/as-ref.stderr
diff --git a/src/test/ui/suggestions/auxiliary/m1.rs b/src/test/ui/auxiliary/m1.rs
index b61667cfd88..b61667cfd88 100644
--- a/src/test/ui/suggestions/auxiliary/m1.rs
+++ b/src/test/ui/auxiliary/m1.rs
diff --git a/src/test/ui/suggestions/auxiliary/m2.rs b/src/test/ui/auxiliary/m2.rs
index 94ff5e4497f..94ff5e4497f 100644
--- a/src/test/ui/suggestions/auxiliary/m2.rs
+++ b/src/test/ui/auxiliary/m2.rs
diff --git a/src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs b/src/test/ui/auxiliary/macro-in-other-crate.rs
index 01282f2ad24..01282f2ad24 100644
--- a/src/test/ui/suggestions/auxiliary/macro-in-other-crate.rs
+++ b/src/test/ui/auxiliary/macro-in-other-crate.rs
diff --git a/src/test/ui/suggestions/auxiliary/removing-extern-crate.rs b/src/test/ui/auxiliary/removing-extern-crate.rs
index 4275e80e7fe..4275e80e7fe 100644
--- a/src/test/ui/suggestions/auxiliary/removing-extern-crate.rs
+++ b/src/test/ui/auxiliary/removing-extern-crate.rs
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.fixed b/src/test/ui/closure-immutable-outer-variable.fixed
index b3a0d592f76..b3a0d592f76 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.fixed
+++ b/src/test/ui/closure-immutable-outer-variable.fixed
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr b/src/test/ui/closure-immutable-outer-variable.nll.stderr
index 335ccefe8a0..335ccefe8a0 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr
+++ b/src/test/ui/closure-immutable-outer-variable.nll.stderr
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.rs b/src/test/ui/closure-immutable-outer-variable.rs
index e162678460c..e162678460c 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.rs
+++ b/src/test/ui/closure-immutable-outer-variable.rs
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed b/src/test/ui/closure-immutable-outer-variable.rs.fixed
index 80a5a45a305..80a5a45a305 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed
+++ b/src/test/ui/closure-immutable-outer-variable.rs.fixed
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr b/src/test/ui/closure-immutable-outer-variable.stderr
index 0ee11d8cf15..0ee11d8cf15 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr
+++ b/src/test/ui/closure-immutable-outer-variable.stderr
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.rs b/src/test/ui/confuse-field-and-method/issue-18343.rs
index ef1566ab56a..ef1566ab56a 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.rs
+++ b/src/test/ui/confuse-field-and-method/issue-18343.rs
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr b/src/test/ui/confuse-field-and-method/issue-18343.stderr
index b1e3105a5f9..b1e3105a5f9 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-18343.stderr
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.rs b/src/test/ui/confuse-field-and-method/issue-2392.rs
index f0c5a2a913f..f0c5a2a913f 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.rs
+++ b/src/test/ui/confuse-field-and-method/issue-2392.rs
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr
index 9049ffd4090..9049ffd4090 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.rs b/src/test/ui/confuse-field-and-method/issue-32128.rs
index d306b38e00e..d306b38e00e 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.rs
+++ b/src/test/ui/confuse-field-and-method/issue-32128.rs
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr b/src/test/ui/confuse-field-and-method/issue-32128.stderr
index 95b764b43ed..95b764b43ed 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-32128.stderr
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.rs b/src/test/ui/confuse-field-and-method/issue-33784.rs
index 4cd50be50d4..4cd50be50d4 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.rs
+++ b/src/test/ui/confuse-field-and-method/issue-33784.rs
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr b/src/test/ui/confuse-field-and-method/issue-33784.stderr
index b7f13320eec..b7f13320eec 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr
+++ b/src/test/ui/confuse-field-and-method/issue-33784.stderr
diff --git a/src/test/ui/suggestions/confuse-field-and-method/private-field.rs b/src/test/ui/confuse-field-and-method/private-field.rs
index 4cf939bbed6..4cf939bbed6 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/private-field.rs
+++ b/src/test/ui/confuse-field-and-method/private-field.rs
diff --git a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr b/src/test/ui/confuse-field-and-method/private-field.stderr
index 145df8b156b..145df8b156b 100644
--- a/src/test/ui/suggestions/confuse-field-and-method/private-field.stderr
+++ b/src/test/ui/confuse-field-and-method/private-field.stderr
diff --git a/src/test/ui/suggestions/const-type-mismatch.rs b/src/test/ui/const-type-mismatch.rs
index ddad4e79cfd..ddad4e79cfd 100644
--- a/src/test/ui/suggestions/const-type-mismatch.rs
+++ b/src/test/ui/const-type-mismatch.rs
diff --git a/src/test/ui/suggestions/const-type-mismatch.stderr b/src/test/ui/const-type-mismatch.stderr
index 965995f82c5..965995f82c5 100644
--- a/src/test/ui/suggestions/const-type-mismatch.stderr
+++ b/src/test/ui/const-type-mismatch.stderr
diff --git a/src/test/ui/suggestions/conversion-methods.rs b/src/test/ui/conversion-methods.rs
index 8a53bc3ca93..8a53bc3ca93 100644
--- a/src/test/ui/suggestions/conversion-methods.rs
+++ b/src/test/ui/conversion-methods.rs
diff --git a/src/test/ui/suggestions/conversion-methods.stderr b/src/test/ui/conversion-methods.stderr
index 970ccad2316..970ccad2316 100644
--- a/src/test/ui/suggestions/conversion-methods.stderr
+++ b/src/test/ui/conversion-methods.stderr
diff --git a/src/test/ui/suggestions/dont-suggest-private-trait-method.rs b/src/test/ui/dont-suggest-private-trait-method.rs
index 99bee0d3c59..99bee0d3c59 100644
--- a/src/test/ui/suggestions/dont-suggest-private-trait-method.rs
+++ b/src/test/ui/dont-suggest-private-trait-method.rs
diff --git a/src/test/ui/suggestions/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr
index 81ecc546a6d..81ecc546a6d 100644
--- a/src/test/ui/suggestions/dont-suggest-private-trait-method.stderr
+++ b/src/test/ui/dont-suggest-private-trait-method.stderr
diff --git a/src/test/ui/suggestions/dotdotdot-expr.rs b/src/test/ui/dotdotdot-expr.rs
index afb73a526a8..afb73a526a8 100644
--- a/src/test/ui/suggestions/dotdotdot-expr.rs
+++ b/src/test/ui/dotdotdot-expr.rs
diff --git a/src/test/ui/suggestions/dotdotdot-expr.stderr b/src/test/ui/dotdotdot-expr.stderr
index 3315538f2f7..3315538f2f7 100644
--- a/src/test/ui/suggestions/dotdotdot-expr.stderr
+++ b/src/test/ui/dotdotdot-expr.stderr
diff --git a/src/test/ui/existential_type.nll.stderr b/src/test/ui/existential_type.nll.stderr
new file mode 100644
index 00000000000..90840bf205c
--- /dev/null
+++ b/src/test/ui/existential_type.nll.stderr
@@ -0,0 +1,111 @@
+error: defining existential type use differs from previous
+  --> $DIR/existential_type.rs:23:1
+   |
+LL | / fn bar() -> Foo { //~ ERROR defining existential type use differs from previous
+LL | |     42i32
+LL | | }
+   | |_^
+   |
+note: previous use here
+  --> $DIR/existential_type.rs:19:1
+   |
+LL | / fn foo() -> Foo {
+LL | |     ""
+LL | | }
+   | |_^
+
+error[E0308]: mismatched types
+  --> $DIR/existential_type.rs:36:5
+   |
+LL | fn bomp() -> boo::Boo {
+   |              -------- expected `Boo` because of return type
+LL |     "" //~ ERROR mismatched types
+   |     ^^ expected anonymized type, found reference
+   |
+   = note: expected type `Boo`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/existential_type.rs:50:23
+   |
+LL |         let _: &str = bomp(); //~ ERROR mismatched types
+   |                       ^^^^^^ expected &str, found anonymized type
+   |
+   = note: expected type `&str`
+              found type `Boo`
+
+error[E0308]: mismatched types
+  --> $DIR/existential_type.rs:54:9
+   |
+LL |     fn bomp() -> boo::Boo {
+   |                  -------- expected `Boo` because of return type
+LL |         "" //~ ERROR mismatched types
+   |         ^^ expected anonymized type, found reference
+   |
+   = note: expected type `Boo`
+              found type `&'static str`
+
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/existential_type.rs:61:1
+   |
+LL | existential type Underconstrained<T: Trait>: 'static; //~ ERROR the trait bound `T: Trait`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Trait` bound
+   = note: the return type of a function must have a statically known size
+
+warning: not reporting region error due to nll
+  --> $DIR/existential_type.rs:78:1
+   |
+LL | existential type WrongGeneric<T>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/existential_type.rs:93:27
+   |
+LL |     let _: &'static str = x; //~ mismatched types
+   |                           ^ expected reference, found anonymized type
+   |
+   = note: expected type `&'static str`
+              found type `NoReveal`
+
+error[E0605]: non-primitive cast: `NoReveal` as `&'static str`
+  --> $DIR/existential_type.rs:94:13
+   |
+LL |     let _ = x as &'static str; //~ non-primitive cast
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: could not find defining uses
+  --> $DIR/existential_type.rs:28:1
+   |
+LL | existential type Bar: std::fmt::Debug; //~ ERROR could not find defining uses
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: could not find defining uses
+  --> $DIR/existential_type.rs:32:5
+   |
+LL |     pub existential type Boo: ::std::fmt::Debug; //~ ERROR could not find defining uses
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: defining existential type use differs from previous
+  --> $DIR/existential_type.rs:74:1
+   |
+LL | / fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR defining existential type use differs from previous
+LL | |     Some(t).into_iter()
+LL | | }
+   | |_^
+   |
+note: previous use here
+  --> $DIR/existential_type.rs:70:1
+   |
+LL | / fn my_iter<T>(t: T) -> MyIter<T> {
+LL | |     std::iter::once(t)
+LL | | }
+   | |_^
+
+error: aborting due to 10 previous errors
+
+Some errors occurred: E0277, E0308, E0605.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/existential_type.rs b/src/test/ui/existential_type.rs
new file mode 100644
index 00000000000..6824d362049
--- /dev/null
+++ b/src/test/ui/existential_type.rs
@@ -0,0 +1,95 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![feature(existential_type)]
+
+fn main() {}
+
+// two definitions with different types
+existential type Foo: std::fmt::Debug;
+
+fn foo() -> Foo {
+    ""
+}
+
+fn bar() -> Foo { //~ ERROR defining existential type use differs from previous
+    42i32
+}
+
+// declared but never defined
+existential type Bar: std::fmt::Debug; //~ ERROR could not find defining uses
+
+mod boo {
+    // declared in module but not defined inside of it
+    pub existential type Boo: ::std::fmt::Debug; //~ ERROR could not find defining uses
+}
+
+fn bomp() -> boo::Boo {
+    "" //~ ERROR mismatched types
+}
+
+mod boo2 {
+    mod boo {
+        pub existential type Boo: ::std::fmt::Debug;
+        fn bomp() -> Boo {
+            ""
+        }
+    }
+
+    // don't actually know the type here
+
+    fn bomp2() {
+        let _: &str = bomp(); //~ ERROR mismatched types
+    }
+
+    fn bomp() -> boo::Boo {
+        "" //~ ERROR mismatched types
+    }
+}
+
+// generics
+
+trait Trait {}
+existential type Underconstrained<T: Trait>: 'static; //~ ERROR the trait bound `T: Trait`
+
+// no `Trait` bound
+fn underconstrain<T>(_: T) -> Underconstrained<T> {
+    unimplemented!()
+}
+
+existential type MyIter<T>: Iterator<Item = T>;
+
+fn my_iter<T>(t: T) -> MyIter<T> {
+    std::iter::once(t)
+}
+
+fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR defining existential type use differs from previous
+    Some(t).into_iter()
+}
+
+existential type WrongGeneric<T>: 'static;
+//~^ ERROR the parameter type `T` may not live long enough
+
+fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+    t
+}
+
+// don't reveal the concrete type
+existential type NoReveal: std::fmt::Debug;
+
+fn define_no_reveal() -> NoReveal {
+    ""
+}
+
+fn no_reveal(x: NoReveal) {
+    let _: &'static str = x; //~ mismatched types
+    let _ = x as &'static str; //~ non-primitive cast
+}
diff --git a/src/test/ui/existential_type.stderr b/src/test/ui/existential_type.stderr
new file mode 100644
index 00000000000..3e7476448bf
--- /dev/null
+++ b/src/test/ui/existential_type.stderr
@@ -0,0 +1,120 @@
+error: defining existential type use differs from previous
+  --> $DIR/existential_type.rs:23:1
+   |
+LL | / fn bar() -> Foo { //~ ERROR defining existential type use differs from previous
+LL | |     42i32
+LL | | }
+   | |_^
+   |
+note: previous use here
+  --> $DIR/existential_type.rs:19:1
+   |
+LL | / fn foo() -> Foo {
+LL | |     ""
+LL | | }
+   | |_^
+
+error[E0308]: mismatched types
+  --> $DIR/existential_type.rs:36:5
+   |
+LL | fn bomp() -> boo::Boo {
+   |              -------- expected `Boo` because of return type
+LL |     "" //~ ERROR mismatched types
+   |     ^^ expected anonymized type, found reference
+   |
+   = note: expected type `Boo`
+              found type `&'static str`
+
+error[E0308]: mismatched types
+  --> $DIR/existential_type.rs:50:23
+   |
+LL |         let _: &str = bomp(); //~ ERROR mismatched types
+   |                       ^^^^^^ expected &str, found anonymized type
+   |
+   = note: expected type `&str`
+              found type `Boo`
+
+error[E0308]: mismatched types
+  --> $DIR/existential_type.rs:54:9
+   |
+LL |     fn bomp() -> boo::Boo {
+   |                  -------- expected `Boo` because of return type
+LL |         "" //~ ERROR mismatched types
+   |         ^^ expected anonymized type, found reference
+   |
+   = note: expected type `Boo`
+              found type `&'static str`
+
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/existential_type.rs:61:1
+   |
+LL | existential type Underconstrained<T: Trait>: 'static; //~ ERROR the trait bound `T: Trait`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
+   |
+   = help: consider adding a `where T: Trait` bound
+   = note: the return type of a function must have a statically known size
+
+error[E0310]: the parameter type `T` may not live long enough
+  --> $DIR/existential_type.rs:78:1
+   |
+LL | existential type WrongGeneric<T>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
+   |                  - help: consider adding an explicit lifetime bound `T: 'static`...
+   |
+note: ...so that the type `T` will meet its required lifetime bounds
+  --> $DIR/existential_type.rs:78:1
+   |
+LL | existential type WrongGeneric<T>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/existential_type.rs:93:27
+   |
+LL |     let _: &'static str = x; //~ mismatched types
+   |                           ^ expected reference, found anonymized type
+   |
+   = note: expected type `&'static str`
+              found type `NoReveal`
+
+error[E0605]: non-primitive cast: `NoReveal` as `&'static str`
+  --> $DIR/existential_type.rs:94:13
+   |
+LL |     let _ = x as &'static str; //~ non-primitive cast
+   |             ^^^^^^^^^^^^^^^^^
+   |
+   = note: an `as` expression can only be used to convert between primitive types. Consider using the `From` trait
+
+error: could not find defining uses
+  --> $DIR/existential_type.rs:28:1
+   |
+LL | existential type Bar: std::fmt::Debug; //~ ERROR could not find defining uses
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: could not find defining uses
+  --> $DIR/existential_type.rs:32:5
+   |
+LL |     pub existential type Boo: ::std::fmt::Debug; //~ ERROR could not find defining uses
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: defining existential type use differs from previous
+  --> $DIR/existential_type.rs:74:1
+   |
+LL | / fn my_iter2<T>(t: T) -> MyIter<T> { //~ ERROR defining existential type use differs from previous
+LL | |     Some(t).into_iter()
+LL | | }
+   | |_^
+   |
+note: previous use here
+  --> $DIR/existential_type.rs:70:1
+   |
+LL | / fn my_iter<T>(t: T) -> MyIter<T> {
+LL | |     std::iter::once(t)
+LL | | }
+   | |_^
+
+error: aborting due to 11 previous errors
+
+Some errors occurred: E0277, E0308, E0310, E0605.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/existential_type2.rs b/src/test/ui/existential_type2.rs
new file mode 100644
index 00000000000..bffb6b5ee10
--- /dev/null
+++ b/src/test/ui/existential_type2.rs
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![feature(existential_type)]
+
+fn main() {}
+
+existential type Underconstrained<T: std::fmt::Debug>: 'static;
+//~^ ERROR `U` doesn't implement `std::fmt::Debug`
+
+// not a defining use, because it doesn't define *all* possible generics
+fn underconstrained<U>(_: U) -> Underconstrained<U> {
+    5u32
+}
+
+existential type Underconstrained2<T: std::fmt::Debug>: 'static;
+//~^ ERROR `V` doesn't implement `std::fmt::Debug`
+
+// not a defining use, because it doesn't define *all* possible generics
+fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
+    5u32
+}
diff --git a/src/test/ui/existential_type2.stderr b/src/test/ui/existential_type2.stderr
new file mode 100644
index 00000000000..53003a4f05d
--- /dev/null
+++ b/src/test/ui/existential_type2.stderr
@@ -0,0 +1,23 @@
+error[E0277]: `U` doesn't implement `std::fmt::Debug`
+  --> $DIR/existential_type2.rs:16:1
+   |
+LL | existential type Underconstrained<T: std::fmt::Debug>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `U`
+   = help: consider adding a `where U: std::fmt::Debug` bound
+   = note: the return type of a function must have a statically known size
+
+error[E0277]: `V` doesn't implement `std::fmt::Debug`
+  --> $DIR/existential_type2.rs:24:1
+   |
+LL | existential type Underconstrained2<T: std::fmt::Debug>: 'static;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug`
+   |
+   = help: the trait `std::fmt::Debug` is not implemented for `V`
+   = help: consider adding a `where V: std::fmt::Debug` bound
+   = note: the return type of a function must have a statically known size
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/existential_type3.rs b/src/test/ui/existential_type3.rs
new file mode 100644
index 00000000000..b090cf26b87
--- /dev/null
+++ b/src/test/ui/existential_type3.rs
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+#![feature(existential_type)]
+
+fn main() {}
+
+existential type WrongGeneric<T: 'static>: 'static;
+
+fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
+//~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
+    v
+}
diff --git a/src/test/ui/existential_type3.stderr b/src/test/ui/existential_type3.stderr
new file mode 100644
index 00000000000..90800728d7c
--- /dev/null
+++ b/src/test/ui/existential_type3.stderr
@@ -0,0 +1,12 @@
+error: type parameter `V` is part of concrete type but not used in parameter list for existential type
+  --> $DIR/existential_type3.rs:18:73
+   |
+LL |   fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
+   |  _________________________________________________________________________^
+LL | | //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
+LL | |     v
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed b/src/test/ui/existential_type4.rs
index e162678460c..a4b74d6751b 100644
--- a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed
+++ b/src/test/ui/existential_type4.rs
@@ -1,4 +1,4 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,15 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// run-rustfix
 
-// Point at the captured immutable outer variable
+#![feature(existential_type)]
 
-fn foo(mut f: Box<FnMut()>) {
-    f();
-}
+fn main() {}
+
+existential type Cmp<T>: 'static;
 
-fn main() {
-    let y = true;
-    foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable
+// not a defining use, because it doesn't define *all* possible generics
+fn cmp() -> Cmp<u32> { //~ ERROR non-defining existential type use in defining scope
+    5u32
 }
diff --git a/src/test/ui/existential_type4.stderr b/src/test/ui/existential_type4.stderr
new file mode 100644
index 00000000000..b11988746ea
--- /dev/null
+++ b/src/test/ui/existential_type4.stderr
@@ -0,0 +1,16 @@
+error: non-defining existential type use in defining scope
+  --> $DIR/existential_type4.rs:19:1
+   |
+LL | / fn cmp() -> Cmp<u32> { //~ ERROR non-defining existential type use in defining scope
+LL | |     5u32
+LL | | }
+   | |_^
+   |
+note: used non-generic type u32 for generic parameter
+  --> $DIR/existential_type4.rs:16:22
+   |
+LL | existential type Cmp<T>: 'static;
+   |                      ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/suggestions/extern-crate-rename.rs b/src/test/ui/extern-crate-rename.rs
index b58149fb0b8..b58149fb0b8 100644
--- a/src/test/ui/suggestions/extern-crate-rename.rs
+++ b/src/test/ui/extern-crate-rename.rs
diff --git a/src/test/ui/suggestions/extern-crate-rename.stderr b/src/test/ui/extern-crate-rename.stderr
index 2c2723fe4c5..2c2723fe4c5 100644
--- a/src/test/ui/suggestions/extern-crate-rename.stderr
+++ b/src/test/ui/extern-crate-rename.stderr
diff --git a/src/test/ui/feature-gate-existential-type.rs b/src/test/ui/feature-gate-existential-type.rs
new file mode 100644
index 00000000000..b35a3916377
--- /dev/null
+++ b/src/test/ui/feature-gate-existential-type.rs
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that existential types must be ungated to use the `existential` keyword
+
+
+
+existential type Foo: std::fmt::Debug; //~ ERROR existential types are unstable
+
+trait Bar {
+    type Baa: std::fmt::Debug;
+}
+
+impl Bar for () {
+    existential type Baa: std::fmt::Debug; //~ ERROR existential types are unstable
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gate-existential-type.stderr b/src/test/ui/feature-gate-existential-type.stderr
new file mode 100644
index 00000000000..6db5fa2ce6b
--- /dev/null
+++ b/src/test/ui/feature-gate-existential-type.stderr
@@ -0,0 +1,19 @@
+error[E0658]: existential types are unstable (see issue #34511)
+  --> $DIR/feature-gate-existential-type.rs:15:1
+   |
+LL | existential type Foo: std::fmt::Debug; //~ ERROR existential types are unstable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(existential_type)] to the crate attributes to enable
+
+error[E0658]: existential types are unstable (see issue #34511)
+  --> $DIR/feature-gate-existential-type.rs:22:5
+   |
+LL |     existential type Baa: std::fmt::Debug; //~ ERROR existential types are unstable
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(existential_type)] to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr b/src/test/ui/fn-closure-mutable-capture.nll.stderr
index 7ef21d3720d..7ef21d3720d 100644
--- a/src/test/ui/suggestions/fn-closure-mutable-capture.nll.stderr
+++ b/src/test/ui/fn-closure-mutable-capture.nll.stderr
diff --git a/src/test/ui/suggestions/fn-closure-mutable-capture.rs b/src/test/ui/fn-closure-mutable-capture.rs
index 385efebd590..385efebd590 100644
--- a/src/test/ui/suggestions/fn-closure-mutable-capture.rs
+++ b/src/test/ui/fn-closure-mutable-capture.rs
diff --git a/src/test/ui/suggestions/fn-closure-mutable-capture.stderr b/src/test/ui/fn-closure-mutable-capture.stderr
index a58d663dc0a..a58d663dc0a 100644
--- a/src/test/ui/suggestions/fn-closure-mutable-capture.stderr
+++ b/src/test/ui/fn-closure-mutable-capture.stderr
diff --git a/src/test/ui/suggestions/for-c-in-str.rs b/src/test/ui/for-c-in-str.rs
index 011886e8073..011886e8073 100644
--- a/src/test/ui/suggestions/for-c-in-str.rs
+++ b/src/test/ui/for-c-in-str.rs
diff --git a/src/test/ui/suggestions/for-c-in-str.stderr b/src/test/ui/for-c-in-str.stderr
index b249df3b4ef..b249df3b4ef 100644
--- a/src/test/ui/suggestions/for-c-in-str.stderr
+++ b/src/test/ui/for-c-in-str.stderr
diff --git a/src/test/ui/suggestions/issue-32354-suggest-import-rename.fixed b/src/test/ui/issue-32354-suggest-import-rename.fixed
index 251f7eb9a24..251f7eb9a24 100644
--- a/src/test/ui/suggestions/issue-32354-suggest-import-rename.fixed
+++ b/src/test/ui/issue-32354-suggest-import-rename.fixed
diff --git a/src/test/ui/suggestions/issue-32354-suggest-import-rename.rs b/src/test/ui/issue-32354-suggest-import-rename.rs
index 57cbeb47a1e..57cbeb47a1e 100644
--- a/src/test/ui/suggestions/issue-32354-suggest-import-rename.rs
+++ b/src/test/ui/issue-32354-suggest-import-rename.rs
diff --git a/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr b/src/test/ui/issue-32354-suggest-import-rename.stderr
index f45a5f7dd61..f45a5f7dd61 100644
--- a/src/test/ui/suggestions/issue-32354-suggest-import-rename.stderr
+++ b/src/test/ui/issue-32354-suggest-import-rename.stderr
diff --git a/src/test/ui/suggestions/issue-43420-no-over-suggest.rs b/src/test/ui/issue-43420-no-over-suggest.rs
index 8c5bde45bae..8c5bde45bae 100644
--- a/src/test/ui/suggestions/issue-43420-no-over-suggest.rs
+++ b/src/test/ui/issue-43420-no-over-suggest.rs
diff --git a/src/test/ui/suggestions/issue-43420-no-over-suggest.stderr b/src/test/ui/issue-43420-no-over-suggest.stderr
index 80bbdd11289..80bbdd11289 100644
--- a/src/test/ui/suggestions/issue-43420-no-over-suggest.stderr
+++ b/src/test/ui/issue-43420-no-over-suggest.stderr
diff --git a/src/test/ui/suggestions/issue-45562.fixed b/src/test/ui/issue-45562.fixed
index 7c01f0d1ee5..7c01f0d1ee5 100644
--- a/src/test/ui/suggestions/issue-45562.fixed
+++ b/src/test/ui/issue-45562.fixed
diff --git a/src/test/ui/suggestions/issue-45562.rs b/src/test/ui/issue-45562.rs
index c27d52fcdd3..c27d52fcdd3 100644
--- a/src/test/ui/suggestions/issue-45562.rs
+++ b/src/test/ui/issue-45562.rs
diff --git a/src/test/ui/suggestions/issue-45562.stderr b/src/test/ui/issue-45562.stderr
index d9e624cadc7..d9e624cadc7 100644
--- a/src/test/ui/suggestions/issue-45562.stderr
+++ b/src/test/ui/issue-45562.stderr
diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
index e3287030408..e3287030408 100644
--- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
+++ b/src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
index f47ea474d51..f47ea474d51 100644
--- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
+++ b/src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
index ecdfec2b3bf..ecdfec2b3bf 100644
--- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
+++ b/src/test/ui/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
diff --git a/src/test/ui/suggestions/issue-46302.rs b/src/test/ui/issue-46302.rs
index 6ae6b549b07..6ae6b549b07 100644
--- a/src/test/ui/suggestions/issue-46302.rs
+++ b/src/test/ui/issue-46302.rs
diff --git a/src/test/ui/suggestions/issue-46302.stderr b/src/test/ui/issue-46302.stderr
index 8e399136fad..8e399136fad 100644
--- a/src/test/ui/suggestions/issue-46302.stderr
+++ b/src/test/ui/issue-46302.stderr
diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.fixed
index 77171cad6e7..77171cad6e7 100644
--- a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed
+++ b/src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.fixed
diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs b/src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.rs
index e5ea9b5ed09..e5ea9b5ed09 100644
--- a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs
+++ b/src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.rs
diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr b/src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.stderr
index 9c492751ca1..9c492751ca1 100644
--- a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr
+++ b/src/test/ui/issue-46756-consider-borrowing-cast-or-binexpr.stderr
diff --git a/src/test/ui/suggestions/issue-48364.rs b/src/test/ui/issue-48364.rs
index 82cb722a656..82cb722a656 100644
--- a/src/test/ui/suggestions/issue-48364.rs
+++ b/src/test/ui/issue-48364.rs
diff --git a/src/test/ui/suggestions/issue-48364.stderr b/src/test/ui/issue-48364.stderr
index b420654a32d..b420654a32d 100644
--- a/src/test/ui/suggestions/issue-48364.stderr
+++ b/src/test/ui/issue-48364.stderr
diff --git a/src/test/ui/suggestions/issue-51244.nll.stderr b/src/test/ui/issue-51244.nll.stderr
index ce02ae2aec2..ce02ae2aec2 100644
--- a/src/test/ui/suggestions/issue-51244.nll.stderr
+++ b/src/test/ui/issue-51244.nll.stderr
diff --git a/src/test/ui/suggestions/issue-51244.rs b/src/test/ui/issue-51244.rs
index 50a21184a98..50a21184a98 100644
--- a/src/test/ui/suggestions/issue-51244.rs
+++ b/src/test/ui/issue-51244.rs
diff --git a/src/test/ui/suggestions/issue-51244.stderr b/src/test/ui/issue-51244.stderr
index 997a74295e5..997a74295e5 100644
--- a/src/test/ui/suggestions/issue-51244.stderr
+++ b/src/test/ui/issue-51244.stderr
diff --git a/src/test/ui/suggestions/issue-51515.rs b/src/test/ui/issue-51515.rs
index 3e0a3b757a3..3e0a3b757a3 100644
--- a/src/test/ui/suggestions/issue-51515.rs
+++ b/src/test/ui/issue-51515.rs
diff --git a/src/test/ui/suggestions/issue-51515.stderr b/src/test/ui/issue-51515.stderr
index 3e7349b5aca..3e7349b5aca 100644
--- a/src/test/ui/suggestions/issue-51515.stderr
+++ b/src/test/ui/issue-51515.stderr
diff --git a/src/test/ui/suggestions/issue-52049.nll.stderr b/src/test/ui/issue-52049.nll.stderr
index 6f71f167611..6f71f167611 100644
--- a/src/test/ui/suggestions/issue-52049.nll.stderr
+++ b/src/test/ui/issue-52049.nll.stderr
diff --git a/src/test/ui/suggestions/issue-52049.rs b/src/test/ui/issue-52049.rs
index daff2258d36..daff2258d36 100644
--- a/src/test/ui/suggestions/issue-52049.rs
+++ b/src/test/ui/issue-52049.rs
diff --git a/src/test/ui/suggestions/issue-52049.stderr b/src/test/ui/issue-52049.stderr
index e1e501023fc..e1e501023fc 100644
--- a/src/test/ui/suggestions/issue-52049.stderr
+++ b/src/test/ui/issue-52049.stderr
diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs b/src/test/ui/method-on-ambiguous-numeric-type.rs
index 2b6e830ec59..2b6e830ec59 100644
--- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.rs
+++ b/src/test/ui/method-on-ambiguous-numeric-type.rs
diff --git a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr b/src/test/ui/method-on-ambiguous-numeric-type.stderr
index 796520e0ec7..796520e0ec7 100644
--- a/src/test/ui/suggestions/method-on-ambiguous-numeric-type.stderr
+++ b/src/test/ui/method-on-ambiguous-numeric-type.stderr
diff --git a/src/test/ui/suggestions/missing-comma-in-match.fixed b/src/test/ui/missing-comma-in-match.fixed
index 4832f35f42d..4832f35f42d 100644
--- a/src/test/ui/suggestions/missing-comma-in-match.fixed
+++ b/src/test/ui/missing-comma-in-match.fixed
diff --git a/src/test/ui/suggestions/missing-comma-in-match.rs b/src/test/ui/missing-comma-in-match.rs
index e39b20e77ea..e39b20e77ea 100644
--- a/src/test/ui/suggestions/missing-comma-in-match.rs
+++ b/src/test/ui/missing-comma-in-match.rs
diff --git a/src/test/ui/suggestions/missing-comma-in-match.stderr b/src/test/ui/missing-comma-in-match.stderr
index 77935934107..77935934107 100644
--- a/src/test/ui/suggestions/missing-comma-in-match.stderr
+++ b/src/test/ui/missing-comma-in-match.stderr
diff --git a/src/test/ui/suggestions/numeric-cast-2.rs b/src/test/ui/numeric-cast-2.rs
index 2092b6bce37..2092b6bce37 100644
--- a/src/test/ui/suggestions/numeric-cast-2.rs
+++ b/src/test/ui/numeric-cast-2.rs
diff --git a/src/test/ui/suggestions/numeric-cast-2.stderr b/src/test/ui/numeric-cast-2.stderr
index 3d485583717..3d485583717 100644
--- a/src/test/ui/suggestions/numeric-cast-2.stderr
+++ b/src/test/ui/numeric-cast-2.stderr
diff --git a/src/test/ui/suggestions/numeric-cast.rs b/src/test/ui/numeric-cast.rs
index 69bfdfa94b1..69bfdfa94b1 100644
--- a/src/test/ui/suggestions/numeric-cast.rs
+++ b/src/test/ui/numeric-cast.rs
diff --git a/src/test/ui/suggestions/numeric-cast.stderr b/src/test/ui/numeric-cast.stderr
index 4aac65ff4cb..4aac65ff4cb 100644
--- a/src/test/ui/suggestions/numeric-cast.stderr
+++ b/src/test/ui/numeric-cast.stderr
diff --git a/src/test/ui/suggestions/placement-syntax.rs b/src/test/ui/placement-syntax.rs
index 39252597a23..39252597a23 100644
--- a/src/test/ui/suggestions/placement-syntax.rs
+++ b/src/test/ui/placement-syntax.rs
diff --git a/src/test/ui/suggestions/placement-syntax.stderr b/src/test/ui/placement-syntax.stderr
index 933ba96519c..933ba96519c 100644
--- a/src/test/ui/suggestions/placement-syntax.stderr
+++ b/src/test/ui/placement-syntax.stderr
diff --git a/src/test/ui/suggestions/pub-ident-fn-2.rs b/src/test/ui/pub-ident-fn-2.rs
index 44884bfcdfd..44884bfcdfd 100644
--- a/src/test/ui/suggestions/pub-ident-fn-2.rs
+++ b/src/test/ui/pub-ident-fn-2.rs
diff --git a/src/test/ui/suggestions/pub-ident-fn-2.stderr b/src/test/ui/pub-ident-fn-2.stderr
index bbbb3df8769..bbbb3df8769 100644
--- a/src/test/ui/suggestions/pub-ident-fn-2.stderr
+++ b/src/test/ui/pub-ident-fn-2.stderr
diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct-2.rs b/src/test/ui/pub-ident-fn-or-struct-2.rs
index 1ccadc8a40b..1ccadc8a40b 100644
--- a/src/test/ui/suggestions/pub-ident-fn-or-struct-2.rs
+++ b/src/test/ui/pub-ident-fn-or-struct-2.rs
diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr b/src/test/ui/pub-ident-fn-or-struct-2.stderr
index e492a8c4756..e492a8c4756 100644
--- a/src/test/ui/suggestions/pub-ident-fn-or-struct-2.stderr
+++ b/src/test/ui/pub-ident-fn-or-struct-2.stderr
diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct.rs b/src/test/ui/pub-ident-fn-or-struct.rs
index 0664918945b..0664918945b 100644
--- a/src/test/ui/suggestions/pub-ident-fn-or-struct.rs
+++ b/src/test/ui/pub-ident-fn-or-struct.rs
diff --git a/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr b/src/test/ui/pub-ident-fn-or-struct.stderr
index c1bff34cec3..c1bff34cec3 100644
--- a/src/test/ui/suggestions/pub-ident-fn-or-struct.stderr
+++ b/src/test/ui/pub-ident-fn-or-struct.stderr
diff --git a/src/test/ui/suggestions/pub-ident-fn.fixed b/src/test/ui/pub-ident-fn.fixed
index f2d0c6c3e1d..f2d0c6c3e1d 100644
--- a/src/test/ui/suggestions/pub-ident-fn.fixed
+++ b/src/test/ui/pub-ident-fn.fixed
diff --git a/src/test/ui/suggestions/pub-ident-fn.rs b/src/test/ui/pub-ident-fn.rs
index 82c32f57eea..82c32f57eea 100644
--- a/src/test/ui/suggestions/pub-ident-fn.rs
+++ b/src/test/ui/pub-ident-fn.rs
diff --git a/src/test/ui/suggestions/pub-ident-fn.stderr b/src/test/ui/pub-ident-fn.stderr
index f7c96b8b9f4..f7c96b8b9f4 100644
--- a/src/test/ui/suggestions/pub-ident-fn.stderr
+++ b/src/test/ui/pub-ident-fn.stderr
diff --git a/src/test/ui/suggestions/pub-ident-struct.rs b/src/test/ui/pub-ident-struct.rs
index d08d498f87a..d08d498f87a 100644
--- a/src/test/ui/suggestions/pub-ident-struct.rs
+++ b/src/test/ui/pub-ident-struct.rs
diff --git a/src/test/ui/suggestions/pub-ident-struct.stderr b/src/test/ui/pub-ident-struct.stderr
index cd53cea7212..cd53cea7212 100644
--- a/src/test/ui/suggestions/pub-ident-struct.stderr
+++ b/src/test/ui/pub-ident-struct.stderr
diff --git a/src/test/ui/suggestions/removing-extern-crate.fixed b/src/test/ui/removing-extern-crate.fixed
index 83b35cec809..83b35cec809 100644
--- a/src/test/ui/suggestions/removing-extern-crate.fixed
+++ b/src/test/ui/removing-extern-crate.fixed
diff --git a/src/test/ui/suggestions/removing-extern-crate.rs b/src/test/ui/removing-extern-crate.rs
index 29479086460..29479086460 100644
--- a/src/test/ui/suggestions/removing-extern-crate.rs
+++ b/src/test/ui/removing-extern-crate.rs
diff --git a/src/test/ui/suggestions/removing-extern-crate.stderr b/src/test/ui/removing-extern-crate.stderr
index f2eed27a266..f2eed27a266 100644
--- a/src/test/ui/suggestions/removing-extern-crate.stderr
+++ b/src/test/ui/removing-extern-crate.stderr
diff --git a/src/test/ui/suggestions/repr.rs b/src/test/ui/repr.rs
index 312f60202c6..312f60202c6 100644
--- a/src/test/ui/suggestions/repr.rs
+++ b/src/test/ui/repr.rs
diff --git a/src/test/ui/suggestions/repr.stderr b/src/test/ui/repr.stderr
index 7a99d8c0448..7a99d8c0448 100644
--- a/src/test/ui/suggestions/repr.stderr
+++ b/src/test/ui/repr.stderr
diff --git a/src/test/ui/suggestions/return-type.rs b/src/test/ui/return-type.rs
index e63787949a4..e63787949a4 100644
--- a/src/test/ui/suggestions/return-type.rs
+++ b/src/test/ui/return-type.rs
diff --git a/src/test/ui/suggestions/return-type.stderr b/src/test/ui/return-type.stderr
index 7d7653eee28..7d7653eee28 100644
--- a/src/test/ui/suggestions/return-type.stderr
+++ b/src/test/ui/return-type.stderr
diff --git a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
index 3dd2675646c..6d18075ba37 100644
--- a/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
+++ b/src/test/ui/single-use-lifetime/one-use-in-fn-argument-in-band.stderr
@@ -1,11 +1,11 @@
-error: lifetime parameter `'b` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:19:22
+error: lifetime parameter `'a` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:19:10
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |                      ^^
-   |                      |
-   |                      this lifetime...
-   |                      ...is used only here
+   |          ^^
+   |          |
+   |          this lifetime...
+   |          ...is used only here
    |
 note: lint level defined here
   --> $DIR/one-use-in-fn-argument-in-band.rs:12:9
@@ -13,14 +13,14 @@ note: lint level defined here
 LL | #![deny(single_use_lifetimes)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: lifetime parameter `'a` only used once
-  --> $DIR/one-use-in-fn-argument-in-band.rs:19:10
+error: lifetime parameter `'b` only used once
+  --> $DIR/one-use-in-fn-argument-in-band.rs:19:22
    |
 LL | fn a(x: &'a u32, y: &'b u32) {
-   |          ^^
-   |          |
-   |          this lifetime...
-   |          ...is used only here
+   |                      ^^
+   |                      |
+   |                      this lifetime...
+   |                      ...is used only here
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/str-array-assignment.rs b/src/test/ui/str-array-assignment.rs
index 9d6cf5fe598..9d6cf5fe598 100644
--- a/src/test/ui/suggestions/str-array-assignment.rs
+++ b/src/test/ui/str-array-assignment.rs
diff --git a/src/test/ui/suggestions/str-array-assignment.stderr b/src/test/ui/str-array-assignment.stderr
index 7a774cab38e..7a774cab38e 100644
--- a/src/test/ui/suggestions/str-array-assignment.stderr
+++ b/src/test/ui/str-array-assignment.stderr
diff --git a/src/test/ui/suggestions/str-as-char.fixed b/src/test/ui/str-as-char.fixed
index c0dad38e436..c0dad38e436 100644
--- a/src/test/ui/suggestions/str-as-char.fixed
+++ b/src/test/ui/str-as-char.fixed
diff --git a/src/test/ui/suggestions/str-as-char.rs b/src/test/ui/str-as-char.rs
index b5a5df0af7f..b5a5df0af7f 100644
--- a/src/test/ui/suggestions/str-as-char.rs
+++ b/src/test/ui/str-as-char.rs
diff --git a/src/test/ui/suggestions/str-as-char.stderr b/src/test/ui/str-as-char.stderr
index 60eb182adf1..60eb182adf1 100644
--- a/src/test/ui/suggestions/str-as-char.stderr
+++ b/src/test/ui/str-as-char.stderr
diff --git a/src/test/ui/suggestions/suggest-labels.rs b/src/test/ui/suggest-labels.rs
index 9fb519c57ed..9fb519c57ed 100644
--- a/src/test/ui/suggestions/suggest-labels.rs
+++ b/src/test/ui/suggest-labels.rs
diff --git a/src/test/ui/suggestions/suggest-labels.stderr b/src/test/ui/suggest-labels.stderr
index 671ff1a56db..671ff1a56db 100644
--- a/src/test/ui/suggestions/suggest-labels.stderr
+++ b/src/test/ui/suggest-labels.stderr
diff --git a/src/test/ui/suggestions/suggest-methods.rs b/src/test/ui/suggest-methods.rs
index 49027deecc1..49027deecc1 100644
--- a/src/test/ui/suggestions/suggest-methods.rs
+++ b/src/test/ui/suggest-methods.rs
diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggest-methods.stderr
index cb352361f33..cb352361f33 100644
--- a/src/test/ui/suggestions/suggest-methods.stderr
+++ b/src/test/ui/suggest-methods.stderr
diff --git a/src/test/ui/suggestions/suggest-ref-mut.rs b/src/test/ui/suggest-ref-mut.rs
index 30b5371af1a..30b5371af1a 100644
--- a/src/test/ui/suggestions/suggest-ref-mut.rs
+++ b/src/test/ui/suggest-ref-mut.rs
diff --git a/src/test/ui/suggestions/suggest-ref-mut.stderr b/src/test/ui/suggest-ref-mut.stderr
index 0b2b240ef53..0b2b240ef53 100644
--- a/src/test/ui/suggestions/suggest-ref-mut.stderr
+++ b/src/test/ui/suggest-ref-mut.stderr
diff --git a/src/test/ui/token/issue-41155.stderr b/src/test/ui/token/issue-41155.stderr
index 84dbc7ffc2f..5c1aae29c2f 100644
--- a/src/test/ui/token/issue-41155.stderr
+++ b/src/test/ui/token/issue-41155.stderr
@@ -1,8 +1,8 @@
-error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found `}`
+error: expected one of `(`, `async`, `const`, `default`, `existential`, `extern`, `fn`, `type`, or `unsafe`, found `}`
   --> $DIR/issue-41155.rs:13:1
    |
 LL |     pub
-   |        - expected one of 8 possible tokens here
+   |        - expected one of 9 possible tokens here
 LL | } //~ ERROR expected one of
    | ^ unexpected token
 
diff --git a/src/test/ui/suggestions/try-on-option.rs b/src/test/ui/try-on-option.rs
index 65ca23402d2..65ca23402d2 100644
--- a/src/test/ui/suggestions/try-on-option.rs
+++ b/src/test/ui/try-on-option.rs
diff --git a/src/test/ui/suggestions/try-on-option.stderr b/src/test/ui/try-on-option.stderr
index 265ee593bb7..265ee593bb7 100644
--- a/src/test/ui/suggestions/try-on-option.stderr
+++ b/src/test/ui/try-on-option.stderr
diff --git a/src/test/ui/suggestions/try-operator-on-main.rs b/src/test/ui/try-operator-on-main.rs
index e52ef45c2ec..e52ef45c2ec 100644
--- a/src/test/ui/suggestions/try-operator-on-main.rs
+++ b/src/test/ui/try-operator-on-main.rs
diff --git a/src/test/ui/suggestions/try-operator-on-main.stderr b/src/test/ui/try-operator-on-main.stderr
index 121ae14f999..121ae14f999 100644
--- a/src/test/ui/suggestions/try-operator-on-main.stderr
+++ b/src/test/ui/try-operator-on-main.stderr
diff --git a/src/test/ui/suggestions/tuple-float-index.fixed b/src/test/ui/tuple-float-index.fixed
index 55bc2f77dad..55bc2f77dad 100644
--- a/src/test/ui/suggestions/tuple-float-index.fixed
+++ b/src/test/ui/tuple-float-index.fixed
diff --git a/src/test/ui/suggestions/tuple-float-index.rs b/src/test/ui/tuple-float-index.rs
index d569ca4cb86..d569ca4cb86 100644
--- a/src/test/ui/suggestions/tuple-float-index.rs
+++ b/src/test/ui/tuple-float-index.rs
diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/tuple-float-index.stderr
index 15af0834f03..15af0834f03 100644
--- a/src/test/ui/suggestions/tuple-float-index.stderr
+++ b/src/test/ui/tuple-float-index.stderr
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-initializer.rs b/src/test/ui/type-ascription-instead-of-initializer.rs
index d80dad8fbd4..d80dad8fbd4 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-initializer.rs
+++ b/src/test/ui/type-ascription-instead-of-initializer.rs
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr b/src/test/ui/type-ascription-instead-of-initializer.stderr
index 3722d2a0e3f..3722d2a0e3f 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-initializer.stderr
+++ b/src/test/ui/type-ascription-instead-of-initializer.stderr
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-statement-end.rs b/src/test/ui/type-ascription-instead-of-statement-end.rs
index 01d773dd5e1..01d773dd5e1 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-statement-end.rs
+++ b/src/test/ui/type-ascription-instead-of-statement-end.rs
diff --git a/src/test/ui/suggestions/type-ascription-instead-of-statement-end.stderr b/src/test/ui/type-ascription-instead-of-statement-end.stderr
index 314c9060d4f..314c9060d4f 100644
--- a/src/test/ui/suggestions/type-ascription-instead-of-statement-end.stderr
+++ b/src/test/ui/type-ascription-instead-of-statement-end.stderr
diff --git a/src/test/ui/suggestions/type-ascription-with-fn-call.rs b/src/test/ui/type-ascription-with-fn-call.rs
index b2c25c37e8e..b2c25c37e8e 100644
--- a/src/test/ui/suggestions/type-ascription-with-fn-call.rs
+++ b/src/test/ui/type-ascription-with-fn-call.rs
diff --git a/src/test/ui/suggestions/type-ascription-with-fn-call.stderr b/src/test/ui/type-ascription-with-fn-call.stderr
index 78df97139b6..78df97139b6 100644
--- a/src/test/ui/suggestions/type-ascription-with-fn-call.stderr
+++ b/src/test/ui/type-ascription-with-fn-call.stderr