diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h
index f57f390143a12..bb83a245859b1 100644
--- a/include/swift/AST/ASTContext.h
+++ b/include/swift/AST/ASTContext.h
@@ -531,7 +531,7 @@ class ASTContext final {
 
   /// Retrieve the declaration of Swift.Error.
   ProtocolDecl *getErrorDecl() const;
-  CanType getExceptionType() const;
+  CanType getErrorExistentialType() const;
   
 #define KNOWN_STDLIB_TYPE_DECL(NAME, DECL_CLASS, NUM_GENERIC_PARAMS) \
   /** Retrieve the declaration of Swift.NAME. */ \
diff --git a/include/swift/AST/ASTDemangler.h b/include/swift/AST/ASTDemangler.h
index 76c90f017c9a5..8e4100d77396e 100644
--- a/include/swift/AST/ASTDemangler.h
+++ b/include/swift/AST/ASTDemangler.h
@@ -66,7 +66,7 @@ class ASTBuilder {
 
   Demangle::NodeFactory &getNodeFactory() { return Factory; }
 
-  Type decodeMangledType(NodePointer node);
+  Type decodeMangledType(NodePointer node, bool forRequirement = true);
   Type createBuiltinType(StringRef builtinName, StringRef mangledName);
 
   TypeDecl *createTypeDecl(NodePointer node);
@@ -109,7 +109,8 @@ class ASTBuilder {
 
   Type createProtocolCompositionType(ArrayRef<ProtocolDecl *> protocols,
                                      Type superclass,
-                                     bool isClassBound);
+                                     bool isClassBound,
+                                     bool forRequirement = true);
 
   Type createExistentialMetatypeType(Type instance,
                      Optional<Demangle::ImplMetatypeRepresentation> repr=None);
diff --git a/include/swift/AST/ASTSynthesis.h b/include/swift/AST/ASTSynthesis.h
index 7ea55cf8c028f..6437e6a1cee5b 100644
--- a/include/swift/AST/ASTSynthesis.h
+++ b/include/swift/AST/ASTSynthesis.h
@@ -56,7 +56,7 @@ inline Type synthesizeType(SynthesisContext &SC,
   switch (kind) {
   case _any: return SC.Context.TheAnyType;
   case _bridgeObject: return SC.Context.TheBridgeObjectType;
-  case _error: return SC.Context.getExceptionType();
+  case _error: return SC.Context.getErrorExistentialType();
   case _executor: return SC.Context.TheExecutorType;
   case _job: return SC.Context.TheJobType;
   case _nativeObject: return SC.Context.TheNativeObjectType;
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index ff6fe4e2225b5..8ca2157cda0d3 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -4363,6 +4363,11 @@ class ProtocolDecl final : public NominalTypeDecl {
   /// not exist.
   AssociatedTypeDecl *getAssociatedType(Identifier name) const;
 
+  /// Returns the existential type for this protocol.
+  Type getExistentialType() const {
+    return ExistentialType::get(getDeclaredInterfaceType());
+  }
+
   /// Walk this protocol and all of the protocols inherited by this protocol,
   /// transitively, invoking the callback function for each protocol.
   ///
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 63dbe7f1ea7d8..4987a8a41fa7f 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -2441,8 +2441,8 @@ ERROR(protocol_composition_one_class,none,
       "contains class %1", (Type, Type))
 
 ERROR(requires_conformance_nonprotocol,none,
-      "type %0 constrained to non-protocol, non-class type %1",
-      (Type, Type))
+      "type %0 constrained to non-protocol, non-class type '%1'",
+      (Type, StringRef))
 NOTE(requires_conformance_nonprotocol_fixit,none,
      "use '%0 == %1' to require '%0' to be '%1'",
      (StringRef, StringRef))
@@ -4648,8 +4648,6 @@ ERROR(unchecked_not_inheritance_clause,none,
 ERROR(unchecked_not_existential,none,
       "'unchecked' attribute cannot apply to non-protocol type %0", (Type))
 
-WARNING(unnecessary_any,none,
-         "'any' is redundant on type %0", (Type))
 ERROR(any_not_existential,none,
        "'any' has no effect on %select{concrete type|type parameter}0 %1",
        (bool, Type))
diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h
index 78499df4b11ce..8a7a8787b2da3 100644
--- a/include/swift/AST/PrintOptions.h
+++ b/include/swift/AST/PrintOptions.h
@@ -278,6 +278,10 @@ struct PrintOptions {
 
   bool PrintImplicitAttrs = true;
 
+  /// Whether to print the \c any keyword for existential
+  /// types.
+  bool PrintExplicitAny = false;
+
   /// Whether to skip keywords with a prefix of underscore such as __consuming.
   bool SkipUnderscoredKeywords = false;
 
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index d84459e1e7904..714349cfdcb18 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -660,7 +660,7 @@ class SelfProtocolConformance : public RootProtocolConformance {
 public:
   /// Get the protocol being conformed to.
   ProtocolDecl *getProtocol() const {
-    return getType()->castTo<ProtocolType>()->getDecl();
+    return dyn_cast<ProtocolDecl>(getType()->getAnyNominal());
   }
 
   /// Get the declaration context in which this conformance was declared.
diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h
index 467753c4df00d..3b7650a430338 100644
--- a/include/swift/AST/Type.h
+++ b/include/swift/AST/Type.h
@@ -385,6 +385,7 @@ class CanType : public Type {
 
   static bool isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig,
                                   bool functionsCount);
+  static bool isConstraintTypeImpl(CanType type);
   static bool isExistentialTypeImpl(CanType type);
   static bool isAnyExistentialTypeImpl(CanType type);
   static bool isObjCExistentialTypeImpl(CanType type);
@@ -457,6 +458,10 @@ class CanType : public Type {
                                /*functions count*/ false);
   }
 
+  bool isConstraintType() const {
+    return isConstraintTypeImpl(*this);
+  }
+
   /// Is this type existential?
   bool isExistentialType() const {
     return isExistentialTypeImpl(*this);
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index c1fa303a8f44f..a848f1dbcff48 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -727,6 +727,9 @@ class alignas(1 << TypeAlignInBits) TypeBase
     return getRecursiveProperties().hasDependentMember();
   }
 
+  /// Whether this type represents a generic constraint.
+  bool isConstraintType() const;
+
   /// isExistentialType - Determines whether this type is an existential type,
   /// whose real (runtime) type is unknown but which is known to conform to
   /// some set of protocols. Protocol and protocol-conformance types are
@@ -2731,6 +2734,8 @@ class ExistentialMetatypeType : public AnyMetatypeType {
   static bool classof(const TypeBase *T) {
     return T->getKind() == TypeKind::ExistentialMetatype;
   }
+
+  Type getExistentialInstanceType();
   
 private:
   ExistentialMetatypeType(Type T, const ASTContext *C,
@@ -5243,7 +5248,7 @@ class ExistentialType final : public TypeBase {
         ConstraintType(constraintType) {}
 
 public:
-  static ExistentialType *get(Type constraint);
+  static Type get(Type constraint);
 
   Type getConstraintType() const { return ConstraintType; }
 
@@ -6335,6 +6340,15 @@ inline GenericTypeParamType *TypeBase::getRootGenericParam() {
   return t->castTo<GenericTypeParamType>();
 }
 
+inline bool TypeBase::isConstraintType() const {
+  return getCanonicalType().isConstraintType();
+}
+
+inline bool CanType::isConstraintTypeImpl(CanType type) {
+  return (isa<ProtocolType>(type) ||
+          isa<ProtocolCompositionType>(type));
+}
+
 inline bool TypeBase::isExistentialType() {
   return getCanonicalType().isExistentialType();
 }
@@ -6441,6 +6455,8 @@ inline NominalTypeDecl *TypeBase::getNominalOrBoundGenericNominal() {
 inline NominalTypeDecl *CanType::getNominalOrBoundGenericNominal() const {
   if (auto Ty = dyn_cast<NominalOrBoundGenericNominalType>(*this))
     return Ty->getDecl();
+  if (auto Ty = dyn_cast<ExistentialType>(*this))
+    return Ty->getConstraintType()->getNominalOrBoundGenericNominal();
   return nullptr;
 }
 
@@ -6449,6 +6465,9 @@ inline NominalTypeDecl *TypeBase::getAnyNominal() {
 }
 
 inline Type TypeBase::getNominalParent() {
+  if (auto existential = getAs<ExistentialType>())
+    return existential->getConstraintType()->getNominalParent();
+
   return castTo<AnyGenericType>()->getParent();
 }
 
diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h
index 1bfed64e7d81e..3960c4d73e7f0 100644
--- a/include/swift/Basic/LangOptions.h
+++ b/include/swift/Basic/LangOptions.h
@@ -315,7 +315,7 @@ namespace swift {
 
     /// Enable support for explicit existential types via the \c any
     /// keyword.
-    bool EnableExplicitExistentialTypes = false;
+    bool EnableExplicitExistentialTypes = true;
 
     /// Enable experimental flow-sensitive concurrent captures.
     bool EnableExperimentalFlowSensitiveConcurrentCaptures = false;
diff --git a/include/swift/Demangling/TypeDecoder.h b/include/swift/Demangling/TypeDecoder.h
index 73a86f320d77c..07b5e5161dc70 100644
--- a/include/swift/Demangling/TypeDecoder.h
+++ b/include/swift/Demangling/TypeDecoder.h
@@ -372,12 +372,16 @@ void decodeRequirement(NodePointer node,
 
     BuiltType constraintType;
     if (child->getKind() ==
-            Demangle::Node::Kind::DependentGenericConformanceRequirement ||
-        child->getKind() ==
-            Demangle::Node::Kind::DependentGenericSameTypeRequirement) {
+        Demangle::Node::Kind::DependentGenericConformanceRequirement) {
       constraintType = Builder.decodeMangledType(child->getChild(1));
       if (!constraintType)
         return;
+    } else if (child->getKind() ==
+               Demangle::Node::Kind::DependentGenericSameTypeRequirement) {
+      constraintType = Builder.decodeMangledType(
+          child->getChild(1), /*forRequirement=*/false);
+      if (!constraintType)
+        return;
     }
 
     switch (child->getKind()) {
@@ -468,15 +472,17 @@ class TypeDecoder {
   explicit TypeDecoder(BuilderType &Builder) : Builder(Builder) {}
 
   /// Given a demangle tree, attempt to turn it into a type.
-  TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node) {
-    return decodeMangledType(Node, 0);
+  TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node,
+                                                 bool forRequirement = true) {
+    return decodeMangledType(Node, 0, forRequirement);
   }
 
 protected:
   static const unsigned MaxDepth = 1024;
 
   TypeLookupErrorOr<BuiltType> decodeMangledType(NodePointer Node,
-                                                 unsigned depth) {
+                                                 unsigned depth,
+                                                 bool forRequirement = true) {
     if (depth > TypeDecoder::MaxDepth)
       return TypeLookupError("Mangled type is too complex");
 
@@ -499,7 +505,8 @@ class TypeDecoder {
       if (Node->getNumChildren() < 1)
         return MAKE_NODE_TYPE_ERROR0(Node, "no children.");
 
-      return decodeMangledType(Node->getChild(0), depth + 1);
+      return decodeMangledType(Node->getChild(0), depth + 1,
+                               forRequirement);
     case NodeKind::Class:
     {
 #if SWIFT_OBJC_INTEROP
@@ -543,7 +550,8 @@ class TypeDecoder {
         return MAKE_NODE_TYPE_ERROR0(genericArgs, "is not TypeList");
 
       for (auto genericArg : *genericArgs) {
-        auto paramType = decodeMangledType(genericArg, depth + 1);
+        auto paramType = decodeMangledType(genericArg, depth + 1,
+                                           /*forRequirement=*/false);
         if (paramType.isError())
           return paramType;
         args.push_back(paramType.getType());
@@ -698,14 +706,16 @@ class TypeDecoder {
       }
 
       return Builder.createProtocolCompositionType(Protocols, Superclass,
-                                                   IsClassBound);
+                                                   IsClassBound,
+                                                   forRequirement);
     }
 
     case NodeKind::Protocol:
     case NodeKind::ProtocolSymbolicReference: {
       if (auto Proto = decodeMangledProtocolType(Node, depth + 1)) {
         return Builder.createProtocolCompositionType(Proto, BuiltType(),
-                                                     /*IsClassBound=*/false);
+                                                     /*IsClassBound=*/false,
+                                                     forRequirement);
       }
 
       return MAKE_NODE_TYPE_ERROR0(Node, "failed to decode protocol type");
@@ -845,7 +855,8 @@ class TypeDecoder {
                           Node->getKind() == NodeKind::EscapingObjCBlock);
 
       auto result =
-          decodeMangledType(Node->getChild(firstChildIdx + 1), depth + 1);
+          decodeMangledType(Node->getChild(firstChildIdx + 1), depth + 1,
+                            /*forRequirement=*/false);
       if (result.isError())
         return result;
       return Builder.createFunctionType(
@@ -962,7 +973,8 @@ class TypeDecoder {
       if (Node->getNumChildren() < 1)
         return MAKE_NODE_TYPE_ERROR0(Node, "no children");
 
-      return decodeMangledType(Node->getChild(0), depth + 1);
+      return decodeMangledType(Node->getChild(0), depth + 1,
+                               /*forRequirement=*/false);
 
     case NodeKind::Tuple: {
       llvm::SmallVector<BuiltType, 8> elements;
@@ -994,7 +1006,8 @@ class TypeDecoder {
 
         // Decode the element type.
         auto elementType =
-            decodeMangledType(element->getChild(typeChildIndex), depth + 1);
+            decodeMangledType(element->getChild(typeChildIndex), depth + 1,
+                              /*forRequirement=*/false);
         if (elementType.isError())
           return elementType;
 
@@ -1012,9 +1025,11 @@ class TypeDecoder {
                                       "fewer children (%zu) than required (2)",
                                       Node->getNumChildren());
 
-        return decodeMangledType(Node->getChild(1), depth + 1);
+        return decodeMangledType(Node->getChild(1), depth + 1,
+                                 /*forRequirement=*/false);
       }
-      return decodeMangledType(Node->getChild(0), depth + 1);
+      return decodeMangledType(Node->getChild(0), depth + 1,
+                               /*forRequirement=*/false);
 
     case NodeKind::DependentGenericType: {
       if (Node->getNumChildren() < 2)
@@ -1161,7 +1176,8 @@ return {}; // Not Implemented!
                 "more substitutions than generic params");
           while (index >= genericParamsAtDepth[paramDepth])
             ++paramDepth, index = 0;
-          auto substTy = decodeMangledType(subst, depth + 1);
+          auto substTy = decodeMangledType(subst, depth + 1,
+                                           /*forRequirement=*/false);
           if (substTy.isError())
             return substTy;
           substitutions.emplace_back(
@@ -1243,7 +1259,8 @@ return {}; // Not Implemented!
         if (genericsNode->getKind() != NodeKind::TypeList)
           break;
         for (auto argNode : *genericsNode) {
-          auto arg = decodeMangledType(argNode, depth + 1);
+          auto arg = decodeMangledType(argNode, depth + 1,
+                                       /*forRequirement=*/false);
           if (arg.isError())
             return arg;
           genericArgsBuf.push_back(arg.getType());
@@ -1480,7 +1497,8 @@ return {}; // Not Implemented!
         }
       }
 
-      auto paramType = decodeMangledType(node, depth + 1);
+      auto paramType = decodeMangledType(node, depth + 1,
+                                         /*forRequirement=*/false);
       if (paramType.isError())
         return false;
 
@@ -1544,8 +1562,10 @@ return {}; // Not Implemented!
 
 template <typename BuilderType>
 inline TypeLookupErrorOr<typename BuilderType::BuiltType>
-decodeMangledType(BuilderType &Builder, NodePointer Node) {
-  return TypeDecoder<BuilderType>(Builder).decodeMangledType(Node);
+decodeMangledType(BuilderType &Builder, NodePointer Node,
+                  bool forRequirement = false) {
+  return TypeDecoder<BuilderType>(Builder)
+      .decodeMangledType(Node, forRequirement);
 }
 
 SWIFT_END_INLINE_NAMESPACE
diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h
index 913508ce5a03d..8732961f7cc30 100644
--- a/include/swift/Reflection/TypeRefBuilder.h
+++ b/include/swift/Reflection/TypeRefBuilder.h
@@ -289,7 +289,7 @@ class TypeRefBuilder {
 
   void clearNodeFactory() { Dem.clear(); }
 
-  BuiltType decodeMangledType(Node *node);
+  BuiltType decodeMangledType(Node *node, bool forRequirement = true);
 
   ///
   /// Factory methods for all TypeRef kinds
@@ -492,7 +492,8 @@ class TypeRefBuilder {
 
   const ProtocolCompositionTypeRef *
   createProtocolCompositionType(llvm::ArrayRef<BuiltProtocolDecl> protocols,
-                                BuiltType superclass, bool isClassBound) {
+                                BuiltType superclass, bool isClassBound,
+                                bool forRequirement = true) {
     std::vector<const TypeRef *> protocolRefs;
     for (const auto &protocol : protocols) {
       if (!protocol)
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 9516c9fc1b76a..29c463576dfd5 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -2220,7 +2220,7 @@ visitOpenExistentialMetatypeInst(OpenExistentialMetatypeInst *Inst) {
   auto openedType = Inst->getType().getASTType();
   auto exType = Inst->getOperand()->getType().getASTType();
   while (auto exMetatype = dyn_cast<ExistentialMetatypeType>(exType)) {
-    exType = exMetatype.getInstanceType();
+    exType = exMetatype->getExistentialInstanceType()->getCanonicalType();
     openedType = cast<MetatypeType>(openedType).getInstanceType();
   }
   remapOpenedType(cast<OpenedArchetypeType>(openedType));
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index d958ceff2ee6b..6e000ffed7904 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -7072,7 +7072,7 @@ class InitExistentialMetatypeInst final
     auto exType = getType().getASTType();
     auto concreteType = getOperand()->getType().getASTType();
     while (auto exMetatype = dyn_cast<ExistentialMetatypeType>(exType)) {
-      exType = exMetatype.getInstanceType();
+      exType = exMetatype->getExistentialInstanceType()->getCanonicalType();
       concreteType = cast<MetatypeType>(concreteType).getInstanceType();
     }
     assert(exType.isExistentialType());
diff --git a/lib/APIDigester/ModuleAnalyzerNodes.cpp b/lib/APIDigester/ModuleAnalyzerNodes.cpp
index e90da097f4313..6d05f5bd1d718 100644
--- a/lib/APIDigester/ModuleAnalyzerNodes.cpp
+++ b/lib/APIDigester/ModuleAnalyzerNodes.cpp
@@ -1017,6 +1017,12 @@ static StringRef getTypeName(SDKContext &Ctx, Type Ty,
   if (auto *NAT = dyn_cast<TypeAliasType>(Ty.getPointer())) {
     return NAT->getDecl()->getNameStr();
   }
+
+  if (auto existential = Ty->getAs<ExistentialType>()) {
+    return getTypeName(Ctx, existential->getConstraintType(),
+                       IsImplicitlyUnwrappedOptional);
+  }
+
   if (Ty->getAnyNominal()) {
     if (IsImplicitlyUnwrappedOptional) {
       assert(Ty->getOptionalObjectType());
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 21bfef2986770..e547554e69b9f 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -847,9 +847,9 @@ Type ASTContext::get##NAME##Type() const { \
 }
 #include "swift/AST/KnownStdlibTypes.def"
 
-CanType ASTContext::getExceptionType() const {
+CanType ASTContext::getErrorExistentialType() const {
   if (auto exn = getErrorDecl()) {
-    return exn->getDeclaredInterfaceType()->getCanonicalType();
+    return exn->getExistentialType()->getCanonicalType();
   } else {
     // Use Builtin.NativeObject just as a stand-in.
     return TheNativeObjectType;
@@ -2256,7 +2256,7 @@ ASTContext::getSelfConformance(ProtocolDecl *protocol) {
   auto &entry = selfConformances[protocol];
   if (!entry) {
     entry = new (*this, AllocationArena::Permanent)
-      SelfProtocolConformance(protocol->getDeclaredInterfaceType());
+      SelfProtocolConformance(protocol->getExistentialType());
   }
   return entry;
 }
@@ -3319,6 +3319,11 @@ MetatypeType::MetatypeType(Type T, const ASTContext *C,
 ExistentialMetatypeType *
 ExistentialMetatypeType::get(Type T, Optional<MetatypeRepresentation> repr,
                              const ASTContext &ctx) {
+  // If we're creating an existential metatype from an
+  // existential type, wrap the constraint type direcly.
+  if (auto existential = T->getAs<ExistentialType>())
+    T = existential->getConstraintType();
+
   auto properties = T->getRecursiveProperties();
   auto arena = getArena(properties);
 
@@ -3351,6 +3356,10 @@ ExistentialMetatypeType::ExistentialMetatypeType(Type T,
   }
 }
 
+Type ExistentialMetatypeType::getExistentialInstanceType() {
+  return ExistentialType::get(getInstanceType());
+}
+
 ModuleType *ModuleType::get(ModuleDecl *M) {
   ASTContext &C = M->getASTContext();
 
@@ -4103,11 +4112,22 @@ ProtocolType::ProtocolType(ProtocolDecl *TheDecl, Type Parent,
                            RecursiveTypeProperties properties)
   : NominalType(TypeKind::Protocol, &Ctx, TheDecl, Parent, properties) { }
 
-ExistentialType *ExistentialType::get(Type constraint) {
+Type ExistentialType::get(Type constraint) {
+  auto &C = constraint->getASTContext();
+  if (!C.LangOpts.EnableExplicitExistentialTypes)
+    return constraint;
+
+  // FIXME: Any and AnyObject don't yet use ExistentialType.
+  if (constraint->isAny() || constraint->isAnyObject())
+    return constraint;
+
+  // ExistentialMetatypeType is already an existential type.
+  if (constraint->is<ExistentialMetatypeType>())
+    return constraint;
+
   auto properties = constraint->getRecursiveProperties();
   auto arena = getArena(properties);
 
-  auto &C = constraint->getASTContext();
   auto &entry = C.getImpl().getArena(arena).ExistentialTypes[constraint];
   if (entry)
     return entry;
@@ -4316,7 +4336,7 @@ GenericEnvironment *OpenedArchetypeType::getGenericEnvironment() const {
 
 CanType OpenedArchetypeType::getAny(Type existential) {
   if (auto metatypeTy = existential->getAs<ExistentialMetatypeType>()) {
-    auto instanceTy = metatypeTy->getInstanceType();
+    auto instanceTy = metatypeTy->getExistentialInstanceType();
     return CanMetatypeType::get(OpenedArchetypeType::getAny(instanceTy));
   }
   assert(existential->isExistentialType());
@@ -4865,7 +4885,7 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type,
     if (auto nsErrorTy = getNSErrorType()) {
       // The corresponding value type is Error.
       if (bridgedValueType)
-        *bridgedValueType = getErrorDecl()->getDeclaredInterfaceType();
+        *bridgedValueType = getErrorExistentialType();
 
       return nsErrorTy;
     }
@@ -4902,7 +4922,7 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type,
   if (findConformance(KnownProtocolKind::Error)) {
     // The corresponding value type is Error.
     if (bridgedValueType)
-      *bridgedValueType = getErrorDecl()->getDeclaredInterfaceType();
+      *bridgedValueType = getErrorExistentialType();
 
     // Bridge to NSError.
     if (auto nsErrorTy = getNSErrorType())
@@ -4990,16 +5010,18 @@ CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
 // constraints while existential values do.
 CanGenericSignature ASTContext::getOpenedArchetypeSignature(Type type) {
   assert(type->isExistentialType());
+  if (auto existential = type->getAs<ExistentialType>())
+    type = existential->getConstraintType();
 
-  const CanType existential = type->getCanonicalType();
+  const CanType constraint = type->getCanonicalType();
 
   // The opened archetype signature for a protocol type is identical
   // to the protocol's own canonical generic signature.
-  if (const auto protoTy = dyn_cast<ProtocolType>(existential)) {
+  if (const auto protoTy = dyn_cast<ProtocolType>(constraint)) {
     return protoTy->getDecl()->getGenericSignature().getCanonicalSignature();
   }
 
-  auto found = getImpl().ExistentialSignatures.find(existential);
+  auto found = getImpl().ExistentialSignatures.find(constraint);
   if (found != getImpl().ExistentialSignatures.end())
     return found->second;
 
@@ -5007,7 +5029,7 @@ CanGenericSignature ASTContext::getOpenedArchetypeSignature(Type type) {
       GenericTypeParamType::get(/*type sequence*/ false,
                                 /*depth*/ 0, /*index*/ 0, *this);
   Requirement requirement(RequirementKind::Conformance, genericParam,
-                          existential);
+                          constraint);
   auto genericSig = buildGenericSignature(*this,
                                           GenericSignature(),
                                           {genericParam},
@@ -5016,7 +5038,7 @@ CanGenericSignature ASTContext::getOpenedArchetypeSignature(Type type) {
   CanGenericSignature canGenericSig(genericSig);
 
   auto result = getImpl().ExistentialSignatures.insert(
-    std::make_pair(existential, canGenericSig));
+    std::make_pair(constraint, canGenericSig));
   assert(result.second);
   (void) result;
 
diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp
index 698da2641b787..149474bd664eb 100644
--- a/lib/AST/ASTDemangler.cpp
+++ b/lib/AST/ASTDemangler.cpp
@@ -70,8 +70,9 @@ TypeDecl *swift::Demangle::getTypeDeclForUSR(ASTContext &ctx,
   return getTypeDeclForMangling(ctx, mangling);
 }
 
-Type ASTBuilder::decodeMangledType(NodePointer node) {
-  return swift::Demangle::decodeMangledType(*this, node).getType();
+Type ASTBuilder::decodeMangledType(NodePointer node, bool forRequirement) {
+  return swift::Demangle::decodeMangledType(*this, node, forRequirement)
+      .getType();
 }
 
 TypeDecl *ASTBuilder::createTypeDecl(NodePointer node) {
@@ -578,18 +579,19 @@ Type ASTBuilder::createImplFunctionType(
 Type ASTBuilder::createProtocolCompositionType(
     ArrayRef<ProtocolDecl *> protocols,
     Type superclass,
-    bool isClassBound) {
+    bool isClassBound,
+    bool forRequirement) {
   std::vector<Type> members;
   for (auto protocol : protocols)
     members.push_back(protocol->getDeclaredInterfaceType());
   if (superclass && superclass->getClassOrBoundGenericClass())
     members.push_back(superclass);
+
   Type composition = ProtocolCompositionType::get(Ctx, members, isClassBound);
-  if (Ctx.LangOpts.EnableExplicitExistentialTypes &&
-      !(composition->isAny() || composition->isAnyObject())) {
-    composition = ExistentialType::get(composition);
-  }
-  return composition;
+  if (forRequirement)
+    return composition;
+
+  return ExistentialType::get(composition);
 }
 
 static MetatypeRepresentation
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index a0dc3450413e3..4f9cdf3a32be2 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -4852,6 +4852,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
             isSimpleUnderPrintOptions(opaque->getExistentialType());
       }
       llvm_unreachable("bad opaque-return-type printing mode");
+    } else if (auto existential = dyn_cast<ExistentialType>(T.getPointer())) {
+      if (!Options.PrintExplicitAny)
+        return isSimpleUnderPrintOptions(existential->getConstraintType());
     }
     return T->hasSimpleTypeRepr();
   }
@@ -5272,9 +5275,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
       }
     }
 
-    auto &ctx = T->getASTContext();
-    if (T->is<ExistentialMetatypeType>() &&
-        ctx.LangOpts.EnableExplicitExistentialTypes)
+    if (T->is<ExistentialMetatypeType>() && Options.PrintExplicitAny)
       Printer << "any ";
 
     printWithParensIfNotSimple(T->getInstanceType());
@@ -5282,7 +5283,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
     // We spell normal metatypes of existential types as .Protocol.
     if (isa<MetatypeType>(T) &&
         T->getInstanceType()->isAnyExistentialType() &&
-        !ctx.LangOpts.EnableExplicitExistentialTypes) {
+        !Options.PrintExplicitAny) {
       Printer << ".Protocol";
     } else {
       Printer << ".Type";
@@ -5875,7 +5876,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
   }
 
   void visitExistentialType(ExistentialType *T) {
-    Printer << "any ";
+    if (Options.PrintExplicitAny)
+      Printer << "any ";
+
     visit(T->getConstraintType());
   }
 
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index b4f4c6931ac52..e05a901e6e1b6 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -2067,7 +2067,10 @@ class Verifier : public ASTWalker {
         abort();
       }
 
-      checkSameType(E->getBase()->getType(), metatype->getInstanceType(),
+      auto instance = metatype->getInstanceType();
+      if (auto existential = metatype->getAs<ExistentialMetatypeType>())
+        instance = existential->getExistentialInstanceType();
+      checkSameType(E->getBase()->getType(), instance,
                     "base type of .Type expression");
       verifyCheckedBase(E);
     }
@@ -3422,11 +3425,12 @@ class Verifier : public ASTWalker {
     }
 
     Type checkExceptionTypeExists(const char *where) {
-      auto exn = Ctx.getErrorDecl();
-      if (exn) return exn->getDeclaredInterfaceType();
+      if (!Ctx.getErrorDecl()) {
+        Out << "exception type does not exist in " << where << "\n";
+        abort();
+      }
 
-      Out << "exception type does not exist in " << where << "\n";
-      abort();
+      return Ctx.getErrorExistentialType();
     }
 
     bool isGoodSourceRange(SourceRange SR) {
diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp
index 7a1a4eca5b6f4..33c9ff575c232 100644
--- a/lib/AST/ClangTypeConverter.cpp
+++ b/lib/AST/ClangTypeConverter.cpp
@@ -750,6 +750,11 @@ ClangTypeConverter::visitProtocolCompositionType(ProtocolCompositionType *type)
   return clangCtx.getObjCObjectPointerType(clangType);
 }
 
+clang::QualType
+ClangTypeConverter::visitExistentialType(ExistentialType *type) {
+  return visit(type->getConstraintType());
+}
+
 clang::QualType
 ClangTypeConverter::visitBuiltinRawPointerType(BuiltinRawPointerType *type) {
   return ClangASTContext.VoidPtrTy;
@@ -828,6 +833,9 @@ clang::QualType ClangTypeConverter::convert(Type type) {
     return it->second;
 
   // Try to do this without making cache entries for obvious cases.
+  if (auto existential = type->getAs<ExistentialType>())
+    type = existential->getConstraintType();
+
   if (auto nominal = type->getAs<NominalType>()) {
     auto decl = nominal->getDecl();
     if (auto clangDecl = decl->getClangDecl()) {
diff --git a/lib/AST/ClangTypeConverter.h b/lib/AST/ClangTypeConverter.h
index d14a930fe6e13..d4ba69e33cf8c 100644
--- a/lib/AST/ClangTypeConverter.h
+++ b/lib/AST/ClangTypeConverter.h
@@ -122,6 +122,7 @@ class ClangTypeConverter :
   clang::QualType visitEnumType(EnumType *type);
   clang::QualType visitFunctionType(FunctionType *type);
   clang::QualType visitProtocolCompositionType(ProtocolCompositionType *type);
+  clang::QualType visitExistentialType(ExistentialType *type);
   clang::QualType visitBuiltinRawPointerType(BuiltinRawPointerType *type);
   clang::QualType visitBuiltinIntegerType(BuiltinIntegerType *type);
   clang::QualType visitBuiltinFloatType(BuiltinFloatType *type);
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 39547a9e1aa9e..dd7995158f2dd 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -5164,7 +5164,10 @@ findProtocolSelfReferences(const ProtocolDecl *proto, Type type,
     return SelfReferenceInfo::forSelfRef(SelfReferencePosition::Invariant);
 
   // Protocol compositions preserve variance.
-  if (auto *comp = type->getAs<ProtocolCompositionType>()) {
+  auto constraint = type;
+  if (auto existential = constraint->getAs<ExistentialType>())
+    constraint = existential->getConstraintType();
+  if (auto *comp = constraint->getAs<ProtocolCompositionType>()) {
     // 'Self' may be referenced only in a superclass component.
     if (const auto superclass = comp->getSuperclass()) {
       return findProtocolSelfReferences(proto, superclass, position);
diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp
index 691c3b7b48166..f27104ed2bdc3 100644
--- a/lib/AST/DiagnosticEngine.cpp
+++ b/lib/AST/DiagnosticEngine.cpp
@@ -549,6 +549,24 @@ static bool typeSpellingIsAmbiguous(Type type,
       auto argType = arg.getAsType();
       if (argType && argType->getWithoutParens().getPointer() != type.getPointer() &&
           argType->getWithoutParens().getString(PO) == type.getString(PO)) {
+        // Currently, existential types are spelled the same way
+        // as protocols and compositions. We can remove this once
+        // existenials are printed with 'any'.
+        if (type->is<ExistentialType>() || argType->isExistentialType()) {
+          auto constraint = type;
+          if (auto existential = type->getAs<ExistentialType>())
+            constraint = existential->getConstraintType();
+
+          auto argConstraint = argType;
+          if (auto existential = argType->getAs<ExistentialType>())
+            argConstraint = existential->getConstraintType();
+
+          if (constraint.getPointer() != argConstraint.getPointer())
+            return true;
+
+          continue;
+        }
+
         return true;
       }
     }
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index f223f310a0e61..7f7e7c4ffff91 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -4500,7 +4500,8 @@ ConstraintResult GenericSignatureBuilder::addTypeRequirement(
   }
 
   // Check whether we have a reasonable constraint type at all.
-  if (!constraintType->isExistentialType() &&
+  if (!constraintType->is<ProtocolType>() &&
+      !constraintType->is<ProtocolCompositionType>() &&
       !constraintType->getClassOrBoundGenericClass()) {
     if (source.getLoc().isValid() && !constraintType->hasError()) {
       Impl->HadAnyError = true;
@@ -6292,8 +6293,16 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
       auto source = constraint.source;
       auto loc = source->getLoc();
 
+      // FIXME: The constraint string is printed directly here because
+      // the current default is to not print `any` for existential
+      // types, but this error message is super confusing without `any`
+      // if the user wrote it explicitly.
+      PrintOptions options;
+      options.PrintExplicitAny = true;
+      auto constraintString = constraintType.getString(options);
+
       Diags.diagnose(loc, diag::requires_conformance_nonprotocol,
-                     subjectType, constraintType);
+                     subjectType, constraintString);
       
       auto getNameWithoutSelf = [&](std::string subjectTypeName) {
         std::string selfSubstring = "Self.";
@@ -6311,7 +6320,7 @@ GenericSignatureBuilder::finalize(TypeArrayView<GenericTypeParamType> genericPar
         auto subjectTypeName = subjectType.getString();
         auto subjectTypeNameWithoutSelf = getNameWithoutSelf(subjectTypeName);
         Diags.diagnose(loc, diag::requires_conformance_nonprotocol_fixit,
-                       subjectTypeNameWithoutSelf, constraintType.getString())
+                       subjectTypeNameWithoutSelf, constraintString)
              .fixItReplace(loc, " == ");
       }
     }
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index 07274fee10894..c406e45c9f242 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -978,13 +978,17 @@ ModuleDecl::lookupExistentialConformance(Type type, ProtocolDecl *protocol) {
   // existential to an archetype parameter, so for now we restrict this to
   // @objc protocols and marker protocols.
   if (!layout.isObjC() && !protocol->isMarkerProtocol()) {
+    auto constraint = type;
+    if (auto existential = constraint->getAs<ExistentialType>())
+      constraint = existential->getConstraintType();
+
     // There's a specific exception for protocols with self-conforming
     // witness tables, but the existential has to be *exactly* that type.
     // TODO: synthesize witness tables on-demand for protocol compositions
     // that can satisfy the requirement.
     if (protocol->requiresSelfConformanceWitnessTable() &&
-        type->is<ProtocolType>() &&
-        type->castTo<ProtocolType>()->getDecl() == protocol)
+        constraint->is<ProtocolType>() &&
+        constraint->castTo<ProtocolType>()->getDecl() == protocol)
       return ProtocolConformanceRef(ctx.getSelfConformance(protocol));
 
     return ProtocolConformanceRef::forInvalid();
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 1046d859eff7c..e27fa2f517438 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -104,6 +104,8 @@ NominalTypeDecl *CanType::getAnyNominal() const {
 }
 
 GenericTypeDecl *CanType::getAnyGeneric() const {
+  if (auto existential = dyn_cast<ExistentialType>(*this))
+    return existential->getConstraintType()->getAnyGeneric();
   if (auto Ty = dyn_cast<AnyGenericType>(*this))
     return Ty->getDecl();
   return nullptr;
@@ -464,6 +466,8 @@ Type TypeBase::eraseOpenedExistential(OpenedArchetypeType *opened) {
       auto instanceType = metatypeType->getInstanceType();
       if (instanceType->hasOpenedExistential()) {
         instanceType = instanceType->eraseOpenedExistential(opened);
+        if (auto existential = instanceType->getAs<ExistentialType>())
+          instanceType = existential->getConstraintType();
         return ExistentialMetatypeType::get(instanceType);
       }
     }
@@ -1199,6 +1203,9 @@ Type TypeBase::replaceSelfParameterType(Type newSelf) {
 /// Look through a metatype, or just return the original type if it is
 /// not a metatype.
 Type TypeBase::getMetatypeInstanceType() {
+  if (auto existentialMetaType = getAs<ExistentialMetatypeType>())
+    return existentialMetaType->getExistentialInstanceType();
+
   if (auto metaTy = getAs<AnyMetatypeType>())
     return metaTy->getInstanceType();
 
@@ -1494,7 +1501,7 @@ CanType TypeBase::computeCanonicalType() {
   case TypeKind::Existential: {
     auto *existential = cast<ExistentialType>(this);
     auto constraint = existential->getConstraintType()->getCanonicalType();
-    Result = ExistentialType::get(constraint);
+    Result = ExistentialType::get(constraint).getPointer();
     break;
   }
   case TypeKind::ExistentialMetatype: {
@@ -2638,7 +2645,7 @@ getForeignRepresentable(Type type, ForeignLanguage language,
   // If type has an error let's fail early.
   if (type->hasError())
     return failure();
-  
+
   // Look through one level of optional type, but remember that we did.
   bool wasOptional = false;
   if (auto valueType = type->getOptionalObjectType()) {
@@ -2646,6 +2653,9 @@ getForeignRepresentable(Type type, ForeignLanguage language,
     wasOptional = true;
   }
 
+  if (auto existential = type->getAs<ExistentialType>())
+    type = existential->getConstraintType();
+
   // Objective-C object types, including metatypes.
   if (language == ForeignLanguage::ObjectiveC) {
     auto representable = getObjCObjectRepresentable(type, dc);
@@ -3237,9 +3247,11 @@ Type ArchetypeType::getExistentialType() const {
   for (auto proto : getConformsTo()) {
     constraintTypes.push_back(proto->getDeclaredInterfaceType());
   }
-  return ProtocolCompositionType::get(
-     const_cast<ArchetypeType*>(this)->getASTContext(), constraintTypes,
-                                      requiresClass());
+  auto &ctx = const_cast<ArchetypeType*>(this)->getASTContext();
+  auto constraint = ProtocolCompositionType::get(
+     ctx, constraintTypes, requiresClass());
+
+  return ExistentialType::get(constraint);
 }
 
 PrimaryArchetypeType::PrimaryArchetypeType(const ASTContext &Ctx,
@@ -5550,6 +5562,10 @@ bool Type::isPrivateStdlibType(bool treatNonBuiltinProtocolsAsPublic) const {
   if (!Ty)
     return false;
 
+  if (auto existential = dyn_cast<ExistentialType>(Ty.getPointer()))
+    return existential->getConstraintType()
+        .isPrivateStdlibType(treatNonBuiltinProtocolsAsPublic);
+
   // A 'public' typealias can have an 'internal' type.
   if (auto *NAT = dyn_cast<TypeAliasType>(Ty.getPointer())) {
     auto *AliasDecl = NAT->getDecl();
@@ -5734,7 +5750,7 @@ SILBoxType::SILBoxType(ASTContext &C,
 Type TypeBase::openAnyExistentialType(OpenedArchetypeType *&opened) {
   assert(isAnyExistentialType());
   if (auto metaty = getAs<ExistentialMetatypeType>()) {
-    opened = OpenedArchetypeType::get(metaty->getInstanceType());
+    opened = OpenedArchetypeType::get(metaty->getExistentialInstanceType());
     if (metaty->hasRepresentation())
       return MetatypeType::get(opened, metaty->getRepresentation());
     else
diff --git a/lib/AST/TypeJoinMeet.cpp b/lib/AST/TypeJoinMeet.cpp
index 403eb0417dc83..2c8db30bae1f6 100644
--- a/lib/AST/TypeJoinMeet.cpp
+++ b/lib/AST/TypeJoinMeet.cpp
@@ -66,6 +66,7 @@ struct TypeJoin : CanTypeVisitor<TypeJoin, CanType> {
   CanType visitBoundGenericStructType(CanType second);
   CanType visitMetatypeType(CanType second);
   CanType visitExistentialMetatypeType(CanType second);
+  CanType visitExistentialType(CanType second);
   CanType visitModuleType(CanType second);
   CanType visitDynamicSelfType(CanType second);
   CanType visitArchetypeType(CanType second);
@@ -271,6 +272,24 @@ CanType TypeJoin::visitExistentialMetatypeType(CanType second) {
   return ExistentialMetatypeType::get(joinInstance)->getCanonicalType();
 }
 
+CanType TypeJoin::visitExistentialType(CanType second) {
+  assert(First != second);
+
+  if (First->getKind() != second->getKind())
+    return TheAnyType;
+
+  auto firstConstraint = First->castTo<ExistentialType>()
+      ->getConstraintType()->getCanonicalType();
+  auto secondConstraint = second->castTo<ExistentialType>()
+      ->getConstraintType()->getCanonicalType();
+
+  auto joinInstance = join(firstConstraint, secondConstraint);
+  if (!joinInstance)
+    return CanType();
+
+  return ExistentialType::get(joinInstance)->getCanonicalType();
+}
+
 CanType TypeJoin::visitModuleType(CanType second) {
   assert(First != second);
 
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 91d1356458d76..59f8e1317939a 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -6244,6 +6244,9 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
   // Local function to add a known protocol only when the
   // underlying type conforms to it.
   auto computedNominal = computedPropertyUnderlyingType->getAnyNominal();
+  if (auto existential =
+          computedPropertyUnderlyingType->getAs<ExistentialType>())
+    computedNominal = existential->getConstraintType()->getAnyNominal();
   auto transferKnown = [&](KnownProtocolKind kind) {
     if (!computedNominal)
       return false;
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index 1273db09499a0..ff8f530bcd18f 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -1049,9 +1049,10 @@ namespace {
               if (memberTypes.empty())
                 hasExplicitAnyObject = true;
 
-              Type importedTypeArg = ProtocolCompositionType::get(
-                  Impl.SwiftContext, memberTypes,
-                  hasExplicitAnyObject);
+              Type importedTypeArg = ExistentialType::get(
+                  ProtocolCompositionType::get(
+                      Impl.SwiftContext, memberTypes,
+                      hasExplicitAnyObject));
               importedTypeArgs.push_back(importedTypeArg);
             }
           }
@@ -1180,6 +1181,9 @@ namespace {
             }
           }
 
+          if (bridgedType->isConstraintType())
+            bridgedType = ExistentialType::get(bridgedType);
+
           return { importedType,
                    ImportHint(ImportHint::ObjCBridged, bridgedType) };
         }
@@ -1200,9 +1204,9 @@ namespace {
           members.push_back(proto->getDeclaredInterfaceType());
         }
 
-        importedType = ProtocolCompositionType::get(Impl.SwiftContext,
-                                                    members,
-                                                    /*HasExplicitAnyObject=*/false);
+        importedType = ExistentialType::get(
+            ProtocolCompositionType::get(Impl.SwiftContext, members,
+                                         /*HasExplicitAnyObject=*/false));
       }
 
       // Class or Class<P> maps to an existential metatype.
@@ -2497,7 +2501,7 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
     bool paramIsIUO;
     if (kind == SpecialMethodKind::NSDictionarySubscriptGetter &&
         paramTy->isObjCIdType()) {
-      swiftParamTy = SwiftContext.getNSCopyingType();
+      swiftParamTy = ExistentialType::get(SwiftContext.getNSCopyingType());
       if (!swiftParamTy)
         return {Type(), false};
       if (optionalityOfParam != OTK_None)
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index 917a2474c0f35..8035c45f87886 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -7831,7 +7831,8 @@ class AsyncConverter : private SourceEntityWalker {
                                  const AsyncHandlerDesc &HandlerDesc) {
     // If the error type is already Error, we can pass it as-is.
     auto ErrorType = *HandlerDesc.getErrorType();
-    if (ErrorType->getCanonicalType() == getASTContext().getExceptionType()) {
+    if (ErrorType->getCanonicalType() ==
+        getASTContext().getErrorExistentialType()) {
       OS << ErrorName;
       return;
     }
diff --git a/lib/IRGen/DebugTypeInfo.cpp b/lib/IRGen/DebugTypeInfo.cpp
index 779f30d9c782a..8ef7826cc4762 100644
--- a/lib/IRGen/DebugTypeInfo.cpp
+++ b/lib/IRGen/DebugTypeInfo.cpp
@@ -158,6 +158,8 @@ TypeDecl *DebugTypeInfo::getDecl() const {
     return UBG->getDecl();
   if (auto *BG = dyn_cast<BoundGenericType>(Type))
     return BG->getDecl();
+  if (auto *E = dyn_cast<ExistentialType>(Type))
+    return E->getConstraintType()->getAnyNominal();
   return nullptr;
 }
 
diff --git a/lib/IRGen/GenBuiltin.cpp b/lib/IRGen/GenBuiltin.cpp
index e6d483391bbed..60e7f20738266 100644
--- a/lib/IRGen/GenBuiltin.cpp
+++ b/lib/IRGen/GenBuiltin.cpp
@@ -592,10 +592,9 @@ if (Builtin.ID == BuiltinValueKind::id) { \
   
     auto *fn = cast<llvm::Function>(IGF.IGM.getWillThrowFn());
     auto error = args.claimNext();
+    auto errorTy = IGF.IGM.Context.getErrorExistentialType();
     auto errorBuffer = IGF.getCalleeErrorResultSlot(
-        SILType::getPrimitiveObjectType(IGF.IGM.Context.getErrorDecl()
-                                            ->getDeclaredInterfaceType()
-                                            ->getCanonicalType()));
+        SILType::getPrimitiveObjectType(errorTy));
     IGF.Builder.CreateStore(error, errorBuffer);
     
     auto context = llvm::UndefValue::get(IGF.IGM.Int8PtrTy);
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index 070fafebb5316..fb64cc9ee854f 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -97,6 +97,22 @@ class EqualUpToClangTypes
   };
 };
 
+static bool equalWithoutExistentialTypes(Type t1, Type t2) {
+  if (!t1->getASTContext().LangOpts.EnableExplicitExistentialTypes)
+    return false;
+
+  auto withoutExistentialTypes = [](Type type) -> Type {
+    return type.transform([](Type type) -> Type {
+      if (auto existential = type->getAs<ExistentialType>())
+        return existential->getConstraintType();
+      return type;
+    });
+  };
+
+  return withoutExistentialTypes(t1)
+      ->isEqual(withoutExistentialTypes(t2));
+}
+
 class IRGenDebugInfoImpl : public IRGenDebugInfo {
   friend class IRGenDebugInfoImpl;
   const IRGenOptions &Opts;
@@ -900,6 +916,9 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
         Ty->dump(llvm::errs());
         abort();
       } else if (!Reconstructed->isEqual(Ty) &&
+                 // FIXME: Some existential types are reconstructed without
+                 // an explicit ExistentialType wrapping the constraint.
+                 !equalWithoutExistentialTypes(Reconstructed, Ty) &&
                  !EqualUpToClangTypes().check(Reconstructed, Ty)) {
         // [FIXME: Include-Clang-type-in-mangling] Remove second check
         llvm::errs() << "Incorrect reconstructed type for " << Result << "\n";
diff --git a/lib/IRGen/IRGenMangler.cpp b/lib/IRGen/IRGenMangler.cpp
index ea92243bb26b8..b1555583bf151 100644
--- a/lib/IRGen/IRGenMangler.cpp
+++ b/lib/IRGen/IRGenMangler.cpp
@@ -216,6 +216,8 @@ std::string IRGenMangler::mangleTypeForLLVMTypeName(CanType Ty) {
   // To make LLVM IR more readable we always add a 'T' prefix so that type names
   // don't start with a digit and don't need to be quoted.
   Buffer << 'T';
+  if (auto existential = Ty->getAs<ExistentialType>())
+    Ty = existential->getConstraintType()->getCanonicalType();
   if (auto P = dyn_cast<ProtocolType>(Ty)) {
     appendProtocolName(P->getDecl(), /*allowStandardSubstitution=*/false);
     appendOperator("P");
diff --git a/lib/SIL/IR/SILType.cpp b/lib/SIL/IR/SILType.cpp
index 046e68782487d..d9faf0009361d 100644
--- a/lib/SIL/IR/SILType.cpp
+++ b/lib/SIL/IR/SILType.cpp
@@ -45,7 +45,7 @@ CanArchetypeType swift::getOpenedArchetypeOf(CanType Ty) {
 }
 
 SILType SILType::getExceptionType(const ASTContext &C) {
-  return SILType::getPrimitiveObjectType(C.getExceptionType());
+  return SILType::getPrimitiveObjectType(C.getErrorExistentialType());
 }
 
 SILType SILType::getNativeObjectType(const ASTContext &C) {
diff --git a/lib/SIL/Utils/BasicBlockUtils.cpp b/lib/SIL/Utils/BasicBlockUtils.cpp
index 4dcdc2800d1a4..3a1f46bdd532f 100644
--- a/lib/SIL/Utils/BasicBlockUtils.cpp
+++ b/lib/SIL/Utils/BasicBlockUtils.cpp
@@ -144,8 +144,8 @@ void swift::getEdgeArgs(TermInst *T, unsigned edgeIdx, SILBasicBlock *newEdgeBB,
     case 1: {
       assert(AACI->getErrorBB());
       auto &C = AACI->getFunction()->getASTContext();
-      auto errorTy = C.getErrorDecl()->getDeclaredType();
-      auto errorSILTy = SILType::getPrimitiveObjectType(errorTy->getCanonicalType());
+      auto errorTy = C.getErrorExistentialType();
+      auto errorSILTy = SILType::getPrimitiveObjectType(errorTy);
       // error BB. this takes the error value argument
       args.push_back(
           newEdgeBB->createPhiArgument(errorSILTy, OwnershipKind::Owned));
diff --git a/lib/SIL/Utils/DynamicCasts.cpp b/lib/SIL/Utils/DynamicCasts.cpp
index 550a0794184b2..ae167f9c9ec57 100644
--- a/lib/SIL/Utils/DynamicCasts.cpp
+++ b/lib/SIL/Utils/DynamicCasts.cpp
@@ -468,8 +468,7 @@ swift::classifyDynamicCast(ModuleDecl *M,
                              : DynamicCastFeasibility::WillFail;
     }
 
-    if (targetMetatype.isAnyExistentialType() &&
-        (isa<ProtocolType>(target) || isa<ProtocolCompositionType>(target))) {
+    if (targetMetatype.isAnyExistentialType() && target->isExistentialType()) {
       auto Feasibility =
           classifyDynamicCastToProtocol(M, source, target, isWholeModuleOpts);
       // Cast from existential metatype to existential metatype may still
diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp
index 3bfaee4e0a897..a81dcfd3fa25a 100644
--- a/lib/SIL/Verifier/SILVerifier.cpp
+++ b/lib/SIL/Verifier/SILVerifier.cpp
@@ -2960,8 +2960,19 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
             "value_metatype instruction must have a metatype representation");
     require(MI->getOperand()->getType().isAnyExistentialType(),
             "existential_metatype operand must be of protocol type");
+
+    // The result of an existential_metatype instruction is an existential
+    // metatype with the same constraint type as its existential operand.
     auto formalInstanceTy
       = MI->getType().castTo<ExistentialMetatypeType>().getInstanceType();
+    if (M->getASTContext().LangOpts.EnableExplicitExistentialTypes &&
+        formalInstanceTy->isConstraintType() &&
+        !(formalInstanceTy->isAny() || formalInstanceTy->isAnyObject())) {
+      require(MI->getOperand()->getType().is<ExistentialType>(),
+              "existential_metatype operand must be an existential type");
+      formalInstanceTy =
+          ExistentialType::get(formalInstanceTy)->getCanonicalType();
+    }
     require(isLoweringOf(MI->getOperand()->getType(), formalInstanceTy),
             "existential_metatype result must be formal metatype of "
             "lowered operand type");
@@ -5252,7 +5263,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
       require(AACI->getErrorBB()->getNumArguments() == 1,
               "error successor must take one argument");
       auto arg = AACI->getErrorBB()->getArgument(0);
-      auto errorType = C.getErrorDecl()->getDeclaredType()->getCanonicalType();
+      auto errorType = C.getErrorExistentialType();
       requireSameType(arg->getType(),
                       SILType::getPrimitiveObjectType(errorType),
               "error successor argument must have Error type");
diff --git a/lib/SILGen/ResultPlan.cpp b/lib/SILGen/ResultPlan.cpp
index 8728c07973570..f229d5d497b40 100644
--- a/lib/SILGen/ResultPlan.cpp
+++ b/lib/SILGen/ResultPlan.cpp
@@ -508,7 +508,7 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
     auto continuationDecl = SGF.getASTContext().getUnsafeContinuationDecl();
 
     auto errorTy = throws
-      ? SGF.getASTContext().getExceptionType()
+      ? SGF.getASTContext().getErrorExistentialType()
       : SGF.getASTContext().getNeverType();
     auto continuationTy = BoundGenericType::get(continuationDecl, Type(),
                                                 { calleeTypeInfo.substResultType, errorTy })
@@ -618,7 +618,7 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
 
         auto continuationDecl = SGF.getASTContext().getUnsafeContinuationDecl();
 
-        auto errorTy = SGF.getASTContext().getExceptionType();
+        auto errorTy = SGF.getASTContext().getErrorExistentialType();
         auto continuationBGT =
             BoundGenericType::get(continuationDecl, Type(),
                                   {calleeTypeInfo.substResultType, errorTy});
@@ -666,9 +666,8 @@ class ForeignAsyncInitializationPlan final : public ResultPlan {
       SGF.B.emitBlock(errorBlock);
       
       Scope errorScope(SGF, loc);
-      
-      auto errorTy = SGF.getASTContext().getErrorDecl()->getDeclaredType()
-        ->getCanonicalType();
+
+      auto errorTy = SGF.getASTContext().getErrorExistentialType();
       auto errorVal = SGF.B.createTermResult(
         SILType::getPrimitiveObjectType(errorTy), OwnershipKind::Owned);
 
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index f3febf7c8ed8f..bd85b869b83b9 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -168,6 +168,7 @@ getBridgingFn(Optional<SILDeclRef> &cacheSlot,
 
 #define REQUIRED(X) Types.get##X##Type()
 #define OPTIONAL(X) OptionalType::get(Types.get##X##Type())
+#define EXISTENTIAL(X) getASTContext().get##X##ExistentialType()
 
 #define GET_BRIDGING_FN(Module, FromKind, FromTy, ToKind, ToTy) \
   SILDeclRef SILGenModule::get##FromTy##To##ToTy##Fn() { \
@@ -182,8 +183,8 @@ GET_BRIDGING_FN(Darwin, REQUIRED, Bool, REQUIRED, DarwinBoolean)
 GET_BRIDGING_FN(Darwin, REQUIRED, DarwinBoolean, REQUIRED, Bool)
 GET_BRIDGING_FN(ObjectiveC, REQUIRED, Bool, REQUIRED, ObjCBool)
 GET_BRIDGING_FN(ObjectiveC, REQUIRED, ObjCBool, REQUIRED, Bool)
-GET_BRIDGING_FN(Foundation, OPTIONAL, NSError, REQUIRED, Error)
-GET_BRIDGING_FN(Foundation, REQUIRED, Error, REQUIRED, NSError)
+GET_BRIDGING_FN(Foundation, OPTIONAL, NSError, EXISTENTIAL, Error)
+GET_BRIDGING_FN(Foundation, EXISTENTIAL, Error, REQUIRED, NSError)
 GET_BRIDGING_FN(WinSDK, REQUIRED, Bool, REQUIRED, WindowsBool)
 GET_BRIDGING_FN(WinSDK, REQUIRED, WindowsBool, REQUIRED, Bool)
 
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 1d9b726e7ec3c..c70dd365f471d 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -1252,7 +1252,7 @@ ManagedValue SILGenFunction::emitNativeToBridgedError(SILLocation loc,
   // FIXME: maybe we should use a different entrypoint for this case, to
   // avoid the code size and performance overhead of forming the box?
   nativeError = emitUnabstractedCast(*this, loc, nativeError, nativeType,
-                                     getASTContext().getExceptionType());
+                                     getASTContext().getErrorExistentialType());
 
   auto bridgeFn = emitGlobalFunctionRef(loc, SGM.getErrorToNSErrorFn());
   auto bridgeFnType = bridgeFn->getType().castTo<SILFunctionType>();
diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp
index efa71d2a76708..10a75bbcf3b67 100644
--- a/lib/SILGen/SILGenBuiltin.cpp
+++ b/lib/SILGen/SILGenBuiltin.cpp
@@ -1564,8 +1564,7 @@ static ManagedValue emitBuiltinWithUnsafeContinuation(
 
     Scope errorScope(SGF, loc);
 
-    auto errorTy = SGF.getASTContext().getErrorDecl()->getDeclaredType()
-      ->getCanonicalType();
+    auto errorTy = SGF.getASTContext().getErrorExistentialType();
     auto errorVal = SGF.B.createTermResult(
         SILType::getPrimitiveObjectType(errorTy), OwnershipKind::Owned);
 
diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp
index 20b353e50f822..8ec0c67263735 100644
--- a/lib/SILGen/SILGenConvert.cpp
+++ b/lib/SILGen/SILGenConvert.cpp
@@ -913,8 +913,11 @@ ManagedValue SILGenFunction::emitExistentialMetatypeToObject(SILLocation loc,
 ManagedValue SILGenFunction::emitProtocolMetatypeToObject(SILLocation loc,
                                                           CanType inputTy,
                                                           SILType resultTy) {
-  ProtocolDecl *protocol = inputTy->castTo<MetatypeType>()
-    ->getInstanceType()->castTo<ProtocolType>()->getDecl();
+  auto protocolType = inputTy->castTo<MetatypeType>()->getInstanceType();
+  if (auto existential = protocolType->getAs<ExistentialType>())
+    protocolType = existential->getConstraintType();
+
+  ProtocolDecl *protocol = protocolType->castTo<ProtocolType>()->getDecl();
 
   SILValue value = B.createObjCProtocol(loc, protocol, resultTy);
   
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 45d9840d9dd43..15f720d0c5746 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -1037,8 +1037,7 @@ SILValue SILGenFunction::emitTemporaryAllocation(SILLocation loc, SILType ty,
   if (auto *DRE = loc.getAsASTNode<DeclRefExpr>())
     if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
       if (!isa<ParamDecl>(VD) && VD->isImplicit() &&
-          (VD->getType()->is<ProtocolType>() ||
-           VD->getType()->is<ProtocolCompositionType>()) &&
+          VD->getType()->isExistentialType() &&
           VD->getType()->getExistentialLayout().isErrorExistential()) {
         DbgVar = SILDebugVariable(VD->isLet(), 0);
         loc = SILLocation(VD);
diff --git a/lib/SILGen/SILGenForeignError.cpp b/lib/SILGen/SILGenForeignError.cpp
index 4c95fc44deaa7..30edca104fa74 100644
--- a/lib/SILGen/SILGenForeignError.cpp
+++ b/lib/SILGen/SILGenForeignError.cpp
@@ -134,7 +134,7 @@ namespace {
     SILValue emitBridged(SILGenFunction &SGF, SILLocation loc,
                          CanType bridgedErrorProto) const override {
       auto nativeErrorType = NativeError->getType().getASTType();
-      assert(nativeErrorType == SGF.SGM.getASTContext().getExceptionType());
+      assert(nativeErrorType == SGF.SGM.getASTContext().getErrorExistentialType());
 
       SILValue bridgedError = SGF.emitNativeToBridgedError(loc,
                                 SGF.emitManagedRValueWithCleanup(NativeError),
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index a044e6c57447f..7f6c109adb83c 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -220,7 +220,7 @@ static ManagedValue emitTransformExistential(SILGenFunction &SGF,
     fromInstanceType = cast<MetatypeType>(fromInstanceType)
       .getInstanceType();
     toInstanceType = cast<ExistentialMetatypeType>(toInstanceType)
-      .getInstanceType();
+      ->getExistentialInstanceType()->getCanonicalType();
   }
 
   ArrayRef<ProtocolConformanceRef> conformances =
@@ -3052,8 +3052,13 @@ buildThunkSignature(SILGenFunction &SGF,
   // Add a new generic parameter to replace the opened existential.
   auto *newGenericParam =
       GenericTypeParamType::get(/*type sequence*/ false, depth, 0, ctx);
+
+  auto constraint = openedExistential->getOpenedExistentialType();
+  if (auto existential = constraint->getAs<ExistentialType>())
+    constraint = existential->getConstraintType();
+
   Requirement newRequirement(RequirementKind::Conformance, newGenericParam,
-                             openedExistential->getOpenedExistentialType());
+                             constraint);
 
   auto genericSig = buildGenericSignature(ctx, baseGenericSig,
                                           { newGenericParam },
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index 08f2af1512c12..20f0383d1cf24 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -842,7 +842,7 @@ static SILFunction *emitSelfConformanceWitness(SILGenModule &SGM,
                                           ProtocolConformanceRef(conformance));
 
   // Open the protocol type.
-  auto openedType = OpenedArchetypeType::get(protocolType);
+  auto openedType = OpenedArchetypeType::get(protocol->getExistentialType());
 
   // Form the substitutions for calling the witness.
   auto witnessSubs = SubstitutionMap::getProtocolSubstitutions(protocol,
diff --git a/lib/SILOptimizer/Differentiation/Thunk.cpp b/lib/SILOptimizer/Differentiation/Thunk.cpp
index e9f5a88cafc7d..2f394f4335fa5 100644
--- a/lib/SILOptimizer/Differentiation/Thunk.cpp
+++ b/lib/SILOptimizer/Differentiation/Thunk.cpp
@@ -66,8 +66,13 @@ CanGenericSignature buildThunkSignature(SILFunction *fn, bool inheritGenericSig,
   // Add a new generic parameter to replace the opened existential.
   auto *newGenericParam =
       GenericTypeParamType::get(/*type sequence*/ false, depth, 0, ctx);
+
+  auto constraint = openedExistential->getOpenedExistentialType();
+  if (auto existential = constraint->getAs<ExistentialType>())
+    constraint = existential->getConstraintType();
+
   Requirement newRequirement(RequirementKind::Conformance, newGenericParam,
-                             openedExistential->getOpenedExistentialType());
+                             constraint);
 
   auto genericSig = buildGenericSignature(ctx, baseGenericSig,
                                           { newGenericParam },
diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp
index b1decdc3830da..57aab7934a478 100644
--- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp
+++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp
@@ -95,12 +95,16 @@ bool ExistentialSpecializer::findConcreteTypeFromSoleConformingType(
   auto ArgType = Arg->getType();
   auto SwiftArgType = ArgType.getASTType();
 
+  CanType constraint = SwiftArgType;
+  if (auto existential = constraint->getAs<ExistentialType>())
+    constraint = existential->getConstraintType()->getCanonicalType();
+
   /// Do not handle composition types yet.
-  if (isa<ProtocolCompositionType>(SwiftArgType))
+  if (isa<ProtocolCompositionType>(constraint))
     return false;
   assert(ArgType.isExistentialType());
   /// Find the protocol decl.
-  auto *PD = dyn_cast<ProtocolDecl>(SwiftArgType->getAnyNominal());
+  auto *PD = dyn_cast<ProtocolDecl>(constraint->getAnyNominal());
   if (!PD)
     return false;
 
diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp
index 47173c70b4aac..5b68e78386ad8 100644
--- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp
+++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp
@@ -304,12 +304,17 @@ void ExistentialTransform::convertExistentialArgTypesToGenericArgTypes(
     auto &param = params[Idx];
     auto PType = param.getArgumentType(M, FTy, F->getTypeExpansionContext());
     assert(PType.isExistentialType());
+
+    CanType constraint = PType;
+    if (auto existential = PType->getAs<ExistentialType>())
+      constraint = existential->getConstraintType()->getCanonicalType();
+
     /// Generate new generic parameter.
     auto *NewGenericParam =
         GenericTypeParamType::get(/*type sequence*/ false, Depth, GPIdx++, Ctx);
     genericParams.push_back(NewGenericParam);
     Requirement NewRequirement(RequirementKind::Conformance, NewGenericParam,
-                               PType);
+                               constraint);
     requirements.push_back(NewRequirement);
     ArgToGenericTypeMap.insert(
         std::pair<int, GenericTypeParamType *>(Idx, NewGenericParam));
diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp
index cbeac56f61175..de244e631fbe9 100644
--- a/lib/Sema/BuilderTransform.cpp
+++ b/lib/Sema/BuilderTransform.cpp
@@ -914,14 +914,14 @@ class BuilderClosureVisitor
 
   /// Visit a throw statement, which never produces a result.
   VarDecl *visitThrowStmt(ThrowStmt *throwStmt) {
-    Type exnType = ctx.getErrorDecl()->getDeclaredInterfaceType();
-    if (!exnType) {
+    if (!ctx.getErrorDecl()) {
       hadError = true;
     }
 
     if (cs) {
      SolutionApplicationTarget target(
-         throwStmt->getSubExpr(), dc, CTP_ThrowStmt, exnType,
+         throwStmt->getSubExpr(), dc, CTP_ThrowStmt,
+         ctx.getErrorExistentialType(),
          /*isDiscarded=*/false);
      if (cs->generateConstraints(target, FreeTypeVariableBinding::Disallow))
        hadError = true;
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 9824e6bd3825d..480d93d2374dc 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -1379,6 +1379,8 @@ namespace {
         baseIsInstance = false;
         isExistentialMetatype = baseMeta->is<ExistentialMetatypeType>();
         baseTy = baseMeta->getInstanceType();
+        if (auto existential = baseTy->getAs<ExistentialType>())
+          baseTy = existential->getConstraintType();
 
         // A valid reference to a static member (computed property or a method)
         // declared on a protocol is only possible if result type conforms to
@@ -5346,10 +5348,8 @@ Expr *ExprRewriter::coerceSuperclass(Expr *expr, Type toType) {
 
   while (fromInstanceType->is<AnyMetatypeType>() &&
          toInstanceType->is<MetatypeType>()) {
-    fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()
-      ->getInstanceType();
-    toInstanceType = toInstanceType->castTo<MetatypeType>()
-      ->getInstanceType();
+    fromInstanceType = fromInstanceType->getMetatypeInstanceType();
+    toInstanceType = toInstanceType->getMetatypeInstanceType();
   }
 
   if (fromInstanceType->is<ArchetypeType>()) {
@@ -5422,7 +5422,7 @@ Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType) {
          toInstanceType->is<ExistentialMetatypeType>()) {
     if (!fromInstanceType->is<UnresolvedType>())
       fromInstanceType = fromInstanceType->castTo<AnyMetatypeType>()->getInstanceType();
-    toInstanceType = toInstanceType->castTo<ExistentialMetatypeType>()->getInstanceType();
+    toInstanceType = toInstanceType->castTo<ExistentialMetatypeType>()->getExistentialInstanceType();
   }
 
   ASTContext &ctx = cs.getASTContext();
@@ -7511,7 +7511,7 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
           openedInstanceTy = metaTy->getInstanceType();
           existentialInstanceTy = existentialInstanceTy
             ->castTo<ExistentialMetatypeType>()
-            ->getInstanceType();
+            ->getExistentialInstanceType();
         }
         assert(openedInstanceTy->castTo<OpenedArchetypeType>()
                    ->getOpenedExistentialType()
diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp
index c665235bece3e..6bcd97622ebc4 100644
--- a/lib/Sema/CSClosure.cpp
+++ b/lib/Sema/CSClosure.cpp
@@ -621,13 +621,12 @@ class ClosureConstraintGenerator
     assert(isSupportedMultiStatementClosure() &&
            "Unsupported statement: Throw");
 
-    Type errType =
-        cs.getASTContext().getErrorDecl()->getDeclaredInterfaceType();
-    if (!errType) {
+    if (!cs.getASTContext().getErrorDecl()) {
       hadError = true;
       return;
     }
 
+    auto errType = cs.getASTContext().getErrorExistentialType();
     auto *errorExpr = throwStmt->getSubExpr();
 
     createConjunction(
@@ -739,7 +738,7 @@ class ClosureConstraintGenerator
         auto *switchStmt = cast<SwitchStmt>(parent.get<Stmt *>());
         contextualTy = cs.getType(switchStmt->getSubjectExpr());
       } else if (parent.isStmt(StmtKind::DoCatch)) {
-        contextualTy = cs.getASTContext().getExceptionType();
+        contextualTy = cs.getASTContext().getErrorExistentialType();
       } else {
         hadError = true;
         return;
diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp
index 52b58b3808242..1418b0e7c4a6b 100644
--- a/lib/Sema/CSDiagnostics.cpp
+++ b/lib/Sema/CSDiagnostics.cpp
@@ -221,6 +221,10 @@ ValueDecl *RequirementFailure::getDeclRef() const {
     // diagnostic directly to its declaration without desugaring.
     if (auto *alias = dyn_cast<TypeAliasType>(type.getPointer()))
       return alias->getDecl();
+
+    if (auto existential = type->getAs<ExistentialType>())
+      return existential->getConstraintType()->getAnyGeneric();
+
     return type->getAnyGeneric();
   };
 
@@ -531,10 +535,14 @@ bool MissingConformanceFailure::diagnoseTypeCannotConform(
     return false;
   }
 
+  Type constraintType = nonConformingType;
+  if (auto existential = constraintType->getAs<ExistentialType>())
+    constraintType = existential->getConstraintType();
+
   emitDiagnostic(diag::type_cannot_conform,
                  nonConformingType->isExistentialType(), 
                  nonConformingType, 
-                 nonConformingType->isEqual(protocolType),
+                 constraintType->isEqual(protocolType),
                  protocolType);
 
   bool emittedSpecializedNote = false;
@@ -2328,9 +2336,13 @@ bool ContextualFailure::diagnoseAsError() {
 
     if (CTP == CTP_ForEachStmt || CTP == CTP_ForEachSequence) {
       if (fromType->isAnyExistentialType()) {
+        Type constraintType = fromType;
+        if (auto existential = constraintType->getAs<ExistentialType>())
+          constraintType = existential->getConstraintType();
+
         emitDiagnostic(diag::type_cannot_conform,
                        /*isExistentialType=*/true, fromType, 
-                       fromType->isEqual(toType), toType);
+                       constraintType->isEqual(toType), toType);
         emitDiagnostic(diag::only_concrete_types_conform_to_protocols);
         return true;
       }
@@ -3063,7 +3075,10 @@ bool ContextualFailure::tryProtocolConformanceFixIt(
   // the protocols of the composition, then store the composition directly.
   // This is because we need to append 'Foo & Bar' instead of 'Foo, Bar' in
   // order to match the written type.
-  if (auto compositionTy = unwrappedToType->getAs<ProtocolCompositionType>()) {
+  auto constraint = unwrappedToType;
+  if (auto existential = constraint->getAs<ExistentialType>())
+    constraint = existential->getConstraintType();
+  if (auto compositionTy = constraint->getAs<ProtocolCompositionType>()) {
     if (compositionTy->getMembers().size() == missingProtoTypeStrings.size()) {
       missingProtoTypeStrings = {compositionTy->getString()};
     }
@@ -3651,7 +3666,8 @@ bool MissingMemberFailure::diagnoseAsError() {
       diagnostic.highlight(getSourceRange())
           .highlight(nameLoc.getSourceRange());
       correction->addFixits(diagnostic);
-    } else if (instanceTy->getAnyNominal() &&
+    } else if ((instanceTy->getAnyNominal() ||
+                instanceTy->is<ExistentialType>()) &&
                getName().getBaseName() == DeclBaseName::createConstructor()) {
       auto &cs = getConstraintSystem();
 
@@ -4123,7 +4139,11 @@ bool AllowTypeOrInstanceMemberFailure::diagnoseAsError() {
           // If we are in a protocol extension of 'Proto' and we see
           // 'Proto.static', suggest 'Self.static'
           if (auto extensionContext = parent->getExtendedProtocolDecl()) {
-            if (extensionContext->getDeclaredType()->isEqual(instanceTy)) {
+            auto constraint = instanceTy;
+            if (auto existential = constraint->getAs<ExistentialType>())
+              constraint = existential->getConstraintType();
+
+            if (extensionContext->getDeclaredType()->isEqual(constraint)) {
               Diag->fixItReplace(getSourceRange(), "Self");
             }
           }
@@ -6838,10 +6858,14 @@ bool AssignmentTypeMismatchFailure::diagnoseMissingConformance() const {
 
   auto retrieveProtocols = [](Type type,
                               llvm::SmallPtrSetImpl<ProtocolDecl *> &members) {
-    if (auto *protocol = type->getAs<ProtocolType>())
+    auto constraint = type;
+    if (auto existential = constraint->getAs<ExistentialType>())
+      constraint = existential->getConstraintType();
+
+    if (auto *protocol = constraint->getAs<ProtocolType>())
       members.insert(protocol->getDecl());
 
-    if (auto *composition = type->getAs<ProtocolCompositionType>()) {
+    if (auto *composition = constraint->getAs<ProtocolCompositionType>()) {
       for (auto member : composition->getMembers()) {
         if (auto *protocol = member->getAs<ProtocolType>())
           members.insert(protocol->getDecl());
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 172e31d7ce545..1124286eefd70 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -2886,42 +2886,40 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
     return result;
   }
 
-  // Handle protocol compositions.
-  if (auto existential1 = type1->getAs<ProtocolCompositionType>()) {
-    if (auto existential2 = type2->getAs<ProtocolCompositionType>()) {
-      auto layout1 = existential1->getExistentialLayout();
-      auto layout2 = existential2->getExistentialLayout();
-
-      // Explicit AnyObject and protocols must match exactly.
-      if (layout1.hasExplicitAnyObject != layout2.hasExplicitAnyObject)
-        return getTypeMatchFailure(locator);
+  // Handle existential types.
+  if (type1->isExistentialType() && type2->isExistentialType()) {
+    auto layout1 = type1->getExistentialLayout();
+    auto layout2 = type2->getExistentialLayout();
 
-      if (layout1.getProtocols().size() != layout2.getProtocols().size())
-        return getTypeMatchFailure(locator);
+    // Explicit AnyObject and protocols must match exactly.
+    if (layout1.hasExplicitAnyObject != layout2.hasExplicitAnyObject)
+      return getTypeMatchFailure(locator);
 
-      for (unsigned i: indices(layout1.getProtocols())) {
-        if (!layout1.getProtocols()[i]->isEqual(layout2.getProtocols()[i]))
-          return getTypeMatchFailure(locator);
-      }
+    if (layout1.getProtocols().size() != layout2.getProtocols().size())
+      return getTypeMatchFailure(locator);
 
-      // This is the only interesting case. We might have type variables
-      // on either side of the superclass constraint, so make sure we
-      // recursively call matchTypes() here.
-      if (layout1.explicitSuperclass || layout2.explicitSuperclass) {
-        if (!layout1.explicitSuperclass || !layout2.explicitSuperclass)
-          return getTypeMatchFailure(locator);
+    for (unsigned i: indices(layout1.getProtocols())) {
+      if (!layout1.getProtocols()[i]->isEqual(layout2.getProtocols()[i]))
+        return getTypeMatchFailure(locator);
+    }
 
-        auto result = matchTypes(layout1.explicitSuperclass,
-                                 layout2.explicitSuperclass,
-                                 ConstraintKind::Bind, subflags,
-                                 locator.withPathElement(
-                                   ConstraintLocator::ExistentialSuperclassType));
-        if (result.isFailure())
-          return result;
-      }
+    // This is the only interesting case. We might have type variables
+    // on either side of the superclass constraint, so make sure we
+    // recursively call matchTypes() here.
+    if (layout1.explicitSuperclass || layout2.explicitSuperclass) {
+      if (!layout1.explicitSuperclass || !layout2.explicitSuperclass)
+        return getTypeMatchFailure(locator);
 
-      return getTypeMatchSuccess();
+      auto result = matchTypes(layout1.explicitSuperclass,
+                               layout2.explicitSuperclass,
+                               ConstraintKind::Bind, subflags,
+                               locator.withPathElement(
+                                 ConstraintLocator::ExistentialSuperclassType));
+      if (result.isFailure())
+        return result;
     }
+
+    return getTypeMatchSuccess();
   }
   // Handle nominal types that are not directly generic.
   if (auto nominal1 = type1->getAs<NominalType>()) {
@@ -6033,8 +6031,12 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
               return true;
           return false;
         };
+
+        auto constraintType = meta1->getInstanceType();
+        if (auto existential = constraintType->getAs<ExistentialType>())
+          constraintType = existential->getConstraintType();
         
-        if (auto protoTy = meta1->getInstanceType()->getAs<ProtocolType>()) {
+        if (auto protoTy = constraintType->getAs<ProtocolType>()) {
           if (protoTy->getDecl()->isObjC()
               && isProtocolClassType(type2)) {
             increaseScore(ScoreKind::SK_UserConversion);
@@ -7007,7 +7009,7 @@ static bool isCastToExpressibleByNilLiteral(ConstraintSystem &cs, Type fromType,
   if (!nilLiteral)
     return false;
 
-  return toType->isEqual(nilLiteral->getDeclaredType()) &&
+  return toType->isEqual(nilLiteral->getExistentialType()) &&
          fromType->getOptionalObjectType();
 }
 
@@ -9808,7 +9810,7 @@ ConstraintSystem::simplifyOpenedExistentialOfConstraint(
     auto instanceTy = type2;
     if (auto metaTy = type2->getAs<ExistentialMetatypeType>()) {
       isMetatype = true;
-      instanceTy = metaTy->getInstanceType();
+      instanceTy = metaTy->getExistentialInstanceType();
     }
     assert(instanceTy->isExistentialType());
     Type openedTy = OpenedArchetypeType::get(instanceTy);
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 258738a70b0b9..61042497b768b 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1767,6 +1767,13 @@ ConstraintSystem::getTypeOfMemberReference(
     auto memberTy = TypeChecker::substMemberTypeWithBase(DC->getParentModule(),
                                                          typeDecl, baseObjTy);
 
+    // If the member type is a constraint, e.g. because the
+    // reference is to a typealias with an underlying protocol
+    // or composition type, the member reference has existential
+    // type.
+    if (memberTy->isConstraintType())
+      memberTy = ExistentialType::get(memberTy);
+
     checkNestedTypeConstraints(*this, memberTy, locator);
 
     // Convert any placeholders and open any generics.
@@ -1995,8 +2002,12 @@ ConstraintSystem::getTypeOfMemberReference(
         if (t->isEqual(selfTy))
           return baseObjTy;
       if (auto *metatypeTy = t->getAs<MetatypeType>())
-        if (metatypeTy->getInstanceType()->isEqual(selfTy))
-          return ExistentialMetatypeType::get(baseObjTy);
+        if (metatypeTy->getInstanceType()->isEqual(selfTy)) {
+          auto constraint = baseObjTy;
+          if (auto existential = baseObjTy->getAs<ExistentialType>())
+            constraint = existential->getConstraintType();
+          return ExistentialMetatypeType::get(constraint);
+        }
       return t;
     });
   }
@@ -2146,7 +2157,8 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator,
     } else if (isa<AbstractFunctionDecl>(decl) || isa<EnumElementDecl>(decl)) {
       if (decl->isInstanceMember() &&
           (!overload.getBaseType() ||
-           !overload.getBaseType()->getAnyNominal()))
+           (!overload.getBaseType()->getAnyNominal() &&
+            !overload.getBaseType()->is<ExistentialType>())))
         return Type();
 
       // Cope with 'Self' returns.
@@ -2506,14 +2518,16 @@ FunctionType::ExtInfo ClosureEffectsRequest::evaluate(
       // Okay, now it should be safe to coerce the pattern.
       // Pull the top-level pattern back out.
       pattern = LabelItem.getPattern();
-      Type exnType = DC->getASTContext().getErrorDecl()->getDeclaredInterfaceType();
 
-      if (!exnType)
+      auto &ctx = DC->getASTContext();
+      if (!ctx.getErrorDecl())
         return false;
+
       auto contextualPattern =
           ContextualPattern::forRawPattern(pattern, DC);
       pattern = TypeChecker::coercePatternToType(
-        contextualPattern, exnType, TypeResolverContext::InExpression);
+        contextualPattern, ctx.getErrorExistentialType(),
+        TypeResolverContext::InExpression);
       if (!pattern)
         return false;
 
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index a3b9730280f7b..3273cb60d04da 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -1211,7 +1211,7 @@ static FuncDecl *deriveEncodable_encode(DerivedConformance &derived) {
   //                         output: ()
   // Create from the inside out:
 
-  auto encoderType = C.getEncoderType();
+  auto encoderType = ExistentialType::get(C.getEncoderType());
   auto returnType = TupleType::getEmpty(C);
 
   // Params: (Encoder)
@@ -1802,7 +1802,7 @@ static ValueDecl *deriveDecodable_init(DerivedConformance &derived) {
   // Compute from the inside out:
 
   // Params: (Decoder)
-  auto decoderType = C.getDecoderType();
+  auto decoderType = ExistentialType::get(C.getDecoderType());
   auto *decoderParamDecl = new (C) ParamDecl(
       SourceLoc(), SourceLoc(), C.Id_from,
       SourceLoc(), C.Id_decoder, conformanceDC);
diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp
index 5b9d1da40891a..e1b1d6813f512 100644
--- a/lib/Sema/TypeCheckAccess.cpp
+++ b/lib/Sema/TypeCheckAccess.cpp
@@ -783,7 +783,12 @@ class AccessControlChecker : public AccessControlCheckerBase,
                               Type());
     }
 
-    auto declKindForType = [](Type type) {
+    auto declKindForType = [](Type type) -> DescriptiveDeclKind {
+      // If this is an existential type, use the decl kind of
+      // its constraint type.
+      if (auto existential = type->getAs<ExistentialType>())
+        type = existential->getConstraintType();
+
       if (isa<TypeAliasType>(type.getPointer()))
         return DescriptiveDeclKind::TypeAlias;
       else if (auto nominal = type->getAnyNominal())
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 77ef0a640a3dd..e310765773040 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -3000,8 +3000,10 @@ void AttributeChecker::visitImplementsAttr(ImplementsAttr *attr) {
 
   Type T = attr->getProtocolType();
   if (!T && attr->getProtocolTypeRepr()) {
+    auto context = TypeResolverContext::GenericRequirement;
     T = TypeResolution::resolveContextualType(attr->getProtocolTypeRepr(), DC,
-                                              None, /*unboundTyOpener*/ nullptr,
+                                              TypeResolutionOptions(context),
+                                              /*unboundTyOpener*/ nullptr,
                                               /*placeholderHandler*/ nullptr);
   }
 
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 1224ebd7bce03..8d0aa0d38d5ae 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -1712,13 +1712,16 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
     //   }
     // }
     //
+    auto constraint = fromType;
+    if (auto existential = constraint->getAs<ExistentialType>())
+      constraint = existential->getConstraintType();
     if (auto *protocolDecl =
-          dyn_cast_or_null<ProtocolDecl>(fromType->getAnyNominal())) {
+          dyn_cast_or_null<ProtocolDecl>(constraint->getAnyNominal())) {
       if (!couldDynamicallyConformToProtocol(toType, protocolDecl, module)) {
         return failed();
       }
     } else if (auto protocolComposition =
-                   fromType->getAs<ProtocolCompositionType>()) {
+                   constraint->getAs<ProtocolCompositionType>()) {
       if (llvm::any_of(protocolComposition->getMembers(),
                        [&](Type protocolType) {
                          if (auto protocolDecl = dyn_cast_or_null<ProtocolDecl>(
@@ -1973,6 +1976,12 @@ static bool checkForDynamicAttribute(CanType ty,
     }
   }
 
+  // If this is an existential type, check if its constraint type
+  // has the attribute.
+  if (auto existential = ty->getAs<ExistentialType>()) {
+    return hasAttribute(existential->getConstraintType());
+  }
+
   // If this is a protocol composition, check if any of its members have the
   // attribute.
   if (auto protocolComp = dyn_cast<ProtocolCompositionType>(ty)) {
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 08eba2bf58742..29afff0f8897a 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -1899,6 +1899,14 @@ bool swift::isMemberOperator(FuncDecl *decl, Type type) {
     }
 
     if (isProtocol) {
+      // FIXME: Source compatibility hack for Swift 5. The compiler
+      // accepts member operators on protocols with existential
+      // type arguments. We should consider banning this in Swift 6.
+      if (auto existential = paramType->getAs<ExistentialType>()) {
+        if (selfNominal == existential->getConstraintType()->getAnyNominal())
+          return true;
+      }
+
       // For a protocol, is it the 'Self' type parameter?
       if (auto genericParam = paramType->getAs<GenericTypeParamType>())
         if (genericParam->isEqual(DC->getSelfInterfaceType()))
diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp
index e6b7906a80a04..817d30eac58f6 100644
--- a/lib/Sema/TypeCheckDeclObjC.cpp
+++ b/lib/Sema/TypeCheckDeclObjC.cpp
@@ -806,7 +806,8 @@ bool swift::isRepresentableInObjC(
     Optional<unsigned> completionHandlerErrorParamIndex;
     if (FD->hasThrows()) {
       completionHandlerErrorParamIndex = completionHandlerParams.size();
-      addCompletionHandlerParam(OptionalType::get(ctx.getExceptionType()));
+      auto errorType = ctx.getErrorExistentialType();
+      addCompletionHandlerParam(OptionalType::get(errorType));
     }
 
     Type completionHandlerType = FunctionType::get(
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 86cc1c175c58b..28ef660793272 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -4783,6 +4783,19 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup(
     auto memberType = TypeChecker::substMemberTypeWithBase(DC->getParentModule(),
                                                            typeDecl, Adoptee);
 
+    // Type witnesses that resolve to constraint types are always
+    // existential types. This can only happen when the type witness
+    // is explicitly written with a type alias. The type alias itself
+    // is still a constraint type because it can be used as both a
+    // type witness and as a generic constraint.
+    //
+    // With SE-0335, using a type alias as both a type witness and a generic
+    // constraint will be disallowed in Swift 6, because existential types
+    // must be explicit, and a generic constraint isn't a valid type witness.
+    if (memberType->isConstraintType()) {
+      memberType = ExistentialType::get(memberType);
+    }
+
     if (!viableTypes.insert(memberType->getCanonicalType()).second)
       continue;
 
@@ -5256,8 +5269,11 @@ void swift::diagnoseConformanceFailure(Type T,
       TypeChecker::containsProtocol(T, Proto, DC->getParentModule())) {
 
     if (!T->isObjCExistentialType()) {
+      Type constraintType = T;
+      if (auto existential = T->getAs<ExistentialType>())
+        constraintType = existential->getConstraintType();
       diags.diagnose(ComplainLoc, diag::type_cannot_conform, true,
-                     T, T->isEqual(Proto->getDeclaredInterfaceType()), 
+                     T, constraintType->isEqual(Proto->getDeclaredInterfaceType()),
                      Proto->getDeclaredInterfaceType());
       diags.diagnose(ComplainLoc,
                      diag::only_concrete_types_conform_to_protocols);
@@ -5390,7 +5406,10 @@ TypeChecker::containsProtocol(Type T, ProtocolDecl *Proto, ModuleDecl *M,
   if (T->isExistentialType()) {
     // Handle the special case of the Error protocol, which self-conforms
     // *and* has a witness table.
-    if (T->isEqual(Proto->getDeclaredInterfaceType()) &&
+    auto constraint = T;
+    if (auto existential = T->getAs<ExistentialType>())
+      constraint = existential->getConstraintType();
+    if (constraint->isEqual(Proto->getDeclaredInterfaceType()) &&
         Proto->requiresSelfConformanceWitnessTable()) {
       auto &ctx = M->getASTContext();
       return ProtocolConformanceRef(ctx.getSelfConformance(Proto));
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 3b7ba396b179e..533eec0efd238 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -855,10 +855,11 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
     // Coerce the operand to the exception type.
     auto E = TS->getSubExpr();
 
-    Type exnType = getASTContext().getErrorDecl()->getDeclaredInterfaceType();
-    if (!exnType) return TS;
+    if (!getASTContext().getErrorDecl())
+      return TS;
 
-    TypeChecker::typeCheckExpression(E, DC, {exnType, CTP_ThrowStmt});
+    Type errorType = getASTContext().getErrorExistentialType();
+    TypeChecker::typeCheckExpression(E, DC, {errorType, CTP_ThrowStmt});
     TS->setSubExpr(E);
 
     return TS;
@@ -1205,7 +1206,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
     auto catches = S->getCatches();
     checkSiblingCaseStmts(catches.begin(), catches.end(),
                           CaseParentKind::DoCatch, limitExhaustivityChecks,
-                          getASTContext().getExceptionType());
+                          getASTContext().getErrorExistentialType());
 
     return S;
   }
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 2e847303218f5..d96094b47393f 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -2274,7 +2274,13 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
           Optional<MetatypeRepresentation> storedRepr;
           // The instance type is not a SIL type.
           auto instanceOptions = options;
-          instanceOptions.setContext(None);
+          TypeResolverContext context = TypeResolverContext::None;
+          if (isa<MetatypeTypeRepr>(repr)) {
+            context = TypeResolverContext::MetatypeBase;
+          } else if (isa<ProtocolTypeRepr>(repr)) {
+            context = TypeResolverContext::ProtocolMetatypeBase;
+          }
+          instanceOptions.setContext(context);
           instanceOptions -= TypeResolutionFlags::SILType;
 
           auto instanceTy = resolveType(base, instanceOptions);
@@ -3166,7 +3172,8 @@ NeverNullType TypeResolver::resolveSILFunctionType(
 
   ProtocolConformanceRef witnessMethodConformance;
   if (witnessMethodProtocol) {
-    auto resolved = resolveType(witnessMethodProtocol, options);
+    auto resolved = resolveType(witnessMethodProtocol,
+        options.withContext(TypeResolverContext::GenericRequirement));
     if (resolved->hasError())
       return resolved;
 
@@ -3442,11 +3449,7 @@ TypeResolver::resolveIdentifierType(IdentTypeRepr *IdType,
     return ErrorType::get(getASTContext());
   }
 
-  // FIXME: Don't use ExistentialType for AnyObject for now.
-  bool isConstraintType = (result->is<ProtocolType>() &&
-                           !result->isAnyObject());
-  if (isConstraintType &&
-      getASTContext().LangOpts.EnableExplicitExistentialTypes &&
+  if (result->isConstraintType() &&
       options.isConstraintImplicitExistential()) {
     return ExistentialType::get(result);
   }
@@ -3807,7 +3810,7 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr,
       continue;
     }
 
-    if (ty->isExistentialType()) {
+    if (ty->isConstraintType()) {
       auto layout = ty->getExistentialLayout();
       if (auto superclass = layout.explicitSuperclass)
         if (checkSuperclass(tyR->getStartLoc(), superclass))
@@ -3835,10 +3838,8 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr,
   auto composition =
       ProtocolCompositionType::get(getASTContext(), Members,
                                    /*HasExplicitAnyObject=*/false);
-  if (getASTContext().LangOpts.EnableExplicitExistentialTypes &&
-      options.isConstraintImplicitExistential() &&
-      !composition->isAny()) {
-    composition = ExistentialType::get(composition);
+  if (options.isConstraintImplicitExistential()) {
+    return ExistentialType::get(composition);
   }
   return composition;
 }
@@ -3861,14 +3862,6 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr,
     return constraintType;
   }
 
-  // Warn about `any Any` and `any AnyObject`.
-  if (constraintType->isAny() || constraintType->isAnyObject()) {
-    diagnose(repr->getLoc(), diag::unnecessary_any,
-             constraintType)
-      .fixItRemove({anyStart, anyEnd});
-    return constraintType;
-  }
-
   return ExistentialType::get(constraintType);
 }
 
@@ -4085,7 +4078,8 @@ class ExistentialTypeVisitor
       if (proto->existentialRequiresAny()) {
         Ctx.Diags.diagnose(comp->getNameLoc(),
                            diag::existential_requires_any,
-                           proto->getName());
+                           proto->getName())
+            .limitBehavior(DiagnosticBehavior::Warning);
       }
     } else if (auto *alias = dyn_cast_or_null<TypeAliasDecl>(comp->getBoundDecl())) {
       auto type = Type(alias->getDeclaredInterfaceType()->getDesugaredType());
@@ -4101,7 +4095,8 @@ class ExistentialTypeVisitor
 
             Ctx.Diags.diagnose(comp->getNameLoc(),
                                diag::existential_requires_any,
-                               protoDecl->getName());
+                               protoDecl->getName())
+                .limitBehavior(DiagnosticBehavior::Warning);
           }
         }
         return false;
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 4e6678f7c7821..96593dd81be82 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -6117,6 +6117,7 @@ Expected<Type> TypeDeserializer::getTypeCheckedImpl() {
   CASE(SequenceArchetype)
   CASE(GenericTypeParam)
   CASE(ProtocolComposition)
+  CASE(Existential)
   CASE(DependentMember)
   CASE(BoundGeneric)
   CASE(SILBlockStorage)
diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h
index 7af4335eb0faa..1ea761faf1e58 100644
--- a/lib/Serialization/ModuleFormat.h
+++ b/lib/Serialization/ModuleFormat.h
@@ -56,7 +56,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
 /// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t SWIFTMODULE_VERSION_MINOR = 655; // dealloc_stack_ref
+const uint16_t SWIFTMODULE_VERSION_MINOR = 656; // enable explicit existentials
 
 /// A standard hash seed used for all string hashes in a serialized module.
 ///
diff --git a/stdlib/public/Reflection/TypeRefBuilder.cpp b/stdlib/public/Reflection/TypeRefBuilder.cpp
index a85eab6dfb3b1..d7a88e95136a3 100644
--- a/stdlib/public/Reflection/TypeRefBuilder.cpp
+++ b/stdlib/public/Reflection/TypeRefBuilder.cpp
@@ -30,8 +30,10 @@
 using namespace swift;
 using namespace reflection;
 
-TypeRefBuilder::BuiltType TypeRefBuilder::decodeMangledType(Node *node) {
-  return swift::Demangle::decodeMangledType(*this, node).getType();
+TypeRefBuilder::BuiltType
+TypeRefBuilder::decodeMangledType(Node *node, bool forRequirement) {
+  return swift::Demangle::decodeMangledType(*this, node, forRequirement)
+      .getType();
 }
 
 RemoteRef<char> TypeRefBuilder::readTypeRef(uint64_t remoteAddr) {
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index ebcfe07948695..d0748a1a3aefb 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -1314,8 +1314,10 @@ class DecodedMetadataBuilder {
   using BuiltTypeDecl = const ContextDescriptor *;
   using BuiltProtocolDecl = ProtocolDescriptorRef;
 
-  BuiltType decodeMangledType(NodePointer node) {
-    return Demangle::decodeMangledType(*this, node).getType();
+  BuiltType decodeMangledType(NodePointer node,
+                              bool forRequirement = true) {
+    return Demangle::decodeMangledType(*this, node, forRequirement)
+        .getType();
   }
 
   Demangle::NodeFactory &getNodeFactory() { return demangler; }
@@ -1483,7 +1485,8 @@ class DecodedMetadataBuilder {
 
   TypeLookupErrorOr<BuiltType>
   createProtocolCompositionType(llvm::ArrayRef<BuiltProtocolDecl> protocols,
-                                BuiltType superclass, bool isClassBound) const {
+                                BuiltType superclass, bool isClassBound,
+                                bool forRequirement = true) const {
     // Determine whether we have a class bound.
     ProtocolClassConstraint classConstraint = ProtocolClassConstraint::Any;
     if (isClassBound || superclass) {
diff --git a/test/ClangImporter/objc_bridging_generics.swift b/test/ClangImporter/objc_bridging_generics.swift
index 8de2c4b6be402..b819a82433f2e 100644
--- a/test/ClangImporter/objc_bridging_generics.swift
+++ b/test/ClangImporter/objc_bridging_generics.swift
@@ -1,4 +1,5 @@
 // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -verify -swift-version 4 -I %S/Inputs/custom-modules %s
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -parse-as-library -enable-explicit-existential-types -verify -swift-version 4 -I %S/Inputs/custom-modules %s
 
 // REQUIRES: objc_interop
 
diff --git a/test/Constraints/common_type_objc.swift b/test/Constraints/common_type_objc.swift
index 35a7239ae08cf..94596747ae77b 100644
--- a/test/Constraints/common_type_objc.swift
+++ b/test/Constraints/common_type_objc.swift
@@ -1,6 +1,9 @@
 // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s -debug-constraints 2>%t.err
 // RUN: %FileCheck %s < %t.err
 
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify -enable-explicit-existential-types %s -debug-constraints 2>%t.err
+// RUN: %FileCheck %s < %t.err
+
 // REQUIRES: objc_interop
 
 import Foundation
diff --git a/test/Constraints/openExistential.swift b/test/Constraints/openExistential.swift
index a50d1ef26daea..48dcfb383df5b 100644
--- a/test/Constraints/openExistential.swift
+++ b/test/Constraints/openExistential.swift
@@ -1,4 +1,5 @@
 // RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -enable-explicit-existential-types
 
 protocol P { }
 
diff --git a/test/Constraints/protocols.swift b/test/Constraints/protocols.swift
index f82e45f3ee30b..ec390422e8dcd 100644
--- a/test/Constraints/protocols.swift
+++ b/test/Constraints/protocols.swift
@@ -1,4 +1,5 @@
 // RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -enable-explicit-existential-types
 
 protocol Fooable { func foo() }
 protocol Barable { func bar() }
diff --git a/test/Generics/function_defs.swift b/test/Generics/function_defs.swift
index 8b5d8499ebfa3..04f2f8e7f9a79 100644
--- a/test/Generics/function_defs.swift
+++ b/test/Generics/function_defs.swift
@@ -34,7 +34,7 @@ func min<T : MethodLessComparable>(_ x: T, y: T) -> T {
 //===----------------------------------------------------------------------===//
 
 func existential<T : EqualComparable, U : EqualComparable>(_ t1: T, t2: T, u: U) {
-  var eqComp : EqualComparable = t1 // Ok
+  var eqComp : EqualComparable = t1 // expected-warning {{protocol 'EqualComparable' as a type must be explicitly marked as 'any'}}
   eqComp = u
   if t1.isEqual(eqComp) {} // expected-error{{cannot convert value of type 'EqualComparable' to expected argument type 'T'}}
   if eqComp.isEqual(t2) {} // expected-error{{member 'isEqual' cannot be used on value of protocol type 'EqualComparable'; use a generic constraint instead}}
@@ -49,11 +49,11 @@ func otherExistential<T : EqualComparable>(_ t1: T) {
   otherEqComp = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}}
   _ = otherEqComp
   
-  var otherEqComp2 : OtherEqualComparable // Ok
+  var otherEqComp2 : any OtherEqualComparable // Ok
   otherEqComp2 = t1 // expected-error{{value of type 'T' does not conform to 'OtherEqualComparable' in assignment}}
   _ = otherEqComp2
 
-  _ = t1 as EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}}
+  _ = t1 as any EqualComparable & OtherEqualComparable // expected-error{{value of type 'T' does not conform to 'EqualComparable & OtherEqualComparable' in coercion}}
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/test/SILGen/protocol_with_superclass.swift b/test/SILGen/protocol_with_superclass.swift
index 8f3c86bc2f9bc..e389e5c9a59a5 100644
--- a/test/SILGen/protocol_with_superclass.swift
+++ b/test/SILGen/protocol_with_superclass.swift
@@ -1,6 +1,9 @@
 // RUN: %target-swift-emit-silgen %s | %FileCheck %s
 // RUN: %target-swift-frontend -emit-ir %s
 
+// RUN: %target-swift-emit-silgen -enable-explicit-existential-types %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-ir -enable-explicit-existential-types %s
+
 // Protocols with superclass-constrained Self.
 
 class Concrete {
diff --git a/test/SILGen/subclass_existentials.swift b/test/SILGen/subclass_existentials.swift
index 7141a054bfe8b..e0d1de9bf6f27 100644
--- a/test/SILGen/subclass_existentials.swift
+++ b/test/SILGen/subclass_existentials.swift
@@ -2,6 +2,9 @@
 // RUN: %target-swift-emit-silgen -module-name subclass_existentials -Xllvm -sil-full-demangle -parse-as-library -primary-file %s -verify | %FileCheck %s
 // RUN: %target-swift-emit-ir -module-name subclass_existentials -parse-as-library -primary-file %s
 
+// RUN: %target-swift-emit-silgen -module-name subclass_existentials -Xllvm -sil-full-demangle -parse-as-library -enable-explicit-existential-types -primary-file %s -verify | %FileCheck %s
+// RUN: %target-swift-emit-ir -module-name subclass_existentials -parse-as-library -enable-explicit-existential-types -primary-file %s
+
 // Note: we pass -verify above to ensure there are no spurious
 // compiler warnings relating to casts.
 
diff --git a/test/Sema/type_join.swift b/test/Sema/type_join.swift
index 3de393ed929e4..8b856bb2f9075 100644
--- a/test/Sema/type_join.swift
+++ b/test/Sema/type_join.swift
@@ -1,4 +1,5 @@
 // RUN: %target-typecheck-verify-swift -parse-stdlib
+// RUN: %target-typecheck-verify-swift -parse-stdlib -enable-explicit-existential-types
 
 import Swift
 
diff --git a/test/decl/nested/protocol.swift b/test/decl/nested/protocol.swift
index f6f261bfdd35d..2bda50bf6ee46 100644
--- a/test/decl/nested/protocol.swift
+++ b/test/decl/nested/protocol.swift
@@ -31,7 +31,7 @@ protocol OuterProtocol {
 struct ConformsToOuterProtocol : OuterProtocol {
   typealias Hen = Int
 
-  func f() { let _ = InnerProtocol.self } // Ok
+  func f() { let _ = InnerProtocol.self } // expected-warning {{protocol 'InnerProtocol' as a type must be explicitly marked as 'any'}}
 }
 
 protocol Racoon {
diff --git a/test/decl/protocol/conforms/inherited.swift b/test/decl/protocol/conforms/inherited.swift
index 33e50e5ee418b..8b54508922117 100644
--- a/test/decl/protocol/conforms/inherited.swift
+++ b/test/decl/protocol/conforms/inherited.swift
@@ -167,13 +167,13 @@ class B : A {
 }
 
 func testB(_ b: B) {
-  var _: P1 = b
-  var _: P4 = b
+  var _: P1 = b // expected-warning {{protocol 'P1' as a type must be explicitly marked as 'any'}}
+  var _: P4 = b // expected-warning {{protocol 'P4' as a type must be explicitly marked as 'any'}}
   var _: P5 = b
   var _: P6 = b
-  var _: P7 = b
+  var _: P7 = b // expected-warning {{protocol 'P7' as a type must be explicitly marked as 'any'}}
   var _: P8 = b
-  var _: P9 = b
+  var _: P9 = b // expected-warning {{protocol 'P9' as a type must be explicitly marked as 'any'}}
 }
 
 // Class A5 conforms to P5 in an inheritable manner.
diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift
index 89a12f2f7cf1f..c002d33a1f6e1 100644
--- a/test/decl/protocol/protocols.swift
+++ b/test/decl/protocol/protocols.swift
@@ -119,7 +119,7 @@ struct Circle {
 func testCircular(_ circle: Circle) {
   // FIXME: It would be nice if this failure were suppressed because the protocols
   // have circular definitions.
-  _ = circle as CircleStart // expected-error{{value of type 'Circle' does not conform to 'CircleStart' in coercion}}
+  _ = circle as any CircleStart // expected-error{{value of type 'Circle' does not conform to 'CircleStart' in coercion}}
 }
 
 // <rdar://problem/14750346>
@@ -439,17 +439,17 @@ func g<T : C2>(_ x : T) {
 
 class C3 : P1 {} // expected-error{{type 'C3' does not conform to protocol 'P1'}}
 func h<T : C3>(_ x : T) {
-  _ = x as P1
+  _ = x as any P1
 }
 func i<T : C3>(_ x : T?) -> Bool {
-  return x is P1
+  return x is any P1
   // expected-warning@-1 {{checking a value with optional type 'T?' against type 'P1' succeeds whenever the value is non-nil; did you mean to use '!= nil'?}}
 }
 func j(_ x : C1) -> Bool {
-  return x is P1
+  return x is P1 // expected-warning {{protocol 'P1' as a type must be explicitly marked as 'any'}}
 }
 func k(_ x : C1?) -> Bool {
-  return x is P1
+  return x is any P1
 }
 
 
diff --git a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift
index 05d6410ead2fa..33fac5d434d45 100644
--- a/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift
+++ b/test/decl/protocol/protocols_with_self_or_assoc_reqs.swift
@@ -57,7 +57,7 @@ protocol P1 {
   func invariantSelf7(_: (G<Self>) -> Void)
   func invariantSelf8(_: G<(Self) -> Void>)
   func invariantSelf9(_: G<() -> Self>)
-  func invariantSelf10(_: P1 & C<Self>)
+  func invariantSelf10(_: any P1 & C<Self>)
   func invariantSelf11() -> G<Self>.InnerG<Void>
   func invariantAssoc1(_: inout Q)
   func invariantAssoc2(_: (inout Q) -> Void)
@@ -68,7 +68,7 @@ protocol P1 {
   func invariantAssoc7(_: (G<Q>) -> Void)
   func invariantAssoc8(_: G<(Q) -> Void>)
   func invariantAssoc9(_: G<() -> Q>)
-  func invariantAssoc10(_: P1 & C<Q>)
+  func invariantAssoc10(_: any P1 & C<Q>)
   func invariantAssoc11() -> G<Q>.InnerG<Void>
 
   // Properties
@@ -117,7 +117,7 @@ protocol P1 {
   var invariantSelfProp7: ((G<Self>) -> Void) -> Void { get }
   var invariantSelfProp8: (G<(Self) -> Void>) -> Void { get }
   var invariantSelfProp9: (G<() -> Self>) -> Void { get }
-  var invariantSelfProp10: (P1 & C<Self>) -> Void { get }
+  var invariantSelfProp10: (any P1 & C<Self>) -> Void { get }
   var invariantSelfProp11: G<Self>.InnerG<Void> { get }
   var invariantAssocProp1: (inout Q) -> Void { get }
   var invariantAssocProp2: ((inout Q) -> Void) -> Void { get }
@@ -128,7 +128,7 @@ protocol P1 {
   var invariantAssocProp7: ((G<Q>) -> Void) { get }
   var invariantAssocProp8: (G<(Q) -> Void>) { get }
   var invariantAssocProp9: (G<() -> Q>) -> Void { get }
-  var invariantAssocProp10: (P1 & C<Q>) -> Void { get }
+  var invariantAssocProp10: (any P1 & C<Q>) -> Void { get }
   var invariantAssocProp11: G<Q>.InnerG<Void> { get }
 
   // Subscripts
@@ -172,7 +172,7 @@ protocol P1 {
   subscript(invariantSelfSubscript4 _: (G<Self>) -> Void) -> Void { get }
   subscript(invariantSelfSubscript5 _: G<(Self) -> Void>) -> Void { get }
   subscript(invariantSelfSubscript6 _: G<() -> Self>) -> Void { get }
-  subscript(invariantSelfSubscript7 _: P1 & C<Self>) -> Void { get }
+  subscript(invariantSelfSubscript7 _: any P1 & C<Self>) -> Void { get }
   subscript(invariantSelfSubscript8 _: Void) -> G<Self>.InnerG<Void> { get }
   subscript(invariantAssocSubscript1 _: G<Q>) -> Void { get }
   subscript(invariantAssocSubscript2 _: Void) -> G<Q> { get }
@@ -180,7 +180,7 @@ protocol P1 {
   subscript(invariantAssocSubscript4 _: (G<Q>) -> Void) -> Void { get }
   subscript(invariantAssocSubscript5 _: G<(Q) -> Void>) -> Void { get }
   subscript(invariantAssocSubscript6 _: G<() -> Q>) -> Void { get }
-  subscript(invariantAssocSubscript7 _: P1 & C<Q>) -> Void { get }
+  subscript(invariantAssocSubscript7 _: any P1 & C<Q>) -> Void { get }
   subscript(invariantAssocSubscript8 _: Void) -> G<Q>.InnerG<Void> { get }
 }
 @available(macOS 10.15, *)
@@ -191,40 +191,40 @@ extension P1 {
 }
 
 do {
-  func testP1(arg: P1) {
+  func testP1(arg: any P1) {
     _ = arg.covariantSelfSimple() // ok
-    let _: P1 = arg.covariantSelfSimple() // ok
+    let _: any P1 = arg.covariantSelfSimple() // ok
     _ = arg.covariantSelfComplex({ _ in },  { _ in }, { _ in }, { _ in }) // ok
-    let _: [String : () -> (P1, P1)] = arg.covariantSelfComplex(
-      { (x: P1) in },
-      { (x: P1?) in },
-      { (x: Array<P1>) in },
-      { (x: Array<Array<P1>?>) in }
+    let _: [String : () -> (any P1, any P1)] = arg.covariantSelfComplex(
+      { (x: any P1) in },
+      { (x: (any P1)?) in },
+      { (x: Array<any P1>) in },
+      { (x: Array<Array<any P1>?>) in }
     ) // ok
     arg.covariantAssocSimple // expected-error {{member 'covariantAssocSimple' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
     arg.covariantAssocComplex({ _ in }, { _ in }, { _ in }, { _ in }) // expected-error {{member 'covariantAssocComplex' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
     // FIXME: expected-error@-1 {{unable to infer type of a closure parameter '_' in the current context}}
 
     _ = arg.covariantSelfPropSimple // ok
-    let _: P1 = arg.covariantSelfPropSimple // ok
+    let _: any P1 = arg.covariantSelfPropSimple // ok
     _ = arg.covariantSelfPropComplex // ok
     let _: (
-      _: (P1) -> Void,
-      _: (P1?) -> Void,
-      _: (Array<P1>) -> Void,
-      _: (Array<Array<P1>?>) -> Void
-    ) -> [String : () -> (P1, P1)] = arg.covariantSelfPropComplex // ok
+      _: (any P1) -> Void,
+      _: ((any P1)?) -> Void,
+      _: (Array<any P1>) -> Void,
+      _: (Array<Array<any P1>?>) -> Void
+    ) -> [String : () -> (any P1, any P1)] = arg.covariantSelfPropComplex // ok
     arg.covariantAssocPropSimple // expected-error {{member 'covariantAssocPropSimple' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
     arg.covariantAssocPropComplex // expected-error {{member 'covariantAssocPropComplex' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
 
     _ = arg[covariantSelfSubscriptSimple: ()] // ok
-    let _: P1 = arg[covariantSelfSubscriptSimple: ()] // ok
+    let _: any P1 = arg[covariantSelfSubscriptSimple: ()] // ok
     _ = arg[covariantSelfSubscriptComplex: { _ in },  { _ in }, { _ in }, { _ in }] // ok
-    let _: [String : () -> (P1, P1)] = arg[
-      covariantSelfSubscriptComplex: { (x: P1) in },
-      { (x: P1?) in },
-      { (x: Array<P1>) in },
-      { (x: Array<Array<P1>?>) in }
+    let _: [String : () -> (any P1, any P1)] = arg[
+      covariantSelfSubscriptComplex: { (x: any P1) in },
+      { (x: (any P1)?) in },
+      { (x: Array<any P1>) in },
+      { (x: Array<Array<any P1>?>) in }
     ] // ok
     arg[covariantAssocSubscriptSimple: ()] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
     arg[covariantAssocSubscriptComplex: { _ in }, { _ in }, { _ in }, { _ in }] // expected-error {{member 'subscript' cannot be used on value of protocol type 'P1'; use a generic constraint instead}}
@@ -444,15 +444,15 @@ protocol P1_TypeMemberOnInstanceAndViceVersa {
 do {
   // Test that invalid reference errors prevail over unsupported existential
   // member accesses.
-  func test(protoMeta: P1_TypeMemberOnInstanceAndViceVersa.Protocol,
-            existMeta: P1_TypeMemberOnInstanceAndViceVersa.Type,
-            instance: P1_TypeMemberOnInstanceAndViceVersa) {
+  func test(protoMeta: (any P1_TypeMemberOnInstanceAndViceVersa).Type,
+            existMeta: any P1_TypeMemberOnInstanceAndViceVersa.Type,
+            instance: any P1_TypeMemberOnInstanceAndViceVersa) {
     // P1_TypeMemberOnInstanceAndViceVersa.Protocol
-    protoMeta.static_invariantSelfMethod() // expected-error {{static member 'static_invariantSelfMethod' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}}
-    protoMeta.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}}
-    protoMeta[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on protocol metatype 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'}}
+    protoMeta.static_invariantSelfMethod() // expected-error {{static member 'static_invariantSelfMethod' cannot be used on protocol metatype '(P1_TypeMemberOnInstanceAndViceVersa).Protocol'}}
+    protoMeta.static_invariantSelfProp // expected-error {{static member 'static_invariantSelfProp' cannot be used on protocol metatype '(P1_TypeMemberOnInstanceAndViceVersa).Protocol'}}
+    protoMeta[static_invariantSelfSubscript: ()] // expected-error {{static member 'subscript' cannot be used on protocol metatype '(P1_TypeMemberOnInstanceAndViceVersa).Protocol'}}
     _ = protoMeta.covariantSelfMethod // ok
-    protoMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type 'P1_TypeMemberOnInstanceAndViceVersa.Protocol'; use a generic constraint instead}}
+    protoMeta.invariantSelfMethod // expected-error {{member 'invariantSelfMethod' cannot be used on value of protocol type '(P1_TypeMemberOnInstanceAndViceVersa).Protocol'; use a generic constraint instead}}
     protoMeta.invariantSelfProp // expected-error {{instance member 'invariantSelfProp' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}}
     protoMeta[invariantSelfSubscript: ()] // expected-error {{instance member 'subscript' cannot be used on type 'P1_TypeMemberOnInstanceAndViceVersa'}}
 
@@ -481,7 +481,7 @@ protocol P2 {
 
   var prop: Self { get set }
 }
-func takesP2(p2: P2) {
+func takesP2(p2: any P2) {
   _ = p2[]
   // expected-error@-1{{member 'subscript' cannot be used on value of protocol type 'P2'; use a generic constraint instead}}
   _ = p2.prop
@@ -500,7 +500,7 @@ protocol MiscTestsProto {
   subscript(intToInt _: Int) -> Int { get }
 }
 do {
-  func miscTests(_ arg: MiscTestsProto) { // ok
+  func miscTests(_ arg: any MiscTestsProto) { // ok
     arg.runce(5)
 
     do {
@@ -515,7 +515,7 @@ do {
     _ = arg[intToAssoc: 17] // expected-error{{member 'subscript' cannot be used on value of protocol type 'MiscTestsProto'; use a generic constraint instead}}
   }
 
-  func existentialSequence(_ e: Sequence) {
+  func existentialSequence(_ e: any Sequence) {
     var x = e.makeIterator() // expected-error{{member 'makeIterator' cannot be used on value of protocol type 'Sequence'; use a generic constraint instead}}
     x.next()
     x.nonexistent()
diff --git a/test/decl/protocol/recursive_requirement.swift b/test/decl/protocol/recursive_requirement.swift
index c99dadbb6b4bd..eab9ac2f8687e 100644
--- a/test/decl/protocol/recursive_requirement.swift
+++ b/test/decl/protocol/recursive_requirement.swift
@@ -91,7 +91,7 @@ protocol AsExistentialB {
 }
 
 protocol AsExistentialAssocTypeA {
-  var delegate : AsExistentialAssocTypeB? { get }
+  var delegate : AsExistentialAssocTypeB? { get } // expected-warning {{protocol 'AsExistentialAssocTypeB' as a type must be explicitly marked as 'any'}}
 }
 protocol AsExistentialAssocTypeB {
   func aMethod(_ object : AsExistentialAssocTypeA)
@@ -103,7 +103,7 @@ protocol AsExistentialAssocTypeAgainA {
   associatedtype Bar
 }
 protocol AsExistentialAssocTypeAgainB {
-  func aMethod(_ object : AsExistentialAssocTypeAgainA)
+  func aMethod(_ object : AsExistentialAssocTypeAgainA) // expected-warning {{protocol 'AsExistentialAssocTypeAgainA' as a type must be explicitly marked as 'any'}}
 }
 
 // SR-547
diff --git a/test/stmt/foreach.swift b/test/stmt/foreach.swift
index e3c3d6a3cb6eb..f11f5ae72b7fc 100644
--- a/test/stmt/foreach.swift
+++ b/test/stmt/foreach.swift
@@ -176,7 +176,7 @@ func testOptionalSequence() {
 }
 
 // FIXME: Should this be allowed?
-func testExistentialSequence(s: Sequence) {
+func testExistentialSequence(s: any Sequence) {
   for x in s { // expected-error {{protocol 'Sequence' as a type cannot conform to the protocol itself}} expected-note {{only concrete types such as structs, enums and classes can conform to protocols}}
     _ = x
   }
diff --git a/test/type/explicit_existential.swift b/test/type/explicit_existential.swift
index b19a802007686..38714635d6a86 100644
--- a/test/type/explicit_existential.swift
+++ b/test/type/explicit_existential.swift
@@ -149,9 +149,9 @@ func testInvalidAny() {
   let _: any ((S) -> Void) = generic // expected-error{{'any' has no effect on concrete type '(S) -> Void'}}
 }
 
-func testRedundantAnyWarning() {
-  let _: any Any // expected-warning {{'any' is redundant on type 'Any'}}
-  let _: any AnyObject // expected-warning {{'any' is redundant on type 'AnyObject'}}
+func anyAny() {
+  let _: any Any
+  let _: any AnyObject
 }
 
 protocol P1 {}
@@ -162,3 +162,43 @@ func testMetatypes() {
   let _: any P1.Type = ConcreteComposition.self
   let _: any (P1 & P2).Type = ConcreteComposition.self
 }
+
+func generic<T: any P1>(_ t: T) {} // expected-error {{type 'T' constrained to non-protocol, non-class type 'any P1'}}
+
+protocol RawRepresentable {
+  associatedtype RawValue
+  var rawValue: RawValue { get }
+}
+
+enum E1: RawRepresentable {
+  typealias RawValue = P1
+
+  var rawValue: P1 {
+    return ConcreteComposition()
+  }
+}
+
+enum E2: RawRepresentable {
+  typealias RawValue = any P1
+
+  var rawValue: any P1 {
+    return ConcreteComposition()
+  }
+}
+
+public protocol MyError {}
+
+extension MyError {
+  static func ~=(lhs: any Error, rhs: Self) -> Bool {
+    return true
+  }
+}
+
+struct Wrapper {
+  typealias E = Error
+}
+
+func typealiasMemberReferences(metatype: Wrapper.Type) {
+  let _: Wrapper.E.Protocol = metatype.E.self
+  let _: (any Wrapper.E).Type = metatype.E.self
+}
diff --git a/test/type/protocol_types.swift b/test/type/protocol_types.swift
index d2d02dd612a3b..41df887c396d0 100644
--- a/test/type/protocol_types.swift
+++ b/test/type/protocol_types.swift
@@ -3,7 +3,7 @@
 protocol HasSelfRequirements {
   func foo(_ x: Self)
 
-  func returnsOwnProtocol() -> HasSelfRequirements
+  func returnsOwnProtocol() -> HasSelfRequirements // expected-warning {{protocol 'HasSelfRequirements' as a type must be explicitly marked as 'any'}}
 }
 protocol Bar {
   // init() methods should not prevent use as an existential.
@@ -36,10 +36,10 @@ func useCompoAsWhereRequirement<T>(_ x: T) where T: HasSelfRequirements & Bar {}
 func useCompoAliasAsWhereRequirement<T>(_ x: T) where T: Compo {}
 func useNestedCompoAliasAsWhereRequirement<T>(_ x: T) where T: CompoAssocType.Compo {}
 
-func useAsType(_: HasSelfRequirements,
-               _: HasSelfRequirements & Bar,
-               _: Compo,
-               _: CompoAssocType.Compo) { }
+func useAsType(_: any HasSelfRequirements,
+               _: any HasSelfRequirements & Bar,
+               _: any Compo,
+               _: any CompoAssocType.Compo) { }
 
 struct TypeRequirement<T: HasSelfRequirements> {}
 struct CompoTypeRequirement<T: HasSelfRequirements & Bar> {}
@@ -74,7 +74,7 @@ do {
 
   func checkIt(_ js: Any) throws {
     switch js {
-    case let dbl as HasAssoc:
+    case let dbl as HasAssoc: // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}}
       throw MyError.bad(dbl)
 
     default:
@@ -83,8 +83,8 @@ do {
   }
 }
 
-func testHasAssoc(_ x: Any, _: HasAssoc) {
-  if let p = x as? HasAssoc {
+func testHasAssoc(_ x: Any, _: HasAssoc) { // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}}
+  if let p = x as? any HasAssoc {
     p.foo() // don't crash here.
   }
 
@@ -92,18 +92,18 @@ func testHasAssoc(_ x: Any, _: HasAssoc) {
     typealias Assoc = Int
     func foo() {}
 
-    func method() -> HasAssoc {}
+    func method() -> HasAssoc {} // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}}
   }
 }
 
 // SR-38
-var b: HasAssoc
+var b: HasAssoc // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}}
 
 // Further generic constraint error testing - typealias used inside statements
 protocol P {}
 typealias MoreHasAssoc = HasAssoc & P
 func testHasMoreAssoc(_ x: Any) {
-  if let p = x as? MoreHasAssoc {
+  if let p = x as? any MoreHasAssoc {
     p.foo() // don't crash here.
   }
 }
@@ -118,34 +118,34 @@ typealias X = Struct1<Pub & Bar>
 _ = Struct1<Pub & Bar>.self
 
 typealias AliasWhere<T> = T
-where T : HasAssoc, T.Assoc == HasAssoc
+where T : HasAssoc, T.Assoc == HasAssoc // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}}
 
 struct StructWhere<T>
 where T : HasAssoc,
-      T.Assoc == HasAssoc {}
+      T.Assoc == any HasAssoc {}
 
-protocol ProtocolWhere where T == HasAssoc {
+protocol ProtocolWhere where T == HasAssoc { // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}}
   associatedtype T
 
   associatedtype U : HasAssoc
-    where U.Assoc == HasAssoc
+    where U.Assoc == any HasAssoc
 }
 
-extension HasAssoc where Assoc == HasAssoc {}
+extension HasAssoc where Assoc == HasAssoc {} // expected-warning {{protocol 'HasAssoc' as a type must be explicitly marked as 'any'}}
 
 func FunctionWhere<T>(_: T)
 where T : HasAssoc,
-      T.Assoc == HasAssoc {}
+      T.Assoc == any HasAssoc {}
 
 struct SubscriptWhere {
   subscript<T>(_: T) -> Int
   where T : HasAssoc,
-        T.Assoc == HasAssoc {
+        T.Assoc == any HasAssoc {
     get {}
     set {}
   }
 }
 
 struct OuterGeneric<T> {
-  func contextuallyGenericMethod() where T == HasAssoc {}
+  func contextuallyGenericMethod() where T == any HasAssoc {}
 }