Merge pull request #13821 from slavapestov/kill-unused-link-entities

Kill unused link entities
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index fefc6bb..a727c13 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -117,7 +117,7 @@
   global ::= global 'TD'                 // dynamic dispatch thunk
   global ::= global 'Td'                 // direct method reference thunk
   global ::= entity entity 'TV'          // vtable override thunk, derived followed by base
-  global ::= type 'D'                    // type mangling for the debugger. TODO: check if we really need this
+  global ::= type label-list? 'D'        // type mangling for the debugger with label list for function types.
   global ::= protocol-conformance entity 'TW' // protocol witness thunk
   global ::= context identifier identifier 'TB' // property behavior initializer thunk (not used currently)
   global ::= context identifier identifier 'Tb' // property behavior setter thunk (not used currently)
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 0330f5f..148911e 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -621,18 +621,11 @@
     Bits.Decl.EscapedFromIfConfig = false;
   }
 
-  ClangNode getClangNodeImpl() const {
-    assert(Bits.Decl.FromClang);
-    return ClangNode::getFromOpaqueValue(
-        *(reinterpret_cast<void * const*>(this) - 1));
-  }
+  /// \brief Get the Clang node associated with this declaration.
+  ClangNode getClangNodeImpl() const;
 
   /// \brief Set the Clang node associated with this declaration.
-  void setClangNode(ClangNode Node) {
-    Bits.Decl.FromClang = true;
-    // Extra memory is allocated for this.
-    *(reinterpret_cast<void **>(this) - 1) = Node.getOpaqueValue();
-  }
+  void setClangNode(ClangNode Node);
 
   void updateClangNode(ClangNode node) {
     assert(hasClangNode());
@@ -1355,8 +1348,10 @@
   }
 };
 
-class GenericContext : public DeclContext {
-private:
+// A private class for forcing exact field layout.
+class _GenericContext {
+// Not really public. See GenericContext.
+public:
   GenericParamList *GenericParams = nullptr;
 
   /// The trailing where clause.
@@ -1371,13 +1366,15 @@
   /// environment will be lazily loaded.
   mutable llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
     GenericSigOrEnv;
+};
 
+class GenericContext : private _GenericContext, public DeclContext {
   /// Lazily populate the generic environment.
   GenericEnvironment *getLazyGenericEnvironmentSlow() const;
 
 protected:
   GenericContext(DeclContextKind Kind, DeclContext *Parent)
-    : DeclContext(Kind, Parent) { }
+    : _GenericContext(), DeclContext(Kind, Parent) { }
 
 public:
   /// \brief Retrieve the set of parameters to a generic context, or null if
@@ -1424,6 +1421,8 @@
   /// Set the generic context of this context.
   void setGenericEnvironment(GenericEnvironment *genericEnv);
 };
+static_assert(sizeof(_GenericContext) + sizeof(DeclContext) ==
+              sizeof(GenericContext), "Please add fields to _GenericContext");
 
 /// Describes what kind of name is being imported.
 ///
@@ -1532,7 +1531,7 @@
 /// ExtensionDecl - This represents a type extension containing methods
 /// associated with the type.  This is not a ValueDecl and has no Type because
 /// there are no runtime values of the Extension's type.  
-class ExtensionDecl final : public Decl, public GenericContext,
+class ExtensionDecl final : public GenericContext, public Decl,
                             public IterableDeclContext {
   SourceLoc ExtensionLoc;  // Location of 'extension' keyword.
   SourceRange Braces;
@@ -1948,13 +1947,13 @@
 /// This, among other things, makes it easier to distinguish between local
 /// top-level variables (which are not live past the end of the statement) and
 /// global variables.
-class TopLevelCodeDecl : public Decl, public DeclContext {
+class TopLevelCodeDecl : public DeclContext, public Decl {
   BraceStmt *Body;
 
 public:
   TopLevelCodeDecl(DeclContext *Parent, BraceStmt *Body = nullptr)
-    : Decl(DeclKind::TopLevelCode, Parent),
-      DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
+    : DeclContext(DeclContextKind::TopLevelCodeDecl, Parent),
+      Decl(DeclKind::TopLevelCode, Parent),
       Body(Body) {}
 
   BraceStmt *getBody() const { return Body; }
@@ -2373,7 +2372,7 @@
 
 /// A type declaration that can have generic parameters attached to it.  Because
 /// it has these generic parameters, it is always a DeclContext.
-class GenericTypeDecl : public TypeDecl, public GenericContext {
+class GenericTypeDecl : public GenericContext, public TypeDecl {
 public:
   GenericTypeDecl(DeclKind K, DeclContext *DC,
                   Identifier name, SourceLoc nameLoc,
@@ -4702,7 +4701,7 @@
 /// A given type can have multiple subscript declarations, so long as the
 /// signatures (indices and element type) are distinct.
 ///
-class SubscriptDecl : public AbstractStorageDecl, public GenericContext {
+class SubscriptDecl : public GenericContext, public AbstractStorageDecl {
   SourceLoc ArrowLoc;
   ParameterList *Indices;
   TypeLoc ElementTy;
@@ -4711,8 +4710,8 @@
   SubscriptDecl(DeclName Name, SourceLoc SubscriptLoc, ParameterList *Indices,
                 SourceLoc ArrowLoc, TypeLoc ElementTy, DeclContext *Parent,
                 GenericParamList *GenericParams)
-    : AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
-      GenericContext(DeclContextKind::SubscriptDecl, Parent),
+    : GenericContext(DeclContextKind::SubscriptDecl, Parent),
+      AbstractStorageDecl(DeclKind::Subscript, Parent, Name, SubscriptLoc),
       ArrowLoc(ArrowLoc), Indices(nullptr), ElementTy(ElementTy) {
     setIndices(Indices);
     setGenericParams(GenericParams);
@@ -4794,7 +4793,7 @@
 };
 
 /// \brief Base class for function-like declarations.
-class AbstractFunctionDecl : public ValueDecl, public GenericContext {
+class AbstractFunctionDecl : public GenericContext, public ValueDecl {
 public:
   enum class BodyKind {
     /// The function did not have a body in the source code file.
@@ -4854,8 +4853,8 @@
                        SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
                        unsigned NumParameterLists,
                        GenericParamList *GenericParams)
-      : ValueDecl(Kind, Parent, Name, NameLoc),
-        GenericContext(DeclContextKind::AbstractFunctionDecl, Parent),
+      : GenericContext(DeclContextKind::AbstractFunctionDecl, Parent),
+        ValueDecl(Kind, Parent, Name, NameLoc),
         Body(nullptr), ThrowsLoc(ThrowsLoc) {
     setBodyKind(BodyKind::None);
     setGenericParams(GenericParams);
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index bec8aae..688bf93 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -72,7 +72,7 @@
 using DeclID = llvm::PointerEmbeddedInt<unsigned, 31>;
 }
 
-enum class DeclContextKind : uint8_t {
+enum class DeclContextKind : unsigned {
   AbstractClosureExpr,
   Initializer,
   TopLevelCodeDecl,
@@ -179,19 +179,24 @@
 /// DeclContext, but a new brace statement is not.  There's no
 /// particular mandate for this, though.
 ///
-/// Note that DeclContexts have stricter alignment requirements than AST nodes
-/// in general, so if an AST node class multiply inherits from DeclContext
-/// and another base class, it must 'using DeclContext::operator new;' in order
-/// to use an allocator with the correct alignment.
+/// Please note that DeclContext assumes that it prefaces AST type hierarchies
+/// and therefore can safely access trailing memory. If you need to create a
+/// macro context, please see GenericContext for how to minimize new entries in
+/// the ASTHierarchy enum below.
 class alignas(1 << DeclContextAlignInBits) DeclContext {
-  
-  enum {
-    KindBits = DeclContextAlignInBits
+  enum class ASTHierarchy : unsigned {
+    Decl,
+    Expr,
+    FileUnit,
+    Initializer,
+    SerializedLocal,
+    // If you add a new AST hierarchies, then update the static_assert() below.
   };
-  static_assert(unsigned(DeclContextKind::Last_DeclContextKind) < 1U<<KindBits,
-                "Not enough KindBits for DeclContextKind");
-  
-  llvm::PointerIntPair<DeclContext*, KindBits, DeclContextKind> ParentAndKind;
+  static_assert(unsigned(ASTHierarchy::SerializedLocal) <
+                (1 << DeclContextAlignInBits),
+                "ASTHierarchy exceeds bits available");
+
+  llvm::PointerIntPair<DeclContext*, 3, ASTHierarchy> ParentAndKind;
 
   /// Change the parent of this context.  This should only be used
   /// very carefully.
@@ -209,17 +214,44 @@
   /// extension thereof, return the GenericTypeDecl.
   GenericTypeDecl *getAsTypeOrTypeExtensionContext() const;
 
+  static ASTHierarchy getASTHierarchyFromKind(DeclContextKind Kind) {
+    switch (Kind) {
+    case DeclContextKind::AbstractClosureExpr:
+      return ASTHierarchy::Expr;
+    case DeclContextKind::Initializer:
+      return ASTHierarchy::Initializer;
+    case DeclContextKind::SerializedLocal:
+      return ASTHierarchy::SerializedLocal;
+    case DeclContextKind::FileUnit:
+      return ASTHierarchy::FileUnit;
+    case DeclContextKind::Module:
+    case DeclContextKind::TopLevelCodeDecl:
+    case DeclContextKind::AbstractFunctionDecl:
+    case DeclContextKind::SubscriptDecl:
+    case DeclContextKind::GenericTypeDecl:
+    case DeclContextKind::ExtensionDecl:
+      return ASTHierarchy::Decl;
+    }
+    llvm_unreachable("Unhandled DeclContextKind");
+  }
+
+  Decl *getAsDeclOrDeclExtensionContext() {
+    return ParentAndKind.getInt() == ASTHierarchy::Decl ?
+      reinterpret_cast<Decl*>(this + 1) : nullptr;
+  }
+  const Decl *getAsDeclOrDeclExtensionContext() const {
+    return const_cast<DeclContext*>(this)->getAsDeclOrDeclExtensionContext();
+  }
+
 public:
   DeclContext(DeclContextKind Kind, DeclContext *Parent)
-    : ParentAndKind(Parent, Kind) {
-    assert((Parent != 0 || isModuleContext()) &&
-           "DeclContext must have a parent unless it is a module!");
+      : ParentAndKind(Parent, getASTHierarchyFromKind(Kind)) {
+    if (Kind != DeclContextKind::Module)
+      assert(Parent != nullptr && "DeclContext must have a parent context");
   }
 
   /// Returns the kind of context this is.
-  DeclContextKind getContextKind() const {
-    return ParentAndKind.getInt();
-  }
+  DeclContextKind getContextKind() const;
   
   /// Determines whether this context is itself a local scope in a
   /// code block.  A context that appears in such a scope, like a
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index 62e845a..d122585 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -3389,7 +3389,7 @@
 
 
 /// \brief A base class for closure expressions.
-class AbstractClosureExpr : public Expr, public DeclContext {
+class AbstractClosureExpr : public DeclContext, public Expr {
   CaptureInfo Captures;
 
   /// \brief The set of parameters.
@@ -3398,8 +3398,8 @@
 public:
   AbstractClosureExpr(ExprKind Kind, Type FnType, bool Implicit,
                       unsigned Discriminator, DeclContext *Parent)
-      : Expr(Kind, Implicit, FnType),
-        DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
+      : DeclContext(DeclContextKind::AbstractClosureExpr, Parent),
+        Expr(Kind, Implicit, FnType),
         parameterList(nullptr) {
     Bits.AbstractClosureExpr.Discriminator = Discriminator;
   }
diff --git a/include/swift/AST/ExprNodes.def b/include/swift/AST/ExprNodes.def
index d57d7c9..3aa95b6 100644
--- a/include/swift/AST/ExprNodes.def
+++ b/include/swift/AST/ExprNodes.def
@@ -48,6 +48,13 @@
 #define LITERAL_EXPR(Id, Parent) EXPR(Id, Parent)
 #endif
 
+/// A expression node with a DeclContext. For example: closures.
+///
+/// By default, these are treated like any other expression.
+#ifndef CONTEXT_EXPR
+#define CONTEXT_EXPR(Id, Parent) EXPR(Id, Parent)
+#endif
+
 /// A convenience for determining the range of expressions.  These will always
 /// appear immediately after the last member.
 #ifndef EXPR_RANGE
@@ -109,8 +116,8 @@
 EXPR(TupleElement, Expr)
 EXPR(CaptureList, Expr)
 ABSTRACT_EXPR(AbstractClosure, Expr)
-  EXPR(Closure, AbstractClosureExpr)
-  EXPR(AutoClosure, AbstractClosureExpr)
+  CONTEXT_EXPR(Closure, AbstractClosureExpr)
+  CONTEXT_EXPR(AutoClosure, AbstractClosureExpr)
   EXPR_RANGE(AbstractClosure, Closure, AutoClosure)
 EXPR(InOut, Expr)
 EXPR(DynamicType, Expr)
@@ -183,5 +190,6 @@
 #undef LITERAL_EXPR
 #undef UNCHECKED_EXPR
 #undef ABSTRACT_EXPR
+#undef CONTEXT_EXPR
 #undef EXPR
 #undef LAST_EXPR
diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h
index 4186e69..41b9f9d 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -127,7 +127,7 @@
 /// output binary and logical module (such as a single library or executable).
 ///
 /// \sa FileUnit
-class ModuleDecl : public TypeDecl, public DeclContext {
+class ModuleDecl : public DeclContext, public TypeDecl {
 public:
   typedef ArrayRef<std::pair<Identifier, SourceLoc>> AccessPathTy;
   typedef std::pair<ModuleDecl::AccessPathTy, ModuleDecl*> ImportedModule;
diff --git a/include/swift/AST/TypeAlignments.h b/include/swift/AST/TypeAlignments.h
index e021da0..67fc513 100644
--- a/include/swift/AST/TypeAlignments.h
+++ b/include/swift/AST/TypeAlignments.h
@@ -52,7 +52,7 @@
 
   /// We frequently use three tag bits on all of these types.
   constexpr size_t DeclAlignInBits = 3;
-  constexpr size_t DeclContextAlignInBits = 4;
+  constexpr size_t DeclContextAlignInBits = 3;
   constexpr size_t ExprAlignInBits = 3;
   constexpr size_t StmtAlignInBits = 3;
   constexpr size_t TypeAlignInBits = 3;
diff --git a/include/swift/Basic/Compiler.h b/include/swift/Basic/Compiler.h
index 04f231a..eea6c93 100644
--- a/include/swift/Basic/Compiler.h
+++ b/include/swift/Basic/Compiler.h
@@ -23,6 +23,9 @@
 #ifndef __has_builtin
 #define __has_builtin(x) 0
 #endif
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
 
 #if SWIFT_COMPILER_IS_MSVC && _MSC_VER < 1910
 // Work around MSVC bug: attempting to reference a deleted function
@@ -40,4 +43,10 @@
 #define SWIFT_ASSUME(x)
 #endif
 
+#if __has_attribute(constructor)
+#define SWIFT_CONSTRUCTOR __attribute__((constructor))
+#else
+#define SWIFT_CONSTRUCTOR
+#endif
+
 #endif // SWIFT_BASIC_COMPILER_H
diff --git a/include/swift/Demangling/Demangle.h b/include/swift/Demangling/Demangle.h
index 152f49d..0b5beec 100644
--- a/include/swift/Demangling/Demangle.h
+++ b/include/swift/Demangling/Demangle.h
@@ -206,6 +206,8 @@
 
   // Only to be used by the demangler parsers.
   void addChild(NodePointer Child, NodeFactory &Factory);
+  // Only to be used by the demangler parsers.
+  void removeChildAt(unsigned Pos, NodeFactory &factory);
 
   // Reverses the order of children.
   void reverseChildren(size_t StartingAt = 0);
@@ -234,6 +236,12 @@
 /// \param mangledName A null-terminated string containing a mangled name.
 bool isSwiftSymbol(const char *mangledName);
 
+/// Returns true if the mangled name has the old scheme of function type
+/// mangling where labels are part of the type.
+///
+/// \param mangledName A null-terminated string containing a mangled name.
+bool isOldFunctionTypeMangling(const char *mangledName);
+
 class Demangler;
 
 /// The demangler context.
diff --git a/include/swift/Demangling/Demangler.h b/include/swift/Demangling/Demangler.h
index b34b3d6..ec0e4d1 100644
--- a/include/swift/Demangling/Demangler.h
+++ b/include/swift/Demangling/Demangler.h
@@ -290,6 +290,11 @@
   StringRef Text;
   size_t Pos = 0;
 
+  /// Mangling style where function type would have
+  /// labels attached to it, instead of having them
+  /// as part of the name.
+  bool IsOldFunctionTypeMangling = false;
+
   Vector<NodePointer> NodeStack;
   Vector<NodePointer> Substitutions;
   Vector<unsigned> PendingSubstitutions;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 3340433..21aa961 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -861,8 +861,8 @@
                              MutableArrayRef<TypeLoc> inherited,
                              DeclContext *parent,
                              TrailingWhereClause *trailingWhereClause)
-  : Decl(DeclKind::Extension, parent),
-    GenericContext(DeclContextKind::ExtensionDecl, parent),
+  : GenericContext(DeclContextKind::ExtensionDecl, parent),
+    Decl(DeclKind::Extension, parent),
     IterableDeclContext(IterableDeclContextKind::ExtensionDecl),
     ExtensionLoc(extensionLoc),
     ExtendedType(extendedType),
@@ -2490,8 +2490,8 @@
                                  Identifier name, SourceLoc nameLoc,
                                  MutableArrayRef<TypeLoc> inherited,
                                  GenericParamList *GenericParams) :
-    TypeDecl(K, DC, name, nameLoc, inherited),
-    GenericContext(DeclContextKind::GenericTypeDecl, DC) {
+    GenericContext(DeclContextKind::GenericTypeDecl, DC),
+    TypeDecl(K, DC, name, nameLoc, inherited) {
   setGenericParams(GenericParams);
 }
 
@@ -5548,3 +5548,30 @@
          && "superclass must be interface type");
   LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
 }
+
+ClangNode Decl::getClangNodeImpl() const {
+  assert(Bits.Decl.FromClang);
+  void * const *ptr = nullptr;
+  switch (getKind()) {
+#define DECL(Id, Parent) \
+  case DeclKind::Id: \
+    ptr = reinterpret_cast<void * const*>(static_cast<const Id##Decl*>(this)); \
+    break;
+#include "swift/AST/DeclNodes.def"
+  }
+  return ClangNode::getFromOpaqueValue(*(ptr - 1));
+}
+
+void Decl::setClangNode(ClangNode Node) {
+  Bits.Decl.FromClang = true;
+  // The extra/preface memory is allocated by the importer.
+  void **ptr = nullptr;
+  switch (getKind()) {
+#define DECL(Id, Parent) \
+  case DeclKind::Id: \
+    ptr = reinterpret_cast<void **>(static_cast<Id##Decl*>(this)); \
+    break;
+#include "swift/AST/DeclNodes.def"
+  }
+  *(ptr - 1) = Node.getOpaqueValue();
+}
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index b3bfe08..4eb4c1c 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -47,32 +47,15 @@
 
 GenericTypeDecl *
 DeclContext::getAsTypeOrTypeExtensionContext() const {
-  switch (getContextKind()) {
-  case DeclContextKind::Module:
-  case DeclContextKind::FileUnit:
-  case DeclContextKind::AbstractClosureExpr:
-  case DeclContextKind::TopLevelCodeDecl:
-  case DeclContextKind::AbstractFunctionDecl:
-  case DeclContextKind::SubscriptDecl:
-  case DeclContextKind::Initializer:
-  case DeclContextKind::SerializedLocal:
-    return nullptr;
-
-  case DeclContextKind::ExtensionDecl: {
-    auto ED = cast<ExtensionDecl>(this);
-    auto type = ED->getExtendedType();
-
-    if (!type)
+  if (auto decl = const_cast<Decl*>(getAsDeclOrDeclExtensionContext())) {
+    if (auto ED = dyn_cast<ExtensionDecl>(decl)) {
+      if (auto type = ED->getExtendedType())
+        return type->getAnyNominal();
       return nullptr;
-
-    return type->getAnyNominal();
+    }
+    return dyn_cast<GenericTypeDecl>(decl);
   }
-
-  case DeclContextKind::GenericTypeDecl:
-    return const_cast<GenericTypeDecl*>(cast<GenericTypeDecl>(this));
-  }
-
-  llvm_unreachable("Unhandled DeclContextKind in switch.");
+  return nullptr;
 }
 
 /// If this DeclContext is a NominalType declaration or an
@@ -101,10 +84,11 @@
 }
 
 ProtocolDecl *DeclContext::getAsProtocolExtensionContext() const {
-  if (getContextKind() != DeclContextKind::ExtensionDecl)
-    return nullptr;
-
-  return dyn_cast_or_null<ProtocolDecl>(getAsTypeOrTypeExtensionContext());
+  if (auto decl = const_cast<Decl*>(getAsDeclOrDeclExtensionContext()))
+    if (auto ED = dyn_cast<ExtensionDecl>(decl))
+      if (auto type = ED->getExtendedType())
+        return dyn_cast_or_null<ProtocolDecl>(type->getAnyNominal());
+  return nullptr;
 }
 
 GenericTypeParamType *DeclContext::getProtocolSelfType() const {
@@ -384,33 +368,10 @@
 
 Decl *DeclContext::getInnermostDeclarationDeclContext() {
   DeclContext *DC = this;
-  while (DC) {
-    switch (DC->getContextKind()) {
-    case DeclContextKind::AbstractClosureExpr:
-    case DeclContextKind::Initializer:
-    case DeclContextKind::SerializedLocal:
-    case DeclContextKind::Module:
-    case DeclContextKind::FileUnit:
-      break;
-
-    case DeclContextKind::TopLevelCodeDecl:
-      return cast<TopLevelCodeDecl>(DC);
-
-    case DeclContextKind::AbstractFunctionDecl:
-      return cast<AbstractFunctionDecl>(DC);
-
-    case DeclContextKind::SubscriptDecl:
-      return cast<SubscriptDecl>(DC);
-
-    case DeclContextKind::GenericTypeDecl:
-      return cast<GenericTypeDecl>(DC);
-
-    case DeclContextKind::ExtensionDecl:
-      return cast<ExtensionDecl>(DC);
-    }
-
-    DC = DC->getParent();
-  }
+  do {
+    if (auto decl = DC->getAsDeclOrDeclExtensionContext())
+      return isa<ModuleDecl>(decl) ? nullptr : decl;
+  } while ((DC = DC->getParent()));
 
   return nullptr;
 }
@@ -1100,3 +1061,83 @@
 
   return false;
 }
+
+DeclContextKind DeclContext::getContextKind() const {
+  switch (ParentAndKind.getInt()) {
+  case ASTHierarchy::Expr:
+    return DeclContextKind::AbstractClosureExpr;
+  case ASTHierarchy::Initializer:
+    return DeclContextKind::Initializer;
+  case ASTHierarchy::SerializedLocal:
+    return DeclContextKind::SerializedLocal;
+  case ASTHierarchy::FileUnit:
+    return DeclContextKind::FileUnit;
+  case ASTHierarchy::Decl: {
+    auto decl = reinterpret_cast<const Decl*>(this + 1);
+    if (isa<AbstractFunctionDecl>(decl))
+      return DeclContextKind::AbstractFunctionDecl;
+    if (isa<GenericTypeDecl>(decl))
+      return DeclContextKind::GenericTypeDecl;
+    switch (decl->getKind()) {
+    case DeclKind::Module:
+      return DeclContextKind::Module;
+    case DeclKind::TopLevelCode:
+      return DeclContextKind::TopLevelCodeDecl;
+    case DeclKind::Subscript:
+      return DeclContextKind::SubscriptDecl;
+    case DeclKind::Extension:
+      return DeclContextKind::ExtensionDecl;
+    default:
+      llvm_unreachable("Unhandled Decl kind");
+    }
+  }
+  }
+  llvm_unreachable("Unhandled DeclContext ASTHierarchy");
+}
+
+#define DECL(Id, Parent) \
+  static_assert(!std::is_base_of<DeclContext, Id##Decl>::value, \
+                "Non-context Decl node has context?");
+#define CONTEXT_DECL(Id, Parent) \
+  static_assert(alignof(DeclContext) == alignof(Id##Decl), "Alignment error"); \
+  static_assert(std::is_base_of<DeclContext, Id##Decl>::value, \
+                "CONTEXT_DECL nodes must inherit from DeclContext");
+#define CONTEXT_VALUE_DECL(Id, Parent) \
+  static_assert(alignof(DeclContext) == alignof(Id##Decl), "Alignment error"); \
+  static_assert(std::is_base_of<DeclContext, Id##Decl>::value, \
+                "CONTEXT_VALUE_DECL nodes must inherit from DeclContext");
+#include "swift/AST/DeclNodes.def"
+
+#define EXPR(Id, Parent) \
+  static_assert(!std::is_base_of<DeclContext, Id##Expr>::value, \
+                "Non-context Expr node has context?");
+#define CONTEXT_EXPR(Id, Parent) \
+  static_assert(alignof(DeclContext) == alignof(Id##Expr), "Alignment error"); \
+  static_assert(std::is_base_of<DeclContext, Id##Expr>::value, \
+                "CONTEXT_EXPR nodes must inherit from DeclContext");
+#include "swift/AST/ExprNodes.def"
+
+#ifndef NDEBUG
+// XXX -- static_cast is not static enough for use with static_assert().
+// DO verify this by temporarily breaking a Decl or Expr.
+// DO NOT assume that the compiler will emit this code blindly.
+SWIFT_CONSTRUCTOR
+static void verify_DeclContext_is_start_of_node() {
+  auto decl = reinterpret_cast<Decl*>(0x1000 + sizeof(DeclContext));
+#define DECL(Id, Parent)
+#define CONTEXT_DECL(Id, Parent) \
+  assert(reinterpret_cast<DeclContext*>(0x1000) == \
+         static_cast<Id##Decl*>(decl));
+#define CONTEXT_VALUE_DECL(Id, Parent) \
+  assert(reinterpret_cast<DeclContext*>(0x1000) == \
+         static_cast<Id##Decl*>(decl));
+#include "swift/AST/DeclNodes.def"
+
+  auto expr = reinterpret_cast<Expr*>(0x1000 + sizeof(DeclContext));
+#define EXPR(Id, Parent)
+#define CONTEXT_EXPR(Id, Parent) \
+  assert(reinterpret_cast<DeclContext*>(0x1000) == \
+         static_cast<Id##Expr*>(expr));
+#include "swift/AST/ExprNodes.def"
+}
+#endif
diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp
index fa2b376..bd943a8 100644
--- a/lib/AST/Module.cpp
+++ b/lib/AST/Module.cpp
@@ -347,8 +347,8 @@
 //===----------------------------------------------------------------------===//
 
 ModuleDecl::ModuleDecl(Identifier name, ASTContext &ctx)
-  : TypeDecl(DeclKind::Module, &ctx, name, SourceLoc(), { }),
-    DeclContext(DeclContextKind::Module, nullptr),
+  : DeclContext(DeclContextKind::Module, nullptr),
+    TypeDecl(DeclKind::Module, &ctx, name, SourceLoc(), { }),
     Flags({0, 0, 0}) {
   ctx.addDestructorCleanup(*this);
   setImplicit();
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index df57f86..c0b0eff 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -136,6 +136,10 @@
   return getManglingPrefixLength(mangledName) != 0;
 }
 
+bool swift::Demangle::isOldFunctionTypeMangling(const char *mangledName) {
+  return mangledName[0] == '_' && mangledName[1] == 'T';
+}
+
 namespace swift {
 namespace Demangle {
 
@@ -151,6 +155,23 @@
   Children[NumChildren++] = Child;
 }
 
+void Node::removeChildAt(unsigned Pos, swift::Demangle::NodeFactory &factory) {
+  assert(Pos < NumChildren && "invalid child position!");
+
+  size_t Index = 0;
+  auto *NewChildren = factory.Allocate<NodePointer>(NumChildren - 1);
+  for (unsigned i = 0, n = NumChildren; i != n; ++i) {
+    auto Child = Children[i];
+    if (i != Pos) {
+      NewChildren[Index] = Child;
+      ++Index;
+    } else {
+      --NumChildren;
+    }
+  }
+  Children = NewChildren;
+}
+
 void Node::reverseChildren(size_t StartingAt) {
   assert(StartingAt <= NumChildren);
   std::reverse(Children + StartingAt, Children + NumChildren);
@@ -257,6 +278,7 @@
   if (PrefixLength == 0)
     return nullptr;
 
+  IsOldFunctionTypeMangling = isOldFunctionTypeMangling(MangledName.data());
   Pos += PrefixLength;
 
   // If any other prefixes are accepted, please update Mangler::verify.
@@ -392,7 +414,7 @@
   auto TypeMangling = createNode(Node::Kind::TypeMangling);
 
   addChild(TypeMangling, LabelList);
-  addChild(TypeMangling, Type);
+  TypeMangling = addChild(TypeMangling, Type);
   return TypeMangling;
 }
 
@@ -884,7 +906,7 @@
 }
 
 NodePointer Demangler::popFunctionParamLabels(NodePointer Type) {
-  if (popNode(Node::Kind::EmptyList))
+  if (!IsOldFunctionTypeMangling && popNode(Node::Kind::EmptyList))
     return createNode(Node::Kind::LabelList);
 
   if (!Type || Type->getKind() != Node::Kind::Type)
@@ -905,15 +927,65 @@
   if (ParameterType->getIndex() == 0)
     return nullptr;
 
+  auto getChildIf =
+      [](NodePointer Node,
+         Node::Kind filterBy) -> std::pair<NodePointer, unsigned> {
+    for (unsigned i = 0, n = Node->getNumChildren(); i != n; ++i) {
+      auto Child = Node->getChild(i);
+      if (Child->getKind() == filterBy)
+        return {Child, i};
+    }
+    return {nullptr, 0};
+  };
+
+  auto getLabel = [&](NodePointer Params, unsigned Idx) -> NodePointer {
+    // Old-style function type mangling has labels as part of the argument.
+    if (IsOldFunctionTypeMangling) {
+      auto Param = Params->getChild(Idx);
+      auto Label = getChildIf(Param, Node::Kind::TupleElementName);
+
+      if (Label.first) {
+        Param->removeChildAt(Label.second, *this);
+        return createNodeWithAllocatedText(Node::Kind::Identifier,
+                                           Label.first->getText());
+      }
+
+      return createNode(Node::Kind::FirstElementMarker);
+    }
+
+    return popNode();
+  };
+
   auto LabelList = createNode(Node::Kind::LabelList);
+  auto Tuple = ParameterType->getFirstChild()->getFirstChild();
+
+  if (IsOldFunctionTypeMangling &&
+      (!Tuple || Tuple->getKind() != Node::Kind::Tuple))
+    return LabelList;
+
+  bool hasLabels = false;
   for (unsigned i = 0, n = ParameterType->getIndex(); i != n; ++i) {
-    auto Label = popNode();
-    assert(Label && (Label->getKind() == Node::Kind::Identifier ||
-                     Label->getKind() == Node::Kind::FirstElementMarker));
+    auto Label = getLabel(Tuple, i);
+
+    if (!Label)
+      return nullptr;
+
+    if (Label->getKind() != Node::Kind::Identifier &&
+        Label->getKind() != Node::Kind::FirstElementMarker)
+      return nullptr;
+
     LabelList->addChild(Label, *this);
+    hasLabels |= Label->getKind() != Node::Kind::FirstElementMarker;
   }
 
-  LabelList->reverseChildren();
+  // Old style label mangling can produce label list without
+  // actual labels, we need to support that case specifically.
+  if (!hasLabels)
+    return createNode(Node::Kind::LabelList);
+
+  if (!IsOldFunctionTypeMangling)
+    LabelList->reverseChildren();
+
   return LabelList;
 }
 
@@ -1999,16 +2071,16 @@
     case None:
       break;
     case Index:
-      addChild(Entity, NameOrIndex);
+      Entity = addChild(Entity, NameOrIndex);
       break;
     case TypeAndMaybePrivateName:
       addChild(Entity, LabelList);
-      addChild(Entity, ParamType);
+      Entity = addChild(Entity, ParamType);
       addChild(Entity, NameOrIndex);
       break;
     case TypeAndIndex:
-      addChild(Entity, NameOrIndex);
-      addChild(Entity, ParamType);
+      Entity = addChild(Entity, NameOrIndex);
+      Entity = addChild(Entity, ParamType);
       break;
   }
   return Entity;
@@ -2035,9 +2107,9 @@
   NodePointer Context = popContext();
 
   NodePointer Subscript = createNode(Node::Kind::Subscript);
-  addChild(Subscript, Context);
+  Subscript = addChild(Subscript, Context);
   addChild(Subscript, LabelList);
-  addChild(Subscript, Type);
+  Subscript = addChild(Subscript, Type);
   addChild(Subscript, PrivateName);
 
   return demangleAccessor(Subscript);
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index 63338be..fbc1ff1 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -163,16 +163,27 @@
   DemanglerPrinter Printer;
   DemangleOptions Options;
   bool SpecializationPrefixPrinted = false;
+  bool isValid = true;
 
 public:
   NodePrinter(DemangleOptions options) : Options(options) {}
   
   std::string printRoot(NodePointer root) {
+    isValid = true;
     print(root);
-    return std::move(Printer).str();
+    if (isValid)
+      return std::move(Printer).str();
+    return "";
   }
 
-private:  
+private:
+  /// Called when the node tree in valid.
+  ///
+  /// The demangler already catches most error cases and mostly produces valid
+  /// node trees. But some cases are difficult to catch in the demangler and
+  /// instead the NodePrinter bails.
+  void setInvalid() { isValid = false; }
+
   void printChildren(Node::iterator begin,
                      Node::iterator end,
                      const char *sep = nullptr) {
@@ -553,7 +564,10 @@
 
   void printFunctionParameters(NodePointer LabelList, NodePointer ParameterType,
                                bool showTypes) {
-    assert(ParameterType->getKind() == Node::Kind::ArgumentTuple);
+    if (ParameterType->getKind() != Node::Kind::ArgumentTuple) {
+      setInvalid();
+      return;
+    }
 
     NodePointer Parameters = ParameterType->getFirstChild();
     assert(Parameters->getKind() == Node::Kind::Type);
@@ -609,7 +623,10 @@
   }
 
   void printFunctionType(NodePointer LabelList, NodePointer node) {
-    assert(node->getNumChildren() == 2 || node->getNumChildren() == 3);
+    if (node->getNumChildren() != 2 && node->getNumChildren() != 3) {
+      setInvalid();
+      return;
+    }
     unsigned startIndex = 0;
     if (node->getChild(0)->getKind() == Node::Kind::ThrowsAnnotation)
       startIndex = 1;
@@ -1925,6 +1942,10 @@
   if (TypePr != TypePrinting::NoType) {
     NodePointer type = getChildIf(Entity, Node::Kind::Type);
     assert(type && "malformed entity");
+    if (!type) {
+      setInvalid();
+      return nullptr;
+    }
     type = type->getChild(0);
     if (TypePr == TypePrinting::FunctionStyle) {
       // We expect to see a function type here, but if we don't, use the colon.
diff --git a/lib/IRGen/ProtocolInfo.h b/lib/IRGen/ProtocolInfo.h
index cb37b83..f69374b 100644
--- a/lib/IRGen/ProtocolInfo.h
+++ b/lib/IRGen/ProtocolInfo.h
@@ -29,9 +29,7 @@
 
 namespace swift {
   class CanType;
-  class Decl;
   class ProtocolConformance;
-  class ProtocolDecl;
 
 namespace irgen {
   class ConformanceInfo; // private to GenProto.cpp
@@ -43,10 +41,11 @@
 /// introduced by the protocol.
 class WitnessTableEntry {
 public:
-  void *MemberOrAssociatedType;
+  llvm::PointerUnion<Decl *, TypeBase *> MemberOrAssociatedType;
   ProtocolDecl *Protocol;
 
-  WitnessTableEntry(void *member, ProtocolDecl *protocol)
+  WitnessTableEntry(llvm::PointerUnion<Decl *, TypeBase *> member,
+                    ProtocolDecl *protocol)
     : MemberOrAssociatedType(member), Protocol(protocol) {}
 
 public:
@@ -54,15 +53,15 @@
 
   static WitnessTableEntry forOutOfLineBase(ProtocolDecl *proto) {
     assert(proto != nullptr);
-    return WitnessTableEntry(nullptr, proto);
+    return WitnessTableEntry({}, proto);
   }
 
   /// Is this a base-protocol entry?
-  bool isBase() const { return MemberOrAssociatedType == nullptr; }
+  bool isBase() const { return MemberOrAssociatedType.isNull(); }
 
   bool matchesBase(ProtocolDecl *proto) const {
     assert(proto != nullptr);
-    return MemberOrAssociatedType == nullptr && Protocol == proto;
+    return MemberOrAssociatedType.isNull() && Protocol == proto;
   }
 
   /// Given that this is a base-protocol entry, is the table
@@ -83,19 +82,21 @@
   }
   
   bool isFunction() const {
-    return Protocol == nullptr &&
-           isa<AbstractFunctionDecl>(
-             static_cast<Decl*>(MemberOrAssociatedType));
+    auto decl = MemberOrAssociatedType.get<Decl*>();
+    return Protocol == nullptr && isa<AbstractFunctionDecl>(decl);
   }
 
   bool matchesFunction(AbstractFunctionDecl *func) const {
     assert(func != nullptr);
-    return MemberOrAssociatedType == func && Protocol == nullptr;
+    if (auto decl = MemberOrAssociatedType.dyn_cast<Decl*>())
+      return decl == func && Protocol == nullptr;
+    return false;
   }
 
   AbstractFunctionDecl *getFunction() const {
     assert(isFunction());
-    return static_cast<AbstractFunctionDecl*>(MemberOrAssociatedType);
+    auto decl = MemberOrAssociatedType.get<Decl*>();
+    return static_cast<AbstractFunctionDecl*>(decl);
   }
 
   static WitnessTableEntry forAssociatedType(AssociatedType ty) {
@@ -103,19 +104,21 @@
   }
   
   bool isAssociatedType() const {
-    return Protocol == nullptr &&
-           isa<AssociatedTypeDecl>(
-             static_cast<Decl*>(MemberOrAssociatedType));
+    if (auto decl = MemberOrAssociatedType.dyn_cast<Decl*>())
+      return Protocol == nullptr && isa<AssociatedTypeDecl>(decl);
+    return false;
   }
 
   bool matchesAssociatedType(AssociatedType assocType) const {
-    return MemberOrAssociatedType == assocType.getAssociation() &&
-           Protocol == nullptr;
+    if (auto decl = MemberOrAssociatedType.dyn_cast<Decl*>())
+      return decl == assocType.getAssociation() && Protocol == nullptr;
+    return false;
   }
 
   AssociatedTypeDecl *getAssociatedType() const {
     assert(isAssociatedType());
-    return static_cast<AssociatedTypeDecl*>(MemberOrAssociatedType);
+    auto decl = MemberOrAssociatedType.get<Decl*>();
+    return static_cast<AssociatedTypeDecl*>(decl);
   }
 
   static WitnessTableEntry forAssociatedConformance(AssociatedConformance conf){
@@ -124,17 +127,20 @@
   }
 
   bool isAssociatedConformance() const {
-    return Protocol != nullptr && MemberOrAssociatedType != nullptr;
+    return Protocol != nullptr && !MemberOrAssociatedType.isNull();
   }
 
   bool matchesAssociatedConformance(const AssociatedConformance &conf) const {
-    return MemberOrAssociatedType == conf.getAssociation().getPointer() &&
-           Protocol == conf.getAssociatedRequirement();
+    if (auto type = MemberOrAssociatedType.dyn_cast<TypeBase*>())
+      return type == conf.getAssociation().getPointer() &&
+             Protocol == conf.getAssociatedRequirement();
+    return false;
   }
 
   CanType getAssociatedConformancePath() const {
     assert(isAssociatedConformance());
-    return CanType(static_cast<TypeBase *>(MemberOrAssociatedType));
+    auto type = MemberOrAssociatedType.get<TypeBase*>();
+    return CanType(type);
   }
 
   ProtocolDecl *getAssociatedConformanceRequirement() const {
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index b76b538..c62282b 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -475,6 +475,7 @@
     return parseExprPostfix(Message, isExprBasic);
 
   case tok::amp_prefix: {
+    SyntaxParsingContext AmpCtx(SyntaxContext, SyntaxKind::InOutExpr);
     SourceLoc Loc = consumeToken(tok::amp_prefix);
 
     ParserResult<Expr> SubExpr = parseExprUnary(Message, isExprBasic);
@@ -558,9 +559,11 @@
 ///   !
 ///   [ expression ]
 ParserResult<Expr> Parser::parseExprKeyPath() {
+  SyntaxParsingContext KeyPathCtx(SyntaxContext, SyntaxKind::KeyPathExpr);
   // Consume '\'.
   SourceLoc backslashLoc = consumeToken(tok::backslash);
   llvm::SaveAndRestore<SourceLoc> slashLoc(SwiftKeyPathSlashLoc, backslashLoc);
+  SyntaxParsingContext ExprCtx(SyntaxContext, SyntaxContextKind::Expr);
 
   // FIXME: diagnostics
   ParserResult<Expr> rootResult, pathResult;
@@ -606,6 +609,7 @@
 ///     '#keyPath' '(' unqualified-name ('.' unqualified-name) * ')'
 ///
 ParserResult<Expr> Parser::parseExprKeyPathObjC() {
+  SyntaxParsingContext ObjcKPCtx(SyntaxContext, SyntaxKind::ObjcKeyPathExpr);
   // Consume '#keyPath'.
   SourceLoc keywordLoc = consumeToken(tok::pound_keyPath);
 
@@ -636,6 +640,7 @@
   // Parse the sequence of unqualified-names.
   ParserStatus status;
   while (true) {
+    SyntaxParsingContext NamePieceCtx(SyntaxContext, SyntaxKind::ObjcNamePiece);
     // Handle code completion.
     if (Tok.is(tok::code_complete))
       return handleCodeCompletion(!components.empty());
@@ -667,6 +672,9 @@
     break;
   }
 
+  // Collect all name pieces to an objc name.
+  SyntaxContext->collectNodesInPlace(SyntaxKind::ObjcName);
+
   // Parse the closing ')'.
   SourceLoc rParenLoc;
   if (status.isError()) {
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 3376344..dabe4b9 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -3607,12 +3607,34 @@
   }
   
   void checkInitBlockStorageHeaderInst(InitBlockStorageHeaderInst *IBSHI) {
-    require(IBSHI->getBlockStorage()->getType().isAddress(),
+    auto storage = IBSHI->getBlockStorage();
+    require(storage->getType().isAddress(),
             "block storage operand must be an address");
-    auto storageTy
-      = IBSHI->getBlockStorage()->getType().getAs<SILBlockStorageType>();
+
+    auto storageTy = storage->getType().getAs<SILBlockStorageType>();
     require(storageTy, "block storage operand must be a @block_storage type");
-    
+
+    auto captureTy = storageTy->getCaptureType();
+    if (auto capturedFnTy = captureTy->getAs<SILFunctionType>()) {
+      if (capturedFnTy->isNoEscape()) {
+        // If the capture is a noescape function then it must be possible to
+        // locally determine the value stored to initialize the storage for the
+        // capture. This is required to diagnose static exclusivity violations
+        // when a noescape closure is converted to a noescape block that
+        // is then passed to a function.
+        auto *storageProjection =
+           storage->getSingleUserOfType<ProjectBlockStorageInst>();
+        require(storageProjection,
+                "block storage operand with noescape capture must have "
+                "projection from block");
+
+        auto *storeInst = storageProjection->getSingleUserOfType<StoreInst>();
+        require(storeInst,
+                "block storage operand with noescape capture must have "
+                "store to projection");
+      }
+    }
+
     require(IBSHI->getInvokeFunction()->getType().isObject(),
             "invoke function operand must be a value");
     auto invokeTy
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 75e8369..89fc3c4 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -524,7 +524,7 @@
     Expr *buildDeclRef(ValueDecl *decl, DeclNameLoc loc, Type openedType,
                        ConstraintLocatorBuilder locator, bool implicit,
                        FunctionRefKind functionRefKind,
-                       AccessSemantics semantics) {
+                       AccessSemantics semantics, bool forceUnwrap) {
       // Determine the declaration selected for this overloaded reference.
       auto &ctx = cs.getASTContext();
       
@@ -554,7 +554,7 @@
                          ConformanceCheckFlags::Used));
             if (conformance && conformance->isConcrete()) {
               if (auto witness =
-                        conformance->getConcrete()->getWitnessDecl(decl, &tc)) {
+                      conformance->getConcrete()->getWitnessDecl(decl, &tc)) {
                 // Hack up an AST that we can type-check (independently) to get
                 // it into the right form.
                 // FIXME: the hop through 'getDecl()' is because
@@ -583,11 +583,14 @@
 
                 cs.cacheExprTypes(refExpr);
 
-               // Remove an outer function-conversion expression. This
-               // happens when we end up referring to a witness for a
-               // superclass conformance, and 'Self' differs.
-               if (auto fnConv = dyn_cast<FunctionConversionExpr>(refExpr))
-                 refExpr = fnConv->getSubExpr();
+                // Remove an outer function-conversion expression. This
+                // happens when we end up referring to a witness for a
+                // superclass conformance, and 'Self' differs.
+                if (auto fnConv = dyn_cast<FunctionConversionExpr>(refExpr))
+                  refExpr = fnConv->getSubExpr();
+
+                if (forceUnwrap)
+                  return forceUnwrapResult(refExpr);
 
                 return refExpr;
               }
@@ -600,10 +603,10 @@
           TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx);
         cs.cacheExprTypes(base);
 
-        return buildMemberRef(base, openedType, SourceLoc(), decl,
-                              loc, openedFnType->getResult(),
-                              locator, locator, implicit, functionRefKind,
-                              semantics, /*isDynamic=*/false);
+        return buildMemberRef(base, openedType, SourceLoc(), decl, loc,
+                              openedFnType->getResult(), locator, locator,
+                              implicit, functionRefKind, semantics,
+                              /*isDynamic=*/false, forceUnwrap);
       }
 
       auto type = solution.simplifyType(openedType);
@@ -636,6 +639,9 @@
                               loc, implicit, semantics, type);
       cs.cacheType(declRefExpr);
       declRefExpr->setFunctionRefKind(functionRefKind);
+      if (forceUnwrap)
+        return forceUnwrapResult(declRefExpr);
+
       return declRefExpr;
     }
 
@@ -878,9 +884,10 @@
     Expr *buildMemberRef(Expr *base, Type openedFullType, SourceLoc dotLoc,
                          ValueDecl *member, DeclNameLoc memberLoc,
                          Type openedType, ConstraintLocatorBuilder locator,
-                         ConstraintLocatorBuilder memberLocator,
-                         bool Implicit, FunctionRefKind functionRefKind,
-                         AccessSemantics semantics, bool isDynamic) {
+                         ConstraintLocatorBuilder memberLocator, bool Implicit,
+                         FunctionRefKind functionRefKind,
+                         AccessSemantics semantics, bool isDynamic,
+                         bool forceUnwrap) {
       auto &tc = cs.getTypeChecker();
       auto &context = tc.Context;
 
@@ -933,9 +940,11 @@
         auto ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit);
         cs.setType(ref, refTy);
         ref->setFunctionRefKind(functionRefKind);
-        return cs.cacheType(new (context)
-                                DotSyntaxBaseIgnoredExpr(base, dotLoc, ref,
-                                                         cs.getType(ref)));
+        auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr(
+            base, dotLoc, ref, cs.getType(ref)));
+        if (forceUnwrap)
+          return forceUnwrapResult(DSBI);
+        return DSBI;
       }
 
       // The formal type of the 'self' value for the member's declaration.
@@ -1056,6 +1065,8 @@
           }
         }
 
+        if (forceUnwrap)
+          return forceUnwrapResult(ref);
         return ref;
       }
 
@@ -1082,6 +1093,8 @@
         cs.setType(memberRefExpr, simplifyType(openedType));
         Expr *result = memberRefExpr;
         closeExistential(result, locator);
+        if (forceUnwrap)
+          return forceUnwrapResult(result);
         return result;
       }
       
@@ -1102,6 +1115,8 @@
       ApplyExpr *apply;
       if (isa<ConstructorDecl>(member)) {
         // FIXME: Provide type annotation.
+        if (forceUnwrap)
+          ref = forceUnwrapResult(ref);
         apply = new (context) ConstructorRefCallExpr(ref, base);
       } else if (!baseIsInstance && member->isInstanceMember()) {
         // Reference to an unbound instance method.
@@ -1110,10 +1125,15 @@
                                                               cs.getType(ref));
         cs.cacheType(result);
         closeExistential(result, locator, /*force=*/openedExistential);
+        if (forceUnwrap)
+          return forceUnwrapResult(result);
         return result;
       } else {
         assert((!baseIsInstance || member->isInstanceMember()) &&
                "can't call a static method on an instance");
+        if (forceUnwrap)
+          ref = forceUnwrapResult(ref);
+
         apply = new (context) DotSyntaxCallExpr(ref, dotLoc, base);
         if (Implicit) {
           apply->setImplicit();
@@ -1358,8 +1378,9 @@
     Expr *buildSubscript(Expr *base, Expr *index,
                          ArrayRef<Identifier> argLabels,
                          bool hasTrailingClosure,
-                         ConstraintLocatorBuilder locator,
-                         bool isImplicit, AccessSemantics semantics) {
+                         ConstraintLocatorBuilder locator, bool isImplicit,
+                         AccessSemantics semantics) {
+
       // Determine the declaration selected for this subscript operation.
       auto selected = getOverloadChoiceIfAvailable(
                         cs.getConstraintLocator(
@@ -1386,13 +1407,31 @@
         return nullptr;
       }
 
-      auto choice = selected->choice;
-      
+      // Build the new subscript.
+      auto newSubscript = buildSubscriptHelper(base, index, argLabels,
+                                               *selected, hasTrailingClosure,
+                                               locator, isImplicit, semantics);
+
+      if (shouldForceUnwrapResult(cs.getConstraintLocator(locator)->getAnchor(),
+                                  selected->choice))
+        return forceUnwrapResult(newSubscript);
+
+      return newSubscript;
+    }
+
+    Expr *buildSubscriptHelper(Expr *base, Expr *index,
+                               ArrayRef<Identifier> argLabels,
+                               SelectedOverload &selected,
+                               bool hasTrailingClosure,
+                               ConstraintLocatorBuilder locator,
+                               bool isImplicit, AccessSemantics semantics) {
+      auto choice = selected.choice;
+
       // Apply a key path if we have one.
       if (choice.getKind() == OverloadChoiceKind::KeyPathApplication) {
-        auto applicationTy = simplifyType(selected->openedType)
-          ->castTo<FunctionType>();
-                
+        auto applicationTy =
+            simplifyType(selected.openedType)->castTo<FunctionType>();
+
         index = cs.coerceToRValue(index);
         // The index argument should be (keyPath: KeyPath<Root, Value>).
         // Dig the key path expression out of the argument tuple.
@@ -1495,7 +1534,7 @@
       }
 
       // Figure out the index and result types.
-      auto subscriptTy = simplifyType(selected->openedType);
+      auto subscriptTy = simplifyType(selected.openedType);
       auto subscriptFnTy = subscriptTy->castTo<AnyFunctionType>();
       auto resultTy = subscriptFnTy->getResult();
 
@@ -1551,7 +1590,7 @@
       }
 
       // Convert the base.
-      auto openedFullFnType = selected->openedFullType->castTo<FunctionType>();
+      auto openedFullFnType = selected.openedFullType->castTo<FunctionType>();
       auto openedBaseType = openedFullFnType->getInput();
       auto containerTy = solution.simplifyType(openedBaseType);
       base = coerceObjectArgumentToType(
@@ -2362,6 +2401,31 @@
       return expr;
     }
 
+    bool shouldForceUnwrapResult(Expr *expr, OverloadChoice &choice) {
+      if (!choice.isImplicitlyUnwrappedValueOrReturnValue())
+        return false;
+
+      auto choiceLocator = cs.getConstraintLocator(
+          expr, ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice);
+
+      return solution.getDisjunctionChoice(choiceLocator);
+    }
+
+    Expr *forceUnwrapResult(Expr *newExpr) {
+      auto ty = simplifyType(cs.getType(newExpr));
+
+      if (auto *fnTy = ty->getAs<AnyFunctionType>()) {
+        auto underlyingType = cs.replaceFinalResultTypeWithUnderlying(fnTy);
+
+        auto &ctx = cs.getTypeChecker().Context;
+        return cs.cacheType(new (ctx) ImplicitlyUnwrappedFunctionConversionExpr(
+            newExpr, underlyingType));
+      } else {
+        return coerceImplicitlyUnwrappedOptionalToValue(
+            newExpr, ty->getWithoutSpecifierType()->getAnyOptionalObjectType());
+      }
+    }
+
     Expr *visitDeclRefExpr(DeclRefExpr *expr) {
       auto locator = cs.getConstraintLocator(expr);
 
@@ -2378,13 +2442,11 @@
       auto choice = selected->choice;
       auto decl = choice.getDecl();
 
-      // FIXME: Cannibalize the existing DeclRefExpr rather than allocating a
-      // new one?
+      auto forceUnwrap = shouldForceUnwrapResult(expr, choice);
       return buildDeclRef(decl, expr->getNameLoc(), selected->openedFullType,
-                          locator,
-                          expr->isImplicit(),
+                          locator, expr->isImplicit(),
                           expr->getFunctionRefKind(),
-                          expr->getAccessSemantics());
+                          expr->getAccessSemantics(), forceUnwrap);
     }
 
     Expr *visitSuperRefExpr(SuperRefExpr *expr) {
@@ -2416,10 +2478,11 @@
       auto choice = selected.choice;
       auto decl = choice.getDecl();
 
+      auto forceUnwrap = shouldForceUnwrapResult(expr, choice);
       return buildDeclRef(decl, expr->getNameLoc(), selected.openedFullType,
                           locator, expr->isImplicit(),
                           choice.getFunctionRefKind(),
-                          AccessSemantics::Ordinary);
+                          AccessSemantics::Ordinary, forceUnwrap);
     }
 
     Expr *visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *expr) {
@@ -2439,17 +2502,13 @@
       auto selected = getOverloadChoice(memberLocator);
       bool isDynamic
         = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
-      return buildMemberRef(expr->getBase(),
-                            selected.openedFullType,
-                            expr->getDotLoc(),
-                            selected.choice.getDecl(), expr->getNameLoc(),
-                            selected.openedType,
-                            cs.getConstraintLocator(expr),
-                            memberLocator,
-                            expr->isImplicit(),
-                            selected.choice.getFunctionRefKind(),
-                            expr->getAccessSemantics(),
-                            isDynamic);
+      auto forceUnwrap = shouldForceUnwrapResult(expr, selected.choice);
+      return buildMemberRef(
+          expr->getBase(), selected.openedFullType, expr->getDotLoc(),
+          selected.choice.getDecl(), expr->getNameLoc(), selected.openedType,
+          cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
+          selected.choice.getFunctionRefKind(), expr->getAccessSemantics(),
+          isDynamic, forceUnwrap);
     }
 
     Expr *visitDynamicMemberRefExpr(DynamicMemberRefExpr *expr) {
@@ -2493,17 +2552,13 @@
       // Build the member reference.
       bool isDynamic
         = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
-      auto result = buildMemberRef(base,
-                                   selected.openedFullType,
-                                   expr->getDotLoc(), member, 
-                                   expr->getNameLoc(),
-                                   selected.openedType,
-                                   cs.getConstraintLocator(expr),
-                                   memberLocator,
-                                   expr->isImplicit(),
-                                   selected.choice.getFunctionRefKind(),
-                                   AccessSemantics::Ordinary,
-                                   isDynamic);
+      auto forceUnwrap = shouldForceUnwrapResult(expr, selected.choice);
+      auto result = buildMemberRef(
+          base, selected.openedFullType, expr->getDotLoc(), member,
+          expr->getNameLoc(), selected.openedType,
+          cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(),
+          selected.choice.getFunctionRefKind(), AccessSemantics::Ordinary,
+          isDynamic, forceUnwrap);
       if (!result)
         return nullptr;
 
@@ -2520,8 +2575,7 @@
         result = finishApply(apply, Type(), cs.getConstraintLocator(expr));
       }
 
-      result = coerceToType(result, resultTy, cs.getConstraintLocator(expr));
-      return result;
+      return coerceToType(result, resultTy, cs.getConstraintLocator(expr));
     }
     
   private:
@@ -2550,15 +2604,12 @@
       // If the subexpression is a metatype, build a direct reference to the
       // constructor.
       if (cs.getType(base)->is<AnyMetatypeType>()) {
-        return buildMemberRef(base, openedType, dotLoc, ctor, nameLoc,
-                              cs.getType(expr),
-                              ConstraintLocatorBuilder(
-                                cs.getConstraintLocator(expr)),
-                              ctorLocator,
-                              implicit,
-                              functionRefKind,
-                              AccessSemantics::Ordinary,
-                              /*isDynamic=*/false);
+        return buildMemberRef(
+            base, openedType, dotLoc, ctor, nameLoc, cs.getType(expr),
+            ConstraintLocatorBuilder(cs.getConstraintLocator(expr)),
+            ctorLocator, implicit, functionRefKind, AccessSemantics::Ordinary,
+            /*isDynamic=*/false,
+            /*forceUnwrap=*/false);
       }
 
       // The subexpression must be either 'self' or 'super'.
@@ -2675,24 +2726,15 @@
 
       case OverloadChoiceKind::Decl:
       case OverloadChoiceKind::DeclViaUnwrappedOptional:
-      case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
       case OverloadChoiceKind::DeclViaDynamic: {
         bool isDynamic
           = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
-        auto member = buildMemberRef(base,
-                                     selected.openedFullType,
-                                     dotLoc,
-                                     selected.choice.getDecl(),
-                                     nameLoc,
-                                     selected.openedType,
-                                     cs.getConstraintLocator(expr),
-                                     memberLocator,
-                                     implicit,
-                                     selected.choice.getFunctionRefKind(),
-                                     AccessSemantics::Ordinary,
-                                     isDynamic);
-
-        return member;
+        auto forceUnwrap = shouldForceUnwrapResult(expr, selected.choice);
+        return buildMemberRef(
+            base, selected.openedFullType, dotLoc, selected.choice.getDecl(),
+            nameLoc, selected.openedType, cs.getConstraintLocator(expr),
+            memberLocator, implicit, selected.choice.getFunctionRefKind(),
+            AccessSemantics::Ordinary, isDynamic, forceUnwrap);
       }
 
       case OverloadChoiceKind::TupleIndex: {
@@ -3433,7 +3475,7 @@
           return nullptr;
 
         return coerceImplicitlyUnwrappedOptionalToValue(
-            coerced, cs.getType(coerced)->getOptionalObjectType());
+            coerced, cs.getType(coerced)->getAnyOptionalObjectType());
       }
 
       return visitCoerceExpr(expr, None);
@@ -3518,7 +3560,7 @@
           return nullptr;
 
         return coerceImplicitlyUnwrappedOptionalToValue(
-            coerced, cs.getType(coerced)->getOptionalObjectType());
+            coerced, cs.getType(coerced)->getAnyOptionalObjectType());
       }
 
       return handleForcedCheckedCastExpr(expr);
@@ -3598,7 +3640,7 @@
           return nullptr;
 
         return coerceImplicitlyUnwrappedOptionalToValue(
-            coerced, cs.getType(coerced)->getOptionalObjectType());
+            coerced, cs.getType(coerced)->getAnyOptionalObjectType());
       }
 
       return handleConditionalCheckedCastExpr(expr);
@@ -7145,6 +7187,12 @@
   if (auto fnTy = cs.lookThroughImplicitlyUnwrappedOptionalType(cs.getType(fn)))
     fn = coerceImplicitlyUnwrappedOptionalToValue(fn, fnTy);
 
+  bool unwrapResult = false;
+  if (auto *IUOFnTy = dyn_cast<ImplicitlyUnwrappedFunctionConversionExpr>(fn)) {
+    unwrapResult = true;
+    fn = IUOFnTy->getSubExpr();
+  }
+
   // If we're applying a function that resulted from a covariant
   // function conversion, strip off that conversion.
   // FIXME: It would be nicer if we could build the ASTs properly in the
@@ -7249,9 +7297,16 @@
           }
       }
     }
+
+    if (unwrapResult)
+      return forceUnwrapResult(result);
+
     return result;
   }
 
+  // FIXME: handle unwrapping everywhere else
+  assert(!unwrapResult);
+
   // If this is an UnresolvedType in the system, preserve it.
   if (cs.getType(fn)->is<UnresolvedType>()) {
     cs.setType(apply, cs.getType(fn));
@@ -7308,17 +7363,13 @@
   // Consider the constructor decl reference expr 'implicit', but the
   // constructor call expr itself has the apply's 'implicitness'.
   bool isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic;
-  Expr *declRef = buildMemberRef(fn,
-                                 selected->openedFullType,
-                                 /*dotLoc=*/SourceLoc(),
-                                 decl, DeclNameLoc(fn->getEndLoc()),
-                                 selected->openedType,
-                                 locator,
-                                 ctorLocator,
-                                 /*Implicit=*/true,
-                                 choice.getFunctionRefKind(),
-                                 AccessSemantics::Ordinary,
-                                 isDynamic);
+  auto forceUnwrap = shouldForceUnwrapResult(apply, choice);
+  Expr *declRef =
+      buildMemberRef(fn, selected->openedFullType,
+                     /*dotLoc=*/SourceLoc(), decl, DeclNameLoc(fn->getEndLoc()),
+                     selected->openedType, locator, ctorLocator,
+                     /*Implicit=*/true, choice.getFunctionRefKind(),
+                     AccessSemantics::Ordinary, isDynamic, forceUnwrap);
   if (!declRef)
     return nullptr;
   declRef->setImplicit(apply->isImplicit());
@@ -8008,15 +8059,13 @@
   ExprRewriter rewriter(cs, solution,
                         /*suppressDiagnostics=*/false);
 
-  auto memberRef = rewriter.buildMemberRef(base, openedFullType,
-                                           base->getStartLoc(),
-                                           witness,
-                                           DeclNameLoc(base->getEndLoc()),
-                                           openedType, dotLocator, dotLocator,
-                                           /*Implicit=*/true,
-                                           FunctionRefKind::SingleApply,
-                                           AccessSemantics::Ordinary,
-                                           /*isDynamic=*/false);
+  auto memberRef = rewriter.buildMemberRef(
+      base, openedFullType, base->getStartLoc(), witness,
+      DeclNameLoc(base->getEndLoc()), openedType, dotLocator, dotLocator,
+      /*Implicit=*/true, FunctionRefKind::SingleApply,
+      AccessSemantics::Ordinary,
+      /*isDynamic=*/false,
+      /*forceUnwrap=*/false);
   call->setFn(memberRef);
 
   // Call the witness.
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index bea8ac3..00cc13e 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -522,7 +522,6 @@
       case OverloadChoiceKind::DeclViaDynamic:
       case OverloadChoiceKind::DeclViaBridge:
       case OverloadChoiceKind::DeclViaUnwrappedOptional:
-      case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
         // FIXME: show deduced types, etc, etc.
         if (EmittedDecls.insert(choice.getDecl()).second)
           tc.diagnose(choice.getDecl(), diag::found_candidate);
@@ -8404,8 +8403,7 @@
     if (resolved->Locator != locator) continue;
     
     // We only handle the simplest decl binding.
-    if (resolved->Choice.getKind() != OverloadChoiceKind::Decl
-        && resolved->Choice.getKind() != OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional)
+    if (resolved->Choice.getKind() != OverloadChoiceKind::Decl)
       return nullptr;
     return resolved->Choice.getDecl();
   }
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 5d08812..bfd98e3 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -997,13 +997,8 @@
                                       TVO_CanBindToLValue |
                                       TVO_CanBindToInOut);
 
-      OverloadChoice choice;
-      if (decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
-        choice = OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
-            CS.getType(base), decl, functionRefKind);
-      } else {
-        choice = OverloadChoice(CS.getType(base), decl, functionRefKind);
-      }
+      OverloadChoice choice =
+          OverloadChoice(CS.getType(base), decl, functionRefKind);
 
       auto locator = CS.getConstraintLocator(expr, ConstraintLocator::Member);
       CS.addBindOverloadConstraint(tv, choice, locator, CurDC);
@@ -1106,13 +1101,8 @@
       // a known subscript here. This might be cleaner if we split off a new
       // UnresolvedSubscriptExpr from SubscriptExpr.
       if (auto decl = declOrNull) {
-        OverloadChoice choice;
-        if (decl->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
-          choice = OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
-              baseTy, decl, FunctionRefKind::DoubleApply);
-        } else {
-          choice = OverloadChoice(baseTy, decl, FunctionRefKind::DoubleApply);
-        }
+        OverloadChoice choice =
+            OverloadChoice(baseTy, decl, FunctionRefKind::DoubleApply);
         CS.addBindOverloadConstraint(fnTy, choice, memberLocator,
                                      CurDC);
       } else {
@@ -1309,15 +1299,8 @@
       auto tv = CS.createTypeVariable(locator,
                                       TVO_CanBindToLValue);
 
-      OverloadChoice choice;
-      if (E->getDecl()
-              ->getAttrs()
-              .hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
-        choice = OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
-            Type(), E->getDecl(), E->getFunctionRefKind());
-      } else {
-        choice = OverloadChoice(Type(), E->getDecl(), E->getFunctionRefKind());
-      }
+      OverloadChoice choice =
+          OverloadChoice(Type(), E->getDecl(), E->getFunctionRefKind());
       CS.resolveOverload(locator, tv, choice, CurDC);
 
       if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
@@ -1394,15 +1377,8 @@
         if (decls[i]->isInvalid())
           continue;
 
-        OverloadChoice choice;
-        if (decls[i]
-                ->getAttrs()
-                .hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
-          choice = OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
-              Type(), decls[i], expr->getFunctionRefKind());
-        } else {
-          choice = OverloadChoice(Type(), decls[i], expr->getFunctionRefKind());
-        }
+        OverloadChoice choice =
+            OverloadChoice(Type(), decls[i], expr->getFunctionRefKind());
         choices.push_back(choice);
       }
 
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index e5b6a37..4f38811 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -131,26 +131,10 @@
   return false;
 }
 
-static bool sameChoiceKind(const OverloadChoice &lhs,
-                           const OverloadChoice &rhs) {
-  if (lhs.getKind() == rhs.getKind())
-    return true;
-
-  if (lhs.getKind() == OverloadChoiceKind::Decl
-      && rhs.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional)
-    return true;
-
-  if (lhs.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional
-      && rhs.getKind() == OverloadChoiceKind::Decl)
-    return true;
-
-  return false;
-}
-
 /// \brief Compare two overload choices for equality.
 static bool sameOverloadChoice(const OverloadChoice &x,
                                const OverloadChoice &y) {
-  if (!sameChoiceKind(x, y))
+  if (x.getKind() != y.getKind())
     return false;
 
   switch (x.getKind()) {
@@ -163,7 +147,6 @@
   case OverloadChoiceKind::DeclViaDynamic:
   case OverloadChoiceKind::DeclViaBridge:
   case OverloadChoiceKind::DeclViaUnwrappedOptional:
-  case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
     return sameDecl(x.getDecl(), y.getDecl());
 
   case OverloadChoiceKind::TupleIndex:
@@ -834,14 +817,13 @@
     }
     
     // If the kinds of overload choice don't match...
-    if (!sameChoiceKind(choice1, choice2)) {
+    if (choice1.getKind() != choice2.getKind()) {
       identical = false;
       
       // A declaration found directly beats any declaration found via dynamic
       // lookup, bridging, or optional unwrapping.
-      if ((choice1.getKind() == OverloadChoiceKind::Decl
-           || choice1.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional) &&
-          (choice2.getKind() == OverloadChoiceKind::DeclViaDynamic || 
+      if ((choice1.getKind() == OverloadChoiceKind::Decl) &&
+          (choice2.getKind() == OverloadChoiceKind::DeclViaDynamic ||
            choice2.getKind() == OverloadChoiceKind::DeclViaBridge ||
            choice2.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional)) {
         score1 += weight;
@@ -851,8 +833,7 @@
       if ((choice1.getKind() == OverloadChoiceKind::DeclViaDynamic ||
            choice1.getKind() == OverloadChoiceKind::DeclViaBridge ||
            choice1.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional) &&
-          (choice2.getKind() == OverloadChoiceKind::Decl
-           || choice2.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional)) {
+          choice2.getKind() == OverloadChoiceKind::Decl) {
         score2 += weight;
         continue;
       }
@@ -874,7 +855,6 @@
     case OverloadChoiceKind::Decl:
     case OverloadChoiceKind::DeclViaBridge:
     case OverloadChoiceKind::DeclViaUnwrappedOptional:
-    case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
       break;
     }
     
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 5cd68af..8653398 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1521,6 +1521,49 @@
     return SolutionKind::Solved;
   }
 
+  // If we're binding an optional type, or function type that has an
+  // optional result type, this may be the result of an IUO
+  // declaration. These are candidates for creating a disjunction.
+  bool isOptional = false;
+  if (type->getRValueType()->getAnyOptionalObjectType()) {
+    isOptional = true;
+  } else if (auto *fnTy = type->getAs<AnyFunctionType>()) {
+    auto resultTy = fnTy->getResult();
+    while (resultTy->is<AnyFunctionType>())
+      resultTy = resultTy->castTo<AnyFunctionType>()->getResult();
+
+    // FIXME: work-around the fact that doesStorageProduceLValue returns true
+    // for
+    //        #selector(getter: NSMenuItem.action)
+    resultTy = resultTy->getRValueType();
+
+    if (resultTy->getAnyOptionalObjectType()) {
+      isOptional = true;
+    }
+  }
+
+  if (isOptional) {
+    SmallVector<LocatorPathElt, 4> path;
+    locator.getLocatorParts(path);
+
+    // Find the last element that is either an indication we need to
+    // create a disjunction, or an indication that we already have.
+    auto last = std::find_if(
+        path.rbegin(), path.rend(), [](LocatorPathElt &elt) -> bool {
+          return elt.getKind() == ConstraintLocator::ImplicitlyUnwrappedValue ||
+                 elt.getKind() ==
+                     ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice;
+        });
+
+    // If we need to create a disjunction for this value, do so.
+    if (last != path.rend() &&
+        last->getKind() == ConstraintLocator::ImplicitlyUnwrappedValue) {
+      buildDisjunctionForImplicitlyUnwrappedOptional(
+          typeVar, type, getConstraintLocator(locator));
+      return SolutionKind::Solved;
+    }
+  }
+
   assignFixedType(typeVar, type);
 
   return SolutionKind::Solved;
@@ -3207,11 +3250,6 @@
                                                          functionRefKind);
     }
 
-    if (cand->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>()) {
-      return OverloadChoice::getDeclForImplicitlyUnwrappedOptional(
-          baseTy, cand, functionRefKind);
-    }
-
     return OverloadChoice(baseTy, cand, functionRefKind);
   };
   
diff --git a/lib/Sema/CalleeCandidateInfo.cpp b/lib/Sema/CalleeCandidateInfo.cpp
index f70ad84..75e642e 100644
--- a/lib/Sema/CalleeCandidateInfo.cpp
+++ b/lib/Sema/CalleeCandidateInfo.cpp
@@ -830,8 +830,7 @@
         // Look through optional or IUO to get the underlying type the decl was
         // found in.
         substType = substType->getAnyOptionalObjectType();
-      } else if (cand.getKind() != OverloadChoiceKind::Decl
-                 && cand.getKind() != OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional) {
+      } else if (cand.getKind() != OverloadChoiceKind::Decl) {
         // Otherwise, if it is a remapping we can't handle, don't try to compute
         // a substitution.
         substType = Type();
diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp
index 49f4d08..8d68fa9 100644
--- a/lib/Sema/Constraint.cpp
+++ b/lib/Sema/Constraint.cpp
@@ -358,10 +358,6 @@
       Out << "decl-via-unwrapped-optional ";
       printDecl();
       break;
-    case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
-      Out << "decl-for-implicitly-unwrapped-optional ";
-      printDecl();
-      break;
     case OverloadChoiceKind::BaseType:
       Out << "base type";
       break;
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index a5795b5..5717faf 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -1403,9 +1403,8 @@
                                                      OverloadChoice choice,
                                                      Type &refType,
                                                      Type &openedFullType) {
-  assert(choice.getKind() == OverloadChoiceKind::Decl
-         || choice.getKind() == OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional);
-  
+  assert(choice.getKind() == OverloadChoiceKind::Decl);
+
   switch (CS.TC.getDeclTypeCheckingSemantics(choice.getDecl())) {
   case DeclTypeCheckingSemantics::Normal:
     return false;
@@ -1515,7 +1514,6 @@
   Type openedFullType;
   switch (auto kind = choice.getKind()) {
   case OverloadChoiceKind::Decl:
-  case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
     // If we refer to a top-level decl with special type-checking semantics,
     // handle it now.
     if (resolveOverloadForDeclWithSpecialTypeCheckingSemantics(
@@ -1675,8 +1673,7 @@
   // value. Processing the bind constraint will generate a new
   // disjunction constraint that attempts the Optional and if that
   // doesn't succeed, the underlying type.
-  if (choice.getKind() ==
-      OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional) {
+  if (choice.isImplicitlyUnwrappedValueOrReturnValue()) {
     locator = getConstraintLocator(locator,
                                    ConstraintLocator::ImplicitlyUnwrappedValue);
   }
@@ -1838,7 +1835,6 @@
     case OverloadChoiceKind::DeclViaDynamic:
     case OverloadChoiceKind::DeclViaBridge:
     case OverloadChoiceKind::DeclViaUnwrappedOptional:
-    case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
       return getDecl()->getFullName();
       
     case OverloadChoiceKind::KeyPathApplication: {
@@ -1855,3 +1851,10 @@
   
   llvm_unreachable("Unhandled OverloadChoiceKind in switch.");
 }
+
+bool OverloadChoice::isImplicitlyUnwrappedValueOrReturnValue() const {
+  // FIXME: Disable new IUO implementation for now.
+  return false;
+  return isDecl() &&
+         getDecl()->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
+}
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 6947b61..7b829f8 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -2331,6 +2331,36 @@
                           ConstraintLocatorBuilder locator);
 
 public:
+  /// Given a function type where the eventual result type is an optional,
+  /// where "eventual result type" is defined as:
+  ///   1. The result type is an optional
+  ///   2. The result type is a function type with an eventual result
+  ///      type that is an optional.
+  ///
+  /// return the same function type but with the eventual result type
+  /// replaced by its underlying type.
+  ///
+  /// i.e. return (S) -> T for (S) -> T?
+  //       return (X) -> () -> Y for (X) -> () -> Y?
+  Type replaceFinalResultTypeWithUnderlying(AnyFunctionType *fnTy) {
+    auto resultTy = fnTy->getResult();
+    if (auto *resultFnTy = resultTy->getAs<AnyFunctionType>())
+      resultTy = replaceFinalResultTypeWithUnderlying(resultFnTy);
+    else
+      resultTy =
+          resultTy->getWithoutSpecifierType()->getAnyOptionalObjectType();
+
+    assert(resultTy);
+
+    if (auto *genericFn = fnTy->getAs<GenericFunctionType>()) {
+      return GenericFunctionType::get(genericFn->getGenericSignature(),
+                                      genericFn->getParams(), resultTy,
+                                      genericFn->getExtInfo());
+    }
+
+    return FunctionType::get(fnTy->getParams(), resultTy, fnTy->getExtInfo());
+  }
+
   // Build a disjunction for the choices between an Optional type and
   // it's underlying type. We'll make the choice of the Optional
   // preferred, and select that if the expression type-checks
@@ -2351,31 +2381,17 @@
     bindToOptional->setFavored();
 
     Type underlyingType;
-    if (auto *fnTy = type->getAs<AnyFunctionType>()) {
-      auto resultTy = fnTy->getResult();
-      while (resultTy->is<AnyFunctionType>())
-        resultTy = resultTy->castTo<AnyFunctionType>()->getResult();
-
-      assert(resultTy->getAnyOptionalObjectType());
-
-      if (auto genericFn = type->getAs<GenericFunctionType>()) {
-        underlyingType = GenericFunctionType::get(
-            genericFn->getGenericSignature(), genericFn->getParams(),
-            resultTy->getAnyOptionalObjectType(), genericFn->getExtInfo());
-      } else {
-        underlyingType = FunctionType::get(fnTy->getParams(),
-                                           resultTy->getAnyOptionalObjectType(),
-                                           fnTy->getExtInfo());
-      }
-    } else {
+    if (auto *fnTy = type->getAs<AnyFunctionType>())
+      underlyingType = replaceFinalResultTypeWithUnderlying(fnTy);
+    else
       underlyingType =
           type->getWithoutSpecifierType()->getAnyOptionalObjectType();
-      assert(underlyingType);
 
-      if (type->is<LValueType>())
-        underlyingType = LValueType::get(underlyingType);
-      assert(!type->is<InOutType>());
-    }
+    assert(underlyingType);
+
+    if (type->is<LValueType>())
+      underlyingType = LValueType::get(underlyingType);
+    assert(!type->is<InOutType>());
 
     auto *bindToUnderlying = Constraint::create(
         *this, ConstraintKind::Bind, tv, underlyingType, disjunctionLocator);
diff --git a/lib/Sema/OverloadChoice.h b/lib/Sema/OverloadChoice.h
index 32d3fff..524e75f 100644
--- a/lib/Sema/OverloadChoice.h
+++ b/lib/Sema/OverloadChoice.h
@@ -53,10 +53,6 @@
   /// \brief The overload choice selects a particular declaration that
   /// was found by unwrapping an optional context type.
   DeclViaUnwrappedOptional,
-  /// \brief The overload choice selects a declaration that is
-  /// implicitly unwrapped only when needed in order to successfully
-  /// type check an expression.
-  DeclForImplicitlyUnwrappedOptional,
   /// \brief The overload choice indexes into a tuple. Index zero will
   /// have the value of this enumerator, index one will have the value of this
   /// enumerator + 1, and so on. Thus, this enumerator must always be last.
@@ -79,9 +75,6 @@
     /// Indicates that this declaration was dynamic, turning a
     /// "Decl" kind into "DeclViaDynamic" kind.
     IsDeclViaDynamic = 0x03,
-    /// Indicates that this declaration is of an Optional that is
-    /// implicitly unwrapped.
-    IsDeclForImplicitlyUnwrappedOptional = 0x04,
   };
 
   /// \brief The base type to be used when referencing the declaration
@@ -127,7 +120,6 @@
            kind != OverloadChoiceKind::DeclViaDynamic &&
            kind != OverloadChoiceKind::DeclViaBridge &&
            kind != OverloadChoiceKind::DeclViaUnwrappedOptional &&
-           kind != OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional &&
            "wrong constructor for decl");
   }
 
@@ -182,20 +174,6 @@
     return result;
   }
 
-  /// Retrieve an overload choice for a declaration that can be
-  /// implicitly unwrapped if needed in order to type check an
-  /// expression.
-  static OverloadChoice
-  getDeclForImplicitlyUnwrappedOptional(Type base, ValueDecl *value,
-                                        FunctionRefKind functionRefKind) {
-    OverloadChoice result;
-    result.BaseAndDeclKind.setPointer(base);
-    result.BaseAndDeclKind.setInt(IsDeclForImplicitlyUnwrappedOptional);
-    result.DeclOrKind = value;
-    result.TheFunctionRefKind = functionRefKind;
-    return result;
-  }
-
   /// \brief Retrieve the base type used to refer to the declaration.
   Type getBaseType() const {
     return BaseAndDeclKind.getPointer();
@@ -209,8 +187,6 @@
       case IsDeclViaDynamic: return OverloadChoiceKind::DeclViaDynamic;
       case IsDeclViaUnwrappedOptional:
         return OverloadChoiceKind::DeclViaUnwrappedOptional;
-      case IsDeclForImplicitlyUnwrappedOptional:
-        return OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional;
       default: return OverloadChoiceKind::Decl;
       }
     }
@@ -231,7 +207,13 @@
   ValueDecl *getDecl() const {
     return DeclOrKind.get<ValueDecl*>();
   }
-  
+
+  /// Returns true if this is either a decl for an optional that was
+  /// declared as one that can be implicitly unwrapped, or is a
+  /// function-typed decl that has a return value that is implicitly
+  /// unwrapped.
+  bool isImplicitlyUnwrappedValueOrReturnValue() const;
+
   /// Get the name of the overload choice.
   DeclName getName() const;
 
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index 4910df3..2148e8b 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -3019,7 +3019,6 @@
     case OverloadChoiceKind::DeclViaDynamic:
     case OverloadChoiceKind::DeclViaBridge:
     case OverloadChoiceKind::DeclViaUnwrappedOptional:
-    case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
       choice.getDecl()->dumpRef(out);
       out << " as ";
       if (choice.getBaseType())
@@ -3196,7 +3195,6 @@
       case OverloadChoiceKind::DeclViaDynamic:
       case OverloadChoiceKind::DeclViaBridge:
       case OverloadChoiceKind::DeclViaUnwrappedOptional:
-      case OverloadChoiceKind::DeclForImplicitlyUnwrappedOptional:
         if (choice.getBaseType())
           out << choice.getBaseType()->getString() << ".";
         out << choice.getDecl()->getBaseName() << ": "
diff --git a/lib/Syntax/Status.md b/lib/Syntax/Status.md
index 52bc7b3..1ff9806 100644
--- a/lib/Syntax/Status.md
+++ b/lib/Syntax/Status.md
@@ -31,13 +31,13 @@
   * SuperRefExpr
   * ImplicitMemberExpr
   * InterpolatedStringLiteralExpr
+  * KeyPathExpr
+  * KeyPathDotExpr
+  * InOutExpr
 
 ### In-progress (UnknownExpr):
   * ObjectLiteralExpr
   * MagicIdentifierLiteralExpr
-  * InOutExpr
-  * KeyPathExpr
-  * KeyPathDotExpr
   * EditorPlaceholderExpr
 
 ### Not-started (UnknownExpr):
diff --git a/lib/Syntax/SyntaxParsingContext.cpp b/lib/Syntax/SyntaxParsingContext.cpp
index 10bf371..537a4e3 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -285,7 +285,7 @@
 
   // Never.
   case AccumulationMode::NotSet:
-    assert(!Enabled && "Cleanup mode must be spefcified before destruction");
+    assert(!Enabled && "Cleanup mode must be specified before destruction");
     break;
   }
 }
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index 22607e4..644fe2f 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -80,8 +80,8 @@
 _TFC3foo3bar3basfT3zimCS_3zim_T_ ---> foo.bar.bas(zim: foo.zim) -> ()
 _TToFC3foo3bar3basfT3zimCS_3zim_T_ ---> {T:_TFC3foo3bar3basfT3zimCS_3zim_T_,C} @objc foo.bar.bas(zim: foo.zim) -> ()
 _TTOFSC3fooFTSdSd_Sd ---> {T:_TFSC3fooFTSdSd_Sd} @nonobjc __C.foo(Swift.Double, Swift.Double) -> Swift.Double
-_T03foo3barC3bas3zimyAaEC_tFTo ---> {T:_T03foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
-_T0SC3fooyS2d_SdtFTO ---> {T:_T0SC3fooyS2d_SdtF} @nonobjc __C.foo(Swift.Double, Swift.Double) -> Swift.Double
+_T03foo3barC3basyAA3zimCAE_tFTo ---> {T:_T03foo3barC3basyAA3zimCAE_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
+_T0SC3fooS2d_SdtFTO ---> {T:_T0SC3fooS2d_SdtF} @nonobjc __C.foo(Swift.Double, Swift.Double) -> Swift.Double
 __$S3foo3barC3bas3zimyAaEC_tFTo ---> {T:_$S3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
 __$SSC3fooyS2d_SdtFTO ---> {T:_$SSC3fooyS2d_SdtF} @nonobjc __C.foo(Swift.Double, Swift.Double) -> Swift.Double
 _$S3foo3barC3bas3zimyAaEC_tFTo ---> {T:_$S3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()
@@ -246,36 +246,60 @@
 _TFVFE15nested_genericsSS3fooFT_T_L_6CheeseCfT8materialx_GS0_x_ ---> init(material: A) -> Cheese #1 in (extension in nested_generics):Swift.String.foo() -> ()<A> in Cheese #1 in (extension in nested_generics):Swift.String.foo() -> ()
 _TTWOE5imojiCSo5Imoji14ImojiMatchRankS_9RankValueS_FS2_g9rankValueqq_Ss16RawRepresentable8RawValue ---> _TTWOE5imojiCSo5Imoji14ImojiMatchRankS_9RankValueS_FS2_g9rankValueqq_Ss16RawRepresentable8RawValue
 _TtFzas4VoidGC16FusionXBaseUtils6FutureQq_ZFVS_7Futures6futureurFFzT_GS0_x_GS0_x__ ---> _TtFzas4VoidGC16FusionXBaseUtils6FutureQq_ZFVS_7Futures6futureurFFzT_GS0_x_GS0_x__
-_T0s17MutableCollectionP1asAARzs012RandomAccessB0RzsAA11SubSequences013BidirectionalB0PRpzsAdHRQlE06rotatecD015shiftingToStart5Indexs01_A9IndexablePQzAN_tFAKs01_M4BasePQzAQcfU_ ---> closure #1 (A.Index) -> A.Index in (extension in a):Swift.MutableCollection<A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection, A.SubSequence: Swift.MutableCollection, A.SubSequence: Swift.RandomAccessCollection>.rotateRandomAccess(shiftingToStart: A.Index) -> A.Index
+_T0s17MutableCollectionP1asAARzs012RandomAccessB0RzsAA11SubSequences013BidirectionalB0PRpzsAdHRQlE06rotatecD05Indexs01_A9IndexablePQzAM15shiftingToStart_tFAJs01_J4BasePQzAQcfU_ ---> closure #1 (A.Index) -> A.Index in (extension in a):Swift.MutableCollection<A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection, A.SubSequence: Swift.MutableCollection, A.SubSequence: Swift.RandomAccessCollection>.rotateRandomAccess(shiftingToStart: A.Index) -> A.Index
+_$Ss17MutableCollectionP1asAARzs012RandomAccessB0RzsAA11SubSequences013BidirectionalB0PRpzsAdHRQlE06rotatecD015shiftingToStart5Indexs01_A9IndexablePQzAN_tFAKs01_M4BasePQzAQcfU_ ---> closure #1 (A.Index) -> A.Index in (extension in a):Swift.MutableCollection<A where A: Swift.MutableCollection, A: Swift.RandomAccessCollection, A.SubSequence: Swift.MutableCollection, A.SubSequence: Swift.RandomAccessCollection>.rotateRandomAccess(shiftingToStart: A.Index) -> A.Index
 _T03foo4_123ABTf3psbpsb_n ---> function signature specialization <Arg[0] = [Constant Propagated String : u8'123'], Arg[1] = [Constant Propagated String : u8'123']> of foo
-_T04main5inneryys5Int32Vz_yADctF25closure_with_box_argumentxz_Bi32__lXXTf1nc_n ---> function signature specialization <Arg[1] = [Closure Propagated : closure_with_box_argument, Argument Types : [<A> { var A } <Builtin.Int32>]> of main.inner(inout Swift.Int32, (Swift.Int32) -> ()) -> ()
-_T03foo6testityyyyc_yyctF1a1bTf3pfpf_n ---> function signature specialization <Arg[0] = [Constant Propagated Function : a], Arg[1] = [Constant Propagated Function : b]> of foo.testit(() -> (), () -> ()) -> ()
+_T04main5innerys5Int32Vz_yADctF25closure_with_box_argumentxz_Bi32__lXXTf1nc_n ---> function signature specialization <Arg[1] = [Closure Propagated : closure_with_box_argument, Argument Types : [<A> { var A } <Builtin.Int32>]> of main.inner(inout Swift.Int32, (Swift.Int32) -> ()) -> ()
+_$S4main5inneryys5Int32Vz_yADctF25closure_with_box_argumentxz_Bi32__lXXTf1nc_n ---> function signature specialization <Arg[1] = [Closure Propagated : closure_with_box_argument, Argument Types : [<A> { var A } <Builtin.Int32>]> of main.inner(inout Swift.Int32, (Swift.Int32) -> ()) -> ()
+_T03foo6testityyyc_yyctF1a1bTf3pfpf_n ---> function signature specialization <Arg[0] = [Constant Propagated Function : a], Arg[1] = [Constant Propagated Function : b]> of foo.testit(() -> (), () -> ()) -> ()
+_$S3foo6testityyyyc_yyctF1a1bTf3pfpf_n ---> function signature specialization <Arg[0] = [Constant Propagated Function : a], Arg[1] = [Constant Propagated Function : b]> of foo.testit(() -> (), () -> ()) -> ()
 _SocketJoinOrLeaveMulticast ---> _SocketJoinOrLeaveMulticast
-_T0s10DictionaryV3t17E6Index2V1loiySbAEyxq__G_AGtFZ ---> static (extension in t17):Swift.Dictionary.Index2.< infix((extension in t17):[A : B].Index2, (extension in t17):[A : B].Index2) -> Swift.Bool
-_T08mangling14varargsVsArray3arr1nySid_SStF ---> mangling.varargsVsArray(arr: Swift.Int..., n: Swift.String) -> ()
-_T08mangling14varargsVsArray3arr1nySaySiG_SStF ---> mangling.varargsVsArray(arr: [Swift.Int], n: Swift.String) -> ()
-_T08mangling14varargsVsArray3arr1nySaySiGd_SStF ---> mangling.varargsVsArray(arr: [Swift.Int]..., n: Swift.String) -> ()
-_T08mangling14varargsVsArray3arrySid_tF ---> mangling.varargsVsArray(arr: Swift.Int...) -> ()
-_T08mangling14varargsVsArray3arrySaySiGd_tF ---> mangling.varargsVsArray(arr: [Swift.Int]...) -> ()
+_T0s10DictionaryV3t17E6Index2V1loiSbAEyxq__G_AGtFZ ---> static (extension in t17):Swift.Dictionary.Index2.< infix((extension in t17):[A : B].Index2, (extension in t17):[A : B].Index2) -> Swift.Bool
+_T08mangling14varargsVsArrayySi3arrd_SS1ntF ---> mangling.varargsVsArray(arr: Swift.Int..., n: Swift.String) -> ()
+_T08mangling14varargsVsArrayySaySiG3arr_SS1ntF ---> mangling.varargsVsArray(arr: [Swift.Int], n: Swift.String) -> ()
+_T08mangling14varargsVsArrayySaySiG3arrd_SS1ntF ---> mangling.varargsVsArray(arr: [Swift.Int]..., n: Swift.String) -> ()
+_T08mangling14varargsVsArrayySi3arrd_tF ---> mangling.varargsVsArray(arr: Swift.Int...) -> ()
+_T08mangling14varargsVsArrayySaySiG3arrd_tF ---> mangling.varargsVsArray(arr: [Swift.Int]...) -> ()
+_$Ss10DictionaryV3t17E6Index2V1loiySbAEyxq__G_AGtFZ ---> static (extension in t17):Swift.Dictionary.Index2.< infix((extension in t17):[A : B].Index2, (extension in t17):[A : B].Index2) -> Swift.Bool
+_$S8mangling14varargsVsArray3arr1nySid_SStF ---> mangling.varargsVsArray(arr: Swift.Int..., n: Swift.String) -> ()
+_$S8mangling14varargsVsArray3arr1nySaySiG_SStF ---> mangling.varargsVsArray(arr: [Swift.Int], n: Swift.String) -> ()
+_$S8mangling14varargsVsArray3arr1nySaySiGd_SStF ---> mangling.varargsVsArray(arr: [Swift.Int]..., n: Swift.String) -> ()
+_$S8mangling14varargsVsArray3arrySid_tF ---> mangling.varargsVsArray(arr: Swift.Int...) -> ()
+_$S8mangling14varargsVsArray3arrySaySiGd_tF ---> mangling.varargsVsArray(arr: [Swift.Int]...) -> ()
 _T0s13_UnicodeViewsVss22RandomAccessCollectionRzs0A8EncodingR_11SubSequence_5IndexQZAFRtzsAcERpzAE_AEQZAIRSs15UnsignedInteger8Iterator_7ElementRPzAE_AlMQZANRS13EncodedScalar_AlMQY_AORSr0_lE13CharacterViewVyxq__G ---> (extension in Swift):Swift._UnicodeViews<A, B><A, B where A: Swift.RandomAccessCollection, B: Swift.UnicodeEncoding, A.Index == A.SubSequence.Index, A.SubSequence: Swift.RandomAccessCollection, A.SubSequence == A.SubSequence.SubSequence, A.Iterator.Element: Swift.UnsignedInteger, A.Iterator.Element == A.SubSequence.Iterator.Element, A.SubSequence.Iterator.Element == B.EncodedScalar.Iterator.Element>.CharacterView
-_T010Foundation11MeasurementV12SimulatorKitSo9UnitAngleCRszlE11OrientationO2eeoiySbAcDEAGOyAF_G_AKtFZ ---> static (extension in SimulatorKit):Foundation.Measurement<A where A == __ObjC.UnitAngle>.Orientation.== infix((extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation, (extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation) -> Swift.Bool
+_T010Foundation11MeasurementV12SimulatorKitSo9UnitAngleCRszlE11OrientationO2eeoiSbAcDEAGOyAF_G_AKtFZ ---> static (extension in SimulatorKit):Foundation.Measurement<A where A == __ObjC.UnitAngle>.Orientation.== infix((extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation, (extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation) -> Swift.Bool
+_$S10Foundation11MeasurementV12SimulatorKitSo9UnitAngleCRszlE11OrientationO2eeoiySbAcDEAGOyAF_G_AKtFZ ---> static (extension in SimulatorKit):Foundation.Measurement<A where A == __ObjC.UnitAngle>.Orientation.== infix((extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation, (extension in SimulatorKit):Foundation.Measurement<__ObjC.UnitAngle>.Orientation) -> Swift.Bool
 _T04main1_yyF ---> main._() -> ()
-_T04test6testitySiyt_tF ---> test.testit(()) -> Swift.Int
+_T04test6testitSiyt_tF ---> test.testit(()) -> Swift.Int
+_$S4test6testitySiyt_tF ---> test.testit(()) -> Swift.Int
 _T08_ElementQzSbs5Error_pIxxdzo_ABSbsAC_pIxidzo_s26RangeReplaceableCollectionRzABRLClTR ---> {T:} reabstraction thunk helper <A where A: Swift.RangeReplaceableCollection, A._Element: AnyObject> from @callee_owned (@owned A._Element) -> (@unowned Swift.Bool, @error @owned Swift.Error) to @callee_owned (@in A._Element) -> (@unowned Swift.Bool, @error @owned Swift.Error)
 _T0Ix_IyB_Tr ---> {T:} reabstraction thunk from @callee_owned () -> () to @callee_unowned @convention(block) () -> ()
 _T0Rml ---> _T0Rml
 _T0Tk ---> _T0Tk
 _T0A8 ---> _T0A8
 _T0s30ReversedRandomAccessCollectionVyxGTfq3nnpf_nTfq1cn_nTfq4x_n ---> _T0s30ReversedRandomAccessCollectionVyxGTfq3nnpf_nTfq1cn_nTfq4x_n
-_T03abc6testityySiFTm ---> merged abc.testit(Swift.Int) -> ()
-_T04main4TestC1xACSi_tc6_PRIV_Llfc ---> main.Test.(in _PRIV_).init(x: Swift.Int) -> main.Test
+_T03abc6testitySiFTm ---> merged abc.testit(Swift.Int) -> ()
+_T04main4TestCACSi1x_tc6_PRIV_Llfc ---> main.Test.(in _PRIV_).init(x: Swift.Int) -> main.Test
+_$S3abc6testityySiFTm ---> merged abc.testit(Swift.Int) -> ()
+_$S4main4TestC1xACSi_tc6_PRIV_Llfc ---> main.Test.(in _PRIV_).init(x: Swift.Int) -> main.Test
 _T0SqWy.17 ---> outlined copy of Swift.Optional with unmangled suffix ".17"
 _T03nix6testitSaySiGyFTv_ ---> outlined variable #0 of nix.testit() -> [Swift.Int]
 _T03nix6testitSaySiGyFTv0_ ---> outlined variable #1 of nix.testit() -> [Swift.Int]
 _T0So11UITextFieldC4textSSSgvgToTepb_ ---> outlined bridged method (pb) of @objc __ObjC.UITextField.text.getter : Swift.String?
 _T0So11UITextFieldC4textSSSgvgToTeab_ ---> outlined bridged method (ab) of @objc __ObjC.UITextField.text.getter : Swift.String?
-_T0So5GizmoC11doSomethingySQyypGSQySaySSGGFToTembnn_ ---> outlined bridged method (mbnn) of @objc __ObjC.Gizmo.doSomething([Swift.String]!) -> Any!
-_T0So5GizmoC12modifyString_10withNumber0D6FoobarSQySSGAF_SiSQyypGtFToTembnnnb_ ---> outlined bridged method (mbnnnb) of @objc __ObjC.Gizmo.modifyString(_: Swift.String!, withNumber: Swift.Int, withFoobar: Any!) -> Swift.String!
+_T0So5GizmoC11doSomethingSQyypGSQySaySSGGFToTembnn_ ---> outlined bridged method (mbnn) of @objc __ObjC.Gizmo.doSomething([Swift.String]!) -> Any!
+_T0So5GizmoC12modifyStringSQySSGAD_Si10withNumberSQyypG0D6FoobartFToTembnnnb_ ---> outlined bridged method (mbnnnb) of @objc __ObjC.Gizmo.modifyString(_: Swift.String!, withNumber: Swift.Int, withFoobar: Any!) -> Swift.String!
+_$SSo5GizmoC11doSomethingySQyypGSQySaySSGGFToTembnn_ ---> outlined bridged method (mbnn) of @objc __ObjC.Gizmo.doSomething([Swift.String]!) -> Any!
+_$SSo5GizmoC12modifyString_10withNumber0D6FoobarSQySSGAF_SiSQyypGtFToTembnnnb_ ---> outlined bridged method (mbnnnb) of @objc __ObjC.Gizmo.modifyString(_: Swift.String!, withNumber: Swift.Int, withFoobar: Any!) -> Swift.String!
 _T04test1SVyxGAA1RA2A1ZRzAA1Y2ZZRpzl1A_AhaGPWT ---> {C} associated type witness table accessor for A.ZZ : test.Y in <A where A: test.Z, A.ZZ: test.Y> test.S<A> : test.R in test
 _T0s24_UnicodeScalarExceptions33_0E4228093681F6920F0AB2E48B4F1C69LLVACycfC ---> Swift.(_UnicodeScalarExceptions in _0E4228093681F6920F0AB2E48B4F1C69).init() -> Swift.(_UnicodeScalarExceptions in _0E4228093681F6920F0AB2E48B4F1C69)
-
+_T0D ---> _T0D
+_T0s18EnumeratedIteratorVyxGs8Sequencess0B8ProtocolRzlsADP5splitSay03SubC0QzGSi9maxSplits_Sb25omittingEmptySubsequencesSb7ElementQzKc14whereSeparatortKFTW ---> {T:} protocol witness for Swift.Sequence.split(maxSplits: Swift.Int, omittingEmptySubsequences: Swift.Bool, whereSeparator: (A.Element) throws -> Swift.Bool) throws -> [A.SubSequence] in conformance <A where A: Swift.IteratorProtocol> Swift.EnumeratedIterator<A> : Swift.Sequence in Swift
+_T0s3SetVyxGs10CollectiotySivm ---> _T0s3SetVyxGs10CollectiotySivm
+_S$s3SetVyxGs10CollectiotySivm ---> _S$s3SetVyxGs10CollectiotySivm
+_T0s18ReversedCollectionVyxGs04LazyB8ProtocolfC ---> _T0s18ReversedCollectionVyxGs04LazyB8ProtocolfC
+_S$s18ReversedCollectionVyxGs04LazyB8ProtocolfC ---> _S$s18ReversedCollectionVyxGs04LazyB8ProtocolfC
+_T0iW ---> _T0iW
+_S$iW ---> _S$iW
+_T0s5print_9separator10terminatoryypfC ---> _T0s5print_9separator10terminatoryypfC
+_S$s5print_9separator10terminatoryypfC ---> _S$s5print_9separator10terminatoryypfC
diff --git a/test/Demangle/Inputs/simplified-manglings.txt b/test/Demangle/Inputs/simplified-manglings.txt
index 38d11e3..f92e4d8 100644
--- a/test/Demangle/Inputs/simplified-manglings.txt
+++ b/test/Demangle/Inputs/simplified-manglings.txt
@@ -203,5 +203,7 @@
 _TTRXFo_oCSo13SKPhysicsBodydVSC7CGPointdVSC8CGVectordGSpV10ObjectiveC8ObjCBool___XFdCb_dS_dS0_dS1_dGSpS3____ ---> thunk for @callee_owned (@owned SKPhysicsBody, @unowned CGPoint, @unowned CGVector, @unowned UnsafeMutablePointer<ObjCBool>) -> ()
 _T0So13SKPhysicsBodyCSC7CGPointVSC8CGVectorVSpy10ObjectiveC8ObjCBoolVGIxxyyy_AbdFSpyAIGIyByyyy_TR ---> thunk for @callee_owned (@owned SKPhysicsBody, @unowned CGPoint, @unowned CGVector, @unowned UnsafeMutablePointer<ObjCBool>) -> ()
 _T04main1_yyF ---> _()
-_T03abc6testityySiFTm ---> testit(_:)
-_T04main4TestC1xACSi_tc6_PRIV_Llfc ---> Test.init(x:)
+_T03abc6testitySiFTm ---> testit(_:)
+_T04main4TestCACSi1x_tc6_PRIV_Llfc ---> Test.init(x:)
+_$S3abc6testityySiFTm ---> testit(_:)
+_$S4main4TestC1xACSi_tc6_PRIV_Llfc ---> Test.init(x:)
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index eefd51c..ecb48cb 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -222,7 +222,8 @@
 
   foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></IdentifierExpr>()</FunctionCallExpr><SequenceExpr><DiscardAssignmentExpr>
   _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ImplicitMemberExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></ImplicitMemberExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
-  _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><IdentifierExpr>x</IdentifierExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></MemberAccessExpr></SequenceExpr>
+  _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><IdentifierExpr>x</IdentifierExpr>.foo<DeclNameArguments>(<DeclNameArgument>x:</DeclNameArgument><DeclNameArgument>y:</DeclNameArgument>)</DeclNameArguments></MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+  _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><FunctionCallExpr><IdentifierExpr>foo</IdentifierExpr>(<FunctionCallArgument><InOutExpr>&<IdentifierExpr>d</IdentifierExpr></InOutExpr></FunctionCallArgument>)</FunctionCallExpr></SequenceExpr>
 }</CodeBlock></FunctionDecl><IfConfigDecl>
 
 #if <IdentifierExpr>blah</IdentifierExpr><ElseDirectiveClause>
@@ -341,4 +342,12 @@
   de </StringSegment><ExpressionSegment>\(<SequenceExpr><IntegerLiteralExpr>3 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><IntegerLiteralExpr>3 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><StringInterpolationExpr>"<StringSegment>abc </StringSegment><ExpressionSegment>\(<FunctionCallExpr><IdentifierExpr>foo</IdentifierExpr>()</FunctionCallExpr>)</ExpressionSegment><StringSegment> def</StringSegment>"</StringInterpolationExpr></SequenceExpr>)</ExpressionSegment><StringSegment>
   fg
   </StringSegment>"""</StringInterpolationExpr></InitializerClause></PatternBinding></VariableDecl>
+}</CodeBlock></FunctionDecl><FunctionDecl>
+
+func keypath<FunctionSignature><ParameterClause>() </ParameterClause></FunctionSignature><CodeBlock>{<SequenceExpr><DiscardAssignmentExpr>
+  _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<IdentifierExpr>a</IdentifierExpr>.?.b</KeyPathExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+  _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<MemberAccessExpr><MemberAccessExpr><IdentifierExpr>a</IdentifierExpr>.b</MemberAccessExpr>.c</MemberAccessExpr></KeyPathExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+  _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<SubscriptExpr><MemberAccessExpr><IdentifierExpr>a</IdentifierExpr>.b</MemberAccessExpr>[<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>]</SubscriptExpr></KeyPathExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+  _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><KeyPathExpr>\<MemberAccessExpr>.a.b</MemberAccessExpr></KeyPathExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+  _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ObjcKeyPathExpr>#keyPath(<ObjcNamePiece>a.</ObjcNamePiece><ObjcNamePiece>b.</ObjcNamePiece><ObjcNamePiece>c</ObjcNamePiece>)</ObjcKeyPathExpr></SequenceExpr>
 }</CodeBlock></FunctionDecl>
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index 15e908d..c36a25f 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -223,6 +223,7 @@
   foo(x:y:)()
   _ = .foo(x:y:)
   _ = x.foo(x:y:)
+  _ = foo(&d)
 }
 
 #if blah
@@ -342,3 +343,11 @@
   fg
   """
 }
+
+func keypath() {
+  _ = \a.?.b
+  _ = \a.b.c
+  _ = \a.b[1]
+  _ = \.a.b
+  _ = #keyPath(a.b.c)
+}
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index d5d4c5e..b8df2b5 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -7,7 +7,7 @@
     Node('InOutExpr', kind='Expr',
          children=[
              Child('Ampersand', kind='PrefixAmpersandToken'),
-             Child('Identifier', kind='IdentifierToken'),
+             Child('Expression', kind='Expr'),
          ]),
 
     # A #column expression.
@@ -440,4 +440,30 @@
                        'MultilineStringQuoteToken',
                    ]),
          ]),
+
+    # e.g. "\a.b[2].a"
+    Node('KeyPathExpr', kind='Expr',
+         children=[
+             Child('Backslash', kind='BackslashToken'),
+             Child('Expression', kind='Expr'),
+         ]),
+
+    # e.g. "a." or "a"
+    Node('ObjcNamePiece', kind='Syntax',
+         children=[
+             Child('Name', kind='IdentifierToken'),
+             Child('Dot', kind='PeriodToken', is_optional=True),
+         ]),
+
+    # e.g. "a.b.c"
+    Node('ObjcName', kind='SyntaxCollection', element='ObjcNamePiece'),
+
+    # e.g. "#keyPath(a.b.c)"
+    Node('ObjcKeyPathExpr', kind='Expr',
+         children=[
+             Child('KeyPath', kind='PoundKeyPathToken'),
+             Child('LeftParen', kind='LeftParenToken'),
+             Child('Name', kind='ObjcName'),
+             Child('RightParen', kind='RightParenToken'),
+         ]),
 ]