Merge pull request #876 from practicalswift/swiftc-28191-swift-typebase-getcanonicaltype

[swiftc] Add test case for crash triggered in swift::TypeBase::getCanonicalType()
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 3622065..8f94f8e 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -2382,7 +2382,7 @@
   /// The type that represents this (sugared) name alias.
   mutable NameAliasType *AliasTy;
 
-  SourceLoc TypeAliasLoc; // The location of the 'typalias' keyword
+  SourceLoc TypeAliasLoc; // The location of the 'typealias' keyword
   TypeLoc UnderlyingTy;
 
 public:
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index d78b660..1bcbb1c 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1815,6 +1815,8 @@
       "contextual type %0 cannot be used with array literal", (Type))
 NOTE(meant_dictionary_lit, sema_tce,none,
      "did you mean to use a dictionary literal instead?", ())
+ERROR(should_use_empty_dictionary_literal,sema_tce,none,
+      "use [:] to get an empty dictionary literal", ())
 
 // Dictionary literals
 ERROR(dictionary_protocol_broken,sema_tce,none,
diff --git a/include/swift/AST/DiagnosticsSema.h b/include/swift/AST/DiagnosticsSema.h
index f452d6d..4947560 100644
--- a/include/swift/AST/DiagnosticsSema.h
+++ b/include/swift/AST/DiagnosticsSema.h
@@ -23,7 +23,7 @@
 namespace swift {
   namespace diag {
 
-    /// Describes the kind of requirement in a protocl.
+    /// Describes the kind of requirement in a protocol.
     enum class RequirementKind : uint8_t {
       Constructor,
       Func,
diff --git a/include/swift/AST/KnownProtocols.def b/include/swift/AST/KnownProtocols.def
index a41610e..615f9d6 100644
--- a/include/swift/AST/KnownProtocols.def
+++ b/include/swift/AST/KnownProtocols.def
@@ -1,4 +1,4 @@
-//===-- KnownProtocols.def - Compiler protocol metaprogramming --*- C++ -*-===//
+//===--- KnownProtocols.def - Compiler protocol metaprogramming -*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 6b6aa02..60dc438 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -252,7 +252,7 @@
     return mem;
   }
   
-  /// Print a parsable and human-readable description of the identifying
+  /// Print a parseable and human-readable description of the identifying
   /// information of the protocol conformance.
   void printName(raw_ostream &os,
                  const PrintOptions &PO = PrintOptions()) const;
diff --git a/include/swift/Basic/StringExtras.h b/include/swift/Basic/StringExtras.h
index 4686012..7f3e81d 100644
--- a/include/swift/Basic/StringExtras.h
+++ b/include/swift/Basic/StringExtras.h
@@ -49,7 +49,6 @@
     Unknown,
     Preposition,
     Verb,
-    AuxiliaryVerb,
     Gerund,
   };
 
diff --git a/include/swift/IDE/REPLCodeCompletion.h b/include/swift/IDE/REPLCodeCompletion.h
index 25768a0..834a3d7 100644
--- a/include/swift/IDE/REPLCodeCompletion.h
+++ b/include/swift/IDE/REPLCodeCompletion.h
@@ -1,4 +1,4 @@
-//===--- REPLCodeCompletion.h - Code completion for REPL ----------* C++ *-===//
+//===--- REPLCodeCompletion.h - Code completion for REPL --------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/include/swift/Parse/CodeCompletionCallbacks.h b/include/swift/Parse/CodeCompletionCallbacks.h
index 1e7f395..3b36640 100644
--- a/include/swift/Parse/CodeCompletionCallbacks.h
+++ b/include/swift/Parse/CodeCompletionCallbacks.h
@@ -1,4 +1,4 @@
-//===- CodeCompletionCallbacks.h - Parser's interface to code completion --===//
+//===--- CodeCompletionCallbacks.h - Parser's interface to code completion ===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/include/swift/Parse/DelayedParsingCallbacks.h b/include/swift/Parse/DelayedParsingCallbacks.h
index 671a5ad..a1ea003 100644
--- a/include/swift/Parse/DelayedParsingCallbacks.h
+++ b/include/swift/Parse/DelayedParsingCallbacks.h
@@ -1,4 +1,4 @@
-//===- DelayedParsingCallbacks.h - Callbacks for Parser's delayed parsing -===//
+//===--- DelayedParsingCallbacks.h - Delayed parsing callbacks ------------===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/include/swift/Runtime/ObjCBridge.h b/include/swift/Runtime/ObjCBridge.h
index 0fcf39c..44f2ad4 100644
--- a/include/swift/Runtime/ObjCBridge.h
+++ b/include/swift/Runtime/ObjCBridge.h
@@ -54,7 +54,7 @@
 } objc_image_info;
 
 // Class and metaclass construction from a compiler-generated memory image.
-// cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.·
+// cls and cls->isa must each be OBJC_MAX_CLASS_SIZE bytes.
 // Extra bytes not used the metadata must be zero.
 // info is the same objc_image_info that would be emitted by a static compiler.
 // Returns nil if a class with the same name already exists.
diff --git a/include/swift/SIL/Dominance.h b/include/swift/SIL/Dominance.h
index 6f588aa..62da9a5 100644
--- a/include/swift/SIL/Dominance.h
+++ b/include/swift/SIL/Dominance.h
@@ -138,6 +138,16 @@
     if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
       return true;
 
+    if (!R->getBlock()) {
+      // The post dom-tree has multiple roots. The compare() function can not
+      // cope with multiple roots if at least one of the roots is caused by
+      // an infinite loop in the CFG (it crashes because no nodes are allocated
+      // for the blocks in the infinite loop).
+      // So we return a conservative false in this case.
+      // TODO: eventually fix the DominatorTreeBase::compare() function.
+      return false;
+    }
+
     // Returns *false* if they match.
     if (compare(Other))
       return true;
diff --git a/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h b/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h
index 037c8e9..602ad92 100644
--- a/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h
@@ -1,4 +1,4 @@
-//===-- ClassHierarchyAnalysis.h - Analysis of Class Hierarchy --*- C++ -*-===//
+//===--- ClassHierarchyAnalysis.h - Analysis of Class Hierarchy -*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/include/swift/SILOptimizer/Utils/ConstantFolding.h b/include/swift/SILOptimizer/Utils/ConstantFolding.h
index b653e74..4e90407 100644
--- a/include/swift/SILOptimizer/Utils/ConstantFolding.h
+++ b/include/swift/SILOptimizer/Utils/ConstantFolding.h
@@ -1,4 +1,4 @@
-//===-- ConstantFolding.h - Utilities for SIL constant folding --*- C++ -*-===//
+//===--- ConstantFolding.h - Utilities for SIL constant folding -*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/include/swift/Sema/TypeCheckRequestKinds.def b/include/swift/Sema/TypeCheckRequestKinds.def
index aeef48b..e64b81b 100644
--- a/include/swift/Sema/TypeCheckRequestKinds.def
+++ b/include/swift/Sema/TypeCheckRequestKinds.def
@@ -1,4 +1,4 @@
-//===-- TypeCheckRequestKinds.def - Type Checking Request Kinds -*- C++ -*-===//
+//===--- TypeCheckRequestKinds.def - Type Check Request Kinds ---*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 6a181f7..0241c78 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -1003,7 +1003,6 @@
     DeclIDField,           // ParamDecl
     BCFixed<1>,            // isVariadic?
     DefaultArgumentField   // default argument
-    // The element pattern trails the record.
     >;
 
   using ParenPatternLayout = BCRecordLayout<
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index c388060..f35eac6 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -1,4 +1,4 @@
-//===--- ASTDumper.cpp - Swift Language AST Dumper-------------------------===//
+//===--- ASTDumper.cpp - Swift Language AST Dumper ------------------------===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index d2140a2..2817a8a 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -1,4 +1,4 @@
-//===--- ASTPrinter.cpp - Swift Language AST Printer-----------------------===//
+//===--- ASTPrinter.cpp - Swift Language AST Printer ----------------------===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index ea094cd..9267d5e 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3152,7 +3152,7 @@
 }
 
 SourceRange VarDecl::getTypeSourceRangeForDiagnostics() const {
-  // For a parameter, map back to it's parameter to get the TypeLoc.
+  // For a parameter, map back to its parameter to get the TypeLoc.
   if (auto *PD = dyn_cast<ParamDecl>(this)) {
     if (auto typeRepr = PD->getTypeLoc().getTypeRepr())
       return typeRepr->getSourceRange();
@@ -3221,7 +3221,10 @@
 }
 
 bool VarDecl::isSelfParameter() const {
-  return isa<ParamDecl>(this) && getName() == getASTContext().Id_self;
+  // Note: we need to check the isImplicit() bit here to make sure that we
+  // don't classify explicit parameters declared with `self` as the self param.
+  return isa<ParamDecl>(this) && getName() == getASTContext().Id_self &&
+         isImplicit();
 }
 
 /// Return true if this stored property needs to be accessed with getters and
diff --git a/lib/AST/Mangle.cpp b/lib/AST/Mangle.cpp
index c670d1d..aee1542 100644
--- a/lib/AST/Mangle.cpp
+++ b/lib/AST/Mangle.cpp
@@ -300,6 +300,8 @@
   }
 
   case DeclContextKind::SubscriptDecl:
+    // FIXME: We may need to do something here if subscripts contain any symbols
+    // exposed with linkage names.
     return mangleContext(ctx->getParent(), shouldBind);
       
   case DeclContextKind::Initializer:
diff --git a/lib/AST/Verifier.cpp b/lib/AST/Verifier.cpp
index 2cd714c..820a987 100644
--- a/lib/AST/Verifier.cpp
+++ b/lib/AST/Verifier.cpp
@@ -1618,7 +1618,6 @@
       // Make sure that there are no archetypes in the interface type.
       if (VD->getDeclContext()->isTypeContext() &&
           !hasEnclosingFunctionContext(VD->getDeclContext()) &&
-      //    !isa<ParamDecl>(VD) && /* because of subscripts */
           VD->getInterfaceType().findIf([](Type type) {
             return type->is<ArchetypeType>();
           })) {
diff --git a/lib/Basic/PartsOfSpeech.def b/lib/Basic/PartsOfSpeech.def
index 713867c..dec4af5 100644
--- a/lib/Basic/PartsOfSpeech.def
+++ b/lib/Basic/PartsOfSpeech.def
@@ -10,7 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 // This file lists words that map to various parts of speech. 
-// ===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 
 #if !defined(PREPOSITION) && !defined(VERB)
 #  error define one or more of PREPOSITION, VERB
@@ -28,10 +28,6 @@
 #  define VERB(Word)
 #endif
 
-#ifndef AUXILIARY_VERB
-#  define AUXILIARY_VERB(Word)
-#endif
-
 DIRECTIONAL_PREPOSITION(above)
 DIRECTIONAL_PREPOSITION(after)
 DIRECTIONAL_PREPOSITION(along)
@@ -842,33 +838,6 @@
 VERB(zip)
 VERB(zoom)
 
-AUXILIARY_VERB(am)
-AUXILIARY_VERB(are)
-AUXILIARY_VERB(been)
-AUXILIARY_VERB(being)
-AUXILIARY_VERB(can)
-AUXILIARY_VERB(could)
-AUXILIARY_VERB(did)
-AUXILIARY_VERB(does)
-AUXILIARY_VERB(had)
-AUXILIARY_VERB(has)
-AUXILIARY_VERB(have)
-AUXILIARY_VERB(having)
-AUXILIARY_VERB(is)
-AUXILIARY_VERB(may)
-AUXILIARY_VERB(might)
-AUXILIARY_VERB(must)
-AUXILIARY_VERB(need)
-AUXILIARY_VERB(needs)
-AUXILIARY_VERB(ought)
-AUXILIARY_VERB(shall)
-AUXILIARY_VERB(should)
-AUXILIARY_VERB(was)
-AUXILIARY_VERB(were)
-AUXILIARY_VERB(will)
-AUXILIARY_VERB(would)
-
-#undef AUXILIARY_VERB
 #undef VERB
 #undef DIRECTIONAL_PREPOSITION
 #undef PREPOSITION
diff --git a/lib/Basic/StringExtras.cpp b/lib/Basic/StringExtras.cpp
index c4601ac..3ffb9f4 100644
--- a/lib/Basic/StringExtras.cpp
+++ b/lib/Basic/StringExtras.cpp
@@ -54,9 +54,6 @@
 #define VERB(Word)                              \
   if (word.equals_lower(#Word))                 \
     return PartOfSpeech::Verb;
-#define AUXILIARY_VERB(Word)                    \
-  if (word.equals_lower(#Word))                 \
-    return PartOfSpeech::AuxiliaryVerb;
 #include "PartsOfSpeech.def"
 
   // Identify gerunds, which always end in "ing".
@@ -671,7 +668,6 @@
         break;
 
       case PartOfSpeech::Unknown:
-      case PartOfSpeech::AuxiliaryVerb:
         // Assume it's a noun or adjective; don't strip anything.
         break;
       }
@@ -703,23 +699,6 @@
   return name;
 }
 
-/// Determine whether the given word indicates a boolean result.
-static bool nameIndicatesBooleanResult(StringRef name) {
-  for (auto word: camel_case::getWords(name)) {
-    // Auxiliary verbs indicate Boolean results.
-    if (getPartOfSpeech(word) == PartOfSpeech::AuxiliaryVerb)
-      return true;
-
-    // Words that end in "s" indicate either Boolean results---it
-    // could be a verb in the present continuous tense---or some kind
-    // of plural, for which "is" would be inappropriate anyway.
-    if (word.back() == 's')
-      return true;
-  }
-
-  return false;
-}
-
 /// A form of toLowercaseWord that also lowercases acronyms.
 static StringRef toLowercaseWordAndAcronym(StringRef string,
                                            StringScratchSpace &scratch) {
@@ -730,12 +709,19 @@
   if (!clang::isUppercase(string[0]))
     return string;
 
-  // Lowercase until we hit the end there is an uppercase letter
-  // followed by a non-uppercase letter.
+  // Lowercase until we hit the an uppercase letter followed by a
+  // non-uppercase letter.
   llvm::SmallString<32> scratchStr;
   for (unsigned i = 0, n = string.size(); i != n; ++i) {
     // If the next character is not uppercase, stop.
     if (i < n - 1 && !clang::isUppercase(string[i+1])) {
+      // If the next non-uppercase character was alphanumeric, we should
+      // still lowercase the character we're on.
+      if (!clang::isLetter(string[i+1])) {
+        scratchStr.push_back(clang::toLowercase(string[i]));
+        ++i;
+      }
+
       scratchStr.append(string.substr(i));
       break;
     }
@@ -805,16 +791,6 @@
       }
     }
 
-    // Boolean properties should start with "is", unless their
-    // first word already implies a Boolean result.
-    if (resultType.isBoolean() && isProperty &&
-        !nameIndicatesBooleanResult(baseName)) {
-      SmallString<32> newName("is");
-      camel_case::appendSentenceCase(newName, baseName);
-      baseName = scratch.copyString(newName);
-      anyChanges = true;
-    }
-
     return lowercaseAcronymsForReturn();
   }
 
@@ -864,7 +840,6 @@
           break;
 
         case PartOfSpeech::Unknown:
-        case PartOfSpeech::AuxiliaryVerb:
           ++nameWordRevIter;
           break;
         }
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 4f104ae..aa11c2c 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -2209,6 +2209,16 @@
   case clang::DeclarationName::Identifier:
     // Map the identifier.
     baseName = D->getDeclName().getAsIdentifierInfo()->getName();
+
+    if (OmitNeedlessWords) {
+      // For Objective-C BOOL properties, use the name of the getter
+      // which, conventionally, has an "is" prefix.
+      if (auto property = dyn_cast<clang::ObjCPropertyDecl>(D)) {
+        if (isBoolType(clangSema.Context, property->getType()))
+          baseName = property->getGetterName().getNameForSlot(0);
+      }
+    }
+
     break;
 
   case clang::DeclarationName::ObjCMultiArgSelector:
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index bc96293..7891701 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -2454,9 +2454,7 @@
                                           decl->isVariadic(),
                                           decl->isNoReturn(),
                                           isInSystemModule(dc),
-                                          hasCustomName,
-                                          &bodyParams,
-                                          name);
+                                          hasCustomName, bodyParams, name);
       if (!type)
         return nullptr;
 
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index ddb84e0..962999a 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -1333,7 +1333,7 @@
                    ArrayRef<const clang::ParmVarDecl *> params,
                    bool isVariadic, bool isNoReturn,
                    bool isFromSystemModule, bool hasCustomName,
-                   ParameterList **parameterList, DeclName &name) {
+                   ParameterList *&parameterList, DeclName &name) {
 
   bool allowNSUIntegerAsInt = isFromSystemModule;
   if (allowNSUIntegerAsInt) {
@@ -1461,13 +1461,13 @@
   }
 
   // Form the parameter list.
-  *parameterList = ParameterList::create(SwiftContext, parameters);
+  parameterList = ParameterList::create(SwiftContext, parameters);
   
   FunctionType::ExtInfo extInfo;
   extInfo = extInfo.withIsNoReturn(isNoReturn);
   
   // Form the function type.
-  auto argTy = (*parameterList)->getType(SwiftContext);
+  auto argTy = parameterList->getType(SwiftContext);
   return FunctionType::get(argTy, swiftResultTy, extInfo);
 }
 
diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h
index 55804c2..f62f865 100644
--- a/lib/ClangImporter/ImporterImpl.h
+++ b/lib/ClangImporter/ImporterImpl.h
@@ -1,4 +1,4 @@
-//===--- ImporterImpl.h - Import Clang Modules - Implementation------------===//
+//===--- ImporterImpl.h - Import Clang Modules: Implementation ------------===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -1128,7 +1128,7 @@
                           bool isVariadic, bool isNoReturn,
                           bool isFromSystemModule,
                           bool hasCustomName,
-                          ParameterList **parameterList,
+                          ParameterList *&parameterList,
                           DeclName &name);
 
   Type importPropertyType(const clang::ObjCPropertyDecl *clangDecl,
diff --git a/lib/ClangImporter/InferredAttributes.def b/lib/ClangImporter/InferredAttributes.def
index 6af823a..54a14a3 100644
--- a/lib/ClangImporter/InferredAttributes.def
+++ b/lib/ClangImporter/InferredAttributes.def
@@ -22,7 +22,7 @@
 // ClassName is the name of the class, i.e., NSManagedObject
 // AttributeSet is an OR of attribute names, i.e., requires_stored_property_inits
 //
-// ===----------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 
 #ifndef INFERRED_ATTRIBUTES
 #  define INFERRED_ATTRIBUTES(ModuleName, ClassName, AttributeSet)
diff --git a/lib/ClangImporter/MacroTable.def b/lib/ClangImporter/MacroTable.def
index 6a11308..11fc681 100644
--- a/lib/ClangImporter/MacroTable.def
+++ b/lib/ClangImporter/MacroTable.def
@@ -13,7 +13,7 @@
 // This file defines the database of macros that should be suppressed during
 // API import.
 //
-// ===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 
 #ifndef SUPPRESS_MACRO
 /// Describes a macro that should be suppressed.
diff --git a/lib/ClangImporter/SortedCFDatabase.def.gyb b/lib/ClangImporter/SortedCFDatabase.def.gyb
index f77c046..04d327e 100644
--- a/lib/ClangImporter/SortedCFDatabase.def.gyb
+++ b/lib/ClangImporter/SortedCFDatabase.def.gyb
@@ -28,7 +28,7 @@
 lineForName = {}
 
 # Load the data file.
-with codecs.open(CFDatabaseFile, encoding=sys.getfilesystemencoding(), errors='strict') as f:
+with codecs.open(CFDatabaseFile, encoding='utf-8', errors='strict') as f:
   for line in f:
     # Pass through preprocessor directives literally.
     # Assume that they all fall into either a strict prologue or epilogue.
diff --git a/lib/IDE/SyntaxModel.cpp b/lib/IDE/SyntaxModel.cpp
index 8be90e7..ad4845b 100644
--- a/lib/IDE/SyntaxModel.cpp
+++ b/lib/IDE/SyntaxModel.cpp
@@ -48,6 +48,7 @@
 
 SyntaxModelContext::SyntaxModelContext(SourceFile &SrcFile)
   : Impl(*new Implementation(SrcFile)) {
+  const bool IsPlayground = Impl.LangOpts.Playground;
   const SourceManager &SM = Impl.SrcMgr;
   std::vector<Token> Tokens = swift::tokenize(Impl.LangOpts, SM,
                                               *Impl.SrcFile.getBufferID(),
@@ -111,7 +112,8 @@
       case tok::floating_literal: Kind = SyntaxNodeKind::Floating; break;
       case tok::string_literal: Kind = SyntaxNodeKind::String; break;
       case tok::comment:
-        if (Tok.getText().startswith("///"))
+        if (Tok.getText().startswith("///") ||
+            (IsPlayground && Tok.getText().startswith("//:")))
           Kind = SyntaxNodeKind::DocCommentLine;
         else if (Tok.getText().startswith("/**"))
           Kind = SyntaxNodeKind::DocCommentBlock;
diff --git a/lib/IRGen/CMakeLists.txt b/lib/IRGen/CMakeLists.txt
index 2fb2169..587d93c 100644
--- a/lib/IRGen/CMakeLists.txt
+++ b/lib/IRGen/CMakeLists.txt
@@ -30,6 +30,7 @@
   IRGenModule.cpp
   IRGenSIL.cpp
   Linking.cpp
+  LocalTypeData.cpp
   SwiftTargetInfo.cpp
   StructLayout.cpp
   TypeLayoutVerifier.cpp
diff --git a/lib/IRGen/DominancePoint.h b/lib/IRGen/DominancePoint.h
new file mode 100644
index 0000000..c99611e
--- /dev/null
+++ b/lib/IRGen/DominancePoint.h
@@ -0,0 +1,77 @@
+//===--- DominancePoint.h - Dominance points ----------------------*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines types relating to local dominance calculations
+//  during the emission of a function.
+//
+//  During the emission of a function, the LLVM IR is not well-formed enough
+//  to do accurate dominance computations.  For example, a basic block may
+//  appear to have a single predecessor, but that may be because a different
+//  predecessor has not yet been added.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_DOMINANCEPOINT_H
+#define SWIFT_IRGEN_DOMINANCEPOINT_H
+
+#include <assert.h>
+#include <stdint.h>
+
+namespace swift {
+namespace irgen {
+  class IRGenFunction;
+
+/// An opaque class for storing keys for the dominance callback.  The
+/// key is assumed to be something like a (uniqued) pointer, and a
+/// null pointer is assumed to mean a non-dominating point.
+class DominancePoint {
+  uintptr_t Value;
+  enum : uintptr_t {
+    Universal = 0,
+  };
+  explicit DominancePoint(uintptr_t value) : Value(value) {}
+public:
+  explicit DominancePoint(void *value)
+      : Value(reinterpret_cast<uintptr_t>(value)) {
+    assert(isOrdinary());
+  }
+
+  /// Something about the definition is known to dominate all possible
+  /// places that will use it.
+  static DominancePoint universal() { return DominancePoint(Universal); }
+
+  bool isOrdinary() const {
+    return Value != Universal;
+  }
+  bool isUniversal() const {
+    return Value == Universal;
+  }
+
+  template <class T> T* as() const {
+    assert(isOrdinary());
+    return reinterpret_cast<T*>(Value);
+  }
+  bool operator==(DominancePoint other) const { return Value == other.Value; }
+};
+
+/// A dominance resolver is a function that answers the question of
+/// whether one dominance point dominates another.
+///
+/// It will only be asked this question with ordinary dominance points.
+using DominanceResolverFunction = bool(*)(IRGenFunction &IGF,
+                                          DominancePoint curPoint,
+                                          DominancePoint definingPoint);
+
+}
+}
+
+#endif
diff --git a/lib/IRGen/DominanceScope.h b/lib/IRGen/DominanceScope.h
new file mode 100644
index 0000000..f0a327e
--- /dev/null
+++ b/lib/IRGen/DominanceScope.h
@@ -0,0 +1,82 @@
+//===--- DominanceScope.h - Dominance scoping ---------------------*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines types relating to local dominance calculations
+//  during the emission of a function.
+//
+//  During the emission of a function, the LLVM IR is not well-formed enough
+//  to do accurate dominance computations.  For example, a basic block may
+//  appear to have a single predecessor, but that may be because a different
+//  predecessor has not yet been added.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_DOMINANCEPOINT_H
+#define SWIFT_IRGEN_DOMINANCEPOINT_H
+
+#include <stdint.h>
+
+namespace swift {
+namespace irgen {
+  class IRGenFunction;
+
+/// An opaque class for storing keys for the dominance callback.  The
+/// key is assumed to be something like a (uniqued) pointer, and a
+/// null pointer is assumed to mean a non-dominating point.
+class DominancePoint {
+  uintptr_t Value;
+  enum : uintptr_t {
+    Universal = 0,
+    Unknown = 1,
+  };
+  explicit DominancePoint(uintptr_t value) : Value(value) {}
+public:
+  explicit DominancePoint(void *value)
+      : Value(reinterpret_cast<uintptr_t>(value)) {
+    assert(isOrdinary());
+  }
+
+  /// Something about the definition is known to dominate all possible
+  /// places that will use it.
+  static DominancePoint universal() { return DominanceKey(Universal); }
+
+  /// This definition point has non-obvious dominance rules; don't put
+  /// anything here and assume it'll dominate other things.  This should be
+  /// used when IRGen adds its own control flow that might interact awkwardly
+  /// with dominance.
+  static DominancePoint unknown() { return DominanceKey(Unknown); }
+
+  bool isOrdinary() {
+    return Value > Uncacheable;
+  }
+  bool isUniversal() {
+    return Value == Universal;
+  }
+  bool isUnknown() {
+    return Value == Unknown;
+  }
+
+  template <class T> T* as() const {
+    assert(isOrdinary());
+    return reinterpret_cast<T*>(Value);
+  }
+  bool operator==(DominancePoint other) const { return Value == other.Value; }
+};
+
+using DominanceResolverFunction = bool(*)(IRGenFunction &IGF,
+                                          DominancePoint curPoint,
+                                          DominancePoint definingPoint);
+
+}
+}
+
+#endif
\ No newline at end of file
diff --git a/lib/IRGen/EnumPayload.h b/lib/IRGen/EnumPayload.h
index 34437db..3b675f4 100644
--- a/lib/IRGen/EnumPayload.h
+++ b/lib/IRGen/EnumPayload.h
@@ -1,4 +1,4 @@
-//===--- EnumPayload.h - Payload management for 'enum' Types ------* C++ *-===//
+//===--- EnumPayload.h - Payload management for 'enum' Types ----*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp
index d451026..c02908b 100644
--- a/lib/IRGen/Fulfillment.cpp
+++ b/lib/IRGen/Fulfillment.cpp
@@ -327,3 +327,18 @@
     return true;
   }
 }
+
+bool FulfillmentMap::Everything::isInterestingType(CanType type) const {
+  return true;
+}
+bool FulfillmentMap::Everything::hasInterestingType(CanType type) const {
+  return true;
+}
+bool FulfillmentMap::Everything
+                   ::hasLimitedInterestingConformances(CanType type) const {
+  return false;
+}
+GenericSignature::ConformsToArray
+FulfillmentMap::Everything::getInterestingConformances(CanType type) const{
+  return {};
+}
diff --git a/lib/IRGen/Fulfillment.h b/lib/IRGen/Fulfillment.h
index 7679050..c4826bd 100644
--- a/lib/IRGen/Fulfillment.h
+++ b/lib/IRGen/Fulfillment.h
@@ -71,8 +71,22 @@
     virtual ~InterestingKeysCallback() = default;
   };
 
+  /// An implementaton of InterestingKeysCallback that returns everything
+  /// fulfillable.
+  struct Everything : InterestingKeysCallback {
+    bool isInterestingType(CanType type) const override;
+    bool hasInterestingType(CanType type) const override;
+    bool hasLimitedInterestingConformances(CanType type) const override;
+    GenericSignature::ConformsToArray
+      getInterestingConformances(CanType type) const override;
+  };
+
   FulfillmentMap() = default;
 
+  using iterator = decltype(Fulfillments)::iterator;
+  iterator begin() { return Fulfillments.begin(); }
+  iterator end() { return Fulfillments.end(); }
+
   /// Is it even theoretically possible that we might find a fulfillment
   /// in the given type?
   static bool isInterestingTypeForFulfillments(CanType type) {
diff --git a/lib/IRGen/GenArchetype.cpp b/lib/IRGen/GenArchetype.cpp
index 2e1e82f..ec23b39 100644
--- a/lib/IRGen/GenArchetype.cpp
+++ b/lib/IRGen/GenArchetype.cpp
@@ -53,7 +53,7 @@
 
 static llvm::Value *emitArchetypeTypeMetadataRef(IRGenFunction &IGF,
                                                  CanArchetypeType archetype) {
-  return IGF.getLocalTypeData(archetype, LocalTypeData::forMetatype());
+  return IGF.getLocalTypeData(archetype, LocalTypeDataKind::forMetatype());
 }
 
 namespace {
@@ -88,8 +88,9 @@
                                CanArchetypeType archetype,
                                unsigned which) const {
     assert(which < getNumStoredProtocols());
+    auto protocol = archetype->getConformsTo()[which];
     return IGF.getLocalTypeData(archetype,
-                          LocalTypeData::forArchetypeProtocolWitness(which));
+                 LocalTypeDataKind::forArchetypeProtocolWitnessTable(protocol));
   }
 };
 
@@ -274,7 +275,7 @@
                            llvm::Value *metadata) {
   assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
   IGF.setUnscopedLocalTypeData(CanType(archetype),
-                               LocalTypeData::forMetatype(),
+                               LocalTypeDataKind::forMetatype(),
                                metadata);
 
   // Create a shadow copy of the metadata in an alloca for the debug info.
@@ -298,8 +299,10 @@
                             llvm::Value *wtable) {
   assert(wtable->getType() == IGF.IGM.WitnessTablePtrTy);
   assert(protocolIndex < archetype->getConformsTo().size());
+  auto protocol = archetype->getConformsTo()[protocolIndex];
   IGF.setUnscopedLocalTypeData(CanType(archetype),
-             LocalTypeData::forArchetypeProtocolWitness(protocolIndex), wtable);
+                  LocalTypeDataKind::forArchetypeProtocolWitnessTable(protocol),
+                               wtable);
 }
 
 /// Inform IRGenFunction that the given archetype has the given value
diff --git a/lib/IRGen/GenCast.cpp b/lib/IRGen/GenCast.cpp
index 1b77d3e..01bc6ab 100644
--- a/lib/IRGen/GenCast.cpp
+++ b/lib/IRGen/GenCast.cpp
@@ -320,7 +320,7 @@
                                    llvm::Twine(name), IGM.getModule());
   fn->setAttributes(IGM.constructInitialAttributes());
   
-  auto IGF = IRGenFunction(IGM, fn);
+  IRGenFunction IGF(IGM, fn);
   Explosion args = IGF.collectParameters();
 
   auto value = args.claimNext();
@@ -593,6 +593,7 @@
 
   // If we're doing a conditional cast, and the ObjC protocol checks failed,
   // then the cast is done.
+  Optional<ConditionalDominanceScope> condition;
   llvm::BasicBlock *origBB = nullptr, *successBB = nullptr, *contBB = nullptr;
   if (!objcProtos.empty()) {
     switch (mode) {
@@ -607,6 +608,7 @@
                                  cast<llvm::PointerType>(objcCast->getType())));
       IGF.Builder.CreateCondBr(isNull, contBB, successBB);
       IGF.Builder.emitBlock(successBB);
+      condition.emplace(IGF);
     }
     }
   }
@@ -658,6 +660,7 @@
 
   // If we had conditional ObjC checks, join the failure paths.
   if (contBB) {
+    condition.reset();
     IGF.Builder.CreateBr(contBB);
     IGF.Builder.emitBlock(contBB);
     
diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp
index d6265e6..5e394c9 100644
--- a/lib/IRGen/GenEnum.cpp
+++ b/lib/IRGen/GenEnum.cpp
@@ -561,6 +561,7 @@
       IGF.Builder.CreateCondBr(xiBool, xiBB, noXIBB);
 
       IGF.Builder.emitBlock(xiBB);
+      ConditionalDominanceScope condition(IGF);
       copyWitnessFromElt(ValueWitness::ExtraInhabitantFlags);
       IGF.Builder.CreateBr(noXIBB);
 
@@ -2083,6 +2084,7 @@
         llvm::BasicBlock *endBB = testFixedEnumContainsPayload(IGF, payload, extraTag);
 
         if (PayloadBitCount > 0) {
+          ConditionalDominanceScope condition(IGF);
           Explosion payloadValue;
           Explosion payloadCopy;
           auto &loadableTI = getLoadablePayloadTypeInfo();
@@ -2131,6 +2133,7 @@
 
         // If we did, consume it.
         if (PayloadBitCount > 0) {
+          ConditionalDominanceScope condition(IGF);
           Explosion payloadValue;
           auto &loadableTI = getLoadablePayloadTypeInfo();
           loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0);
@@ -2173,6 +2176,7 @@
 
         // If we did, consume it.
         if (PayloadBitCount > 0) {
+          ConditionalDominanceScope condition(IGF);
           Explosion payloadValue;
           auto &loadableTI = getLoadablePayloadTypeInfo();
           loadableTI.unpackFromEnumPayload(IGF, payload, payloadValue, 0);
@@ -2205,6 +2209,8 @@
         // Check that there is a payload at the address.
         llvm::BasicBlock *endBB = testEnumContainsPayload(IGF, addr, T);
 
+        ConditionalDominanceScope condition(IGF);
+
         // If there is, project and destroy it.
         Address payloadAddr = projectPayloadData(IGF, addr);
         getPayloadTypeInfo().destroy(IGF, payloadAddr,
@@ -2288,46 +2294,64 @@
         llvm::BasicBlock *noDestPayloadBB
           = testEnumContainsPayload(IGF, dest, T);
 
-        // Here, the destination has a payload. Now see if the source also has
-        // one.
-        llvm::BasicBlock *destNoSrcPayloadBB
-          = testEnumContainsPayload(IGF, src, T);
+        {
+          ConditionalDominanceScope destCondition(IGF);
 
-        // Here, both source and destination have payloads. Do the reassignment
-        // of the payload in-place.
-        if (isTake)
-          getPayloadTypeInfo().assignWithTake(IGF, destData, srcData, PayloadT);
-        else
-          getPayloadTypeInfo().assignWithCopy(IGF, destData, srcData, PayloadT);
-        IGF.Builder.CreateBr(endBB);
+          // Here, the destination has a payload. Now see if the source also
+          // has one.
+          llvm::BasicBlock *destNoSrcPayloadBB
+            = testEnumContainsPayload(IGF, src, T);
 
-        // If the destination has a payload but the source doesn't, we can destroy
-        // the payload and primitive-store the new no-payload value.
-        IGF.Builder.emitBlock(destNoSrcPayloadBB);
-        getPayloadTypeInfo().destroy(IGF, destData, PayloadT);
-        emitPrimitiveCopy(IGF, dest, src, T);
-        IGF.Builder.CreateBr(endBB);
+          {
+            ConditionalDominanceScope destSrcCondition(IGF);
+
+            // Here, both source and destination have payloads. Do the
+            // reassignment of the payload in-place.
+            getPayloadTypeInfo().assign(IGF, destData, srcData,
+                                        isTake, PayloadT);
+            IGF.Builder.CreateBr(endBB);
+          }
+
+          // If the destination has a payload but the source doesn't, we can
+          // destroy the payload and primitive-store the new no-payload value.
+          IGF.Builder.emitBlock(destNoSrcPayloadBB);
+          {
+            ConditionalDominanceScope destNoSrcCondition(IGF);
+            getPayloadTypeInfo().destroy(IGF, destData, PayloadT);
+            emitPrimitiveCopy(IGF, dest, src, T);
+            IGF.Builder.CreateBr(endBB);
+          }
+        }
 
         // Now, if the destination has no payload, check if the source has one.
         IGF.Builder.emitBlock(noDestPayloadBB);
-        llvm::BasicBlock *noDestNoSrcPayloadBB
-          = testEnumContainsPayload(IGF, src, T);
+        {
+          ConditionalDominanceScope noDestCondition(IGF);
+          llvm::BasicBlock *noDestNoSrcPayloadBB
+            = testEnumContainsPayload(IGF, src, T);
 
-        // Here, the source has a payload but the destination doesn't. We can
-        // copy-initialize the source over the destination, then primitive-store
-        // the zero extra tag (if any).
-        if (isTake)
-          getPayloadTypeInfo().initializeWithTake(IGF, destData, srcData, PayloadT);
-        else
-          getPayloadTypeInfo().initializeWithCopy(IGF, destData, srcData, PayloadT);
-        emitInitializeExtraTagBitsForPayload(IGF, dest, T);
-        IGF.Builder.CreateBr(endBB);
+          {
+            ConditionalDominanceScope noDestSrcCondition(IGF);
 
-        // If neither destination nor source have payloads, we can just primitive-
-        // store the new empty-case value.
-        IGF.Builder.emitBlock(noDestNoSrcPayloadBB);
-        emitPrimitiveCopy(IGF, dest, src, T);
-        IGF.Builder.CreateBr(endBB);
+            // Here, the source has a payload but the destination doesn't.
+            // We can copy-initialize the source over the destination, then
+            // primitive-store the zero extra tag (if any).
+
+            getPayloadTypeInfo().initialize(IGF, destData, srcData, isTake,
+                                            PayloadT);
+            emitInitializeExtraTagBitsForPayload(IGF, dest, T);
+            IGF.Builder.CreateBr(endBB);
+          }
+
+          // If neither destination nor source have payloads, we can just
+          // primitive- store the new empty-case value.
+          IGF.Builder.emitBlock(noDestNoSrcPayloadBB);
+          {
+            ConditionalDominanceScope noDestNoSrcCondition(IGF);
+            emitPrimitiveCopy(IGF, dest, src, T);
+            IGF.Builder.CreateBr(endBB);
+          }
+        }
 
         IGF.Builder.emitBlock(endBB);
         return;
@@ -2377,22 +2401,25 @@
         llvm::BasicBlock *noSrcPayloadBB
           = testEnumContainsPayload(IGF, src, T);
 
-        // Here, the source value has a payload. Initialize the destination with
-        // it, and set the extra tag if any to zero.
-        if (isTake)
-          getPayloadTypeInfo().initializeWithTake(IGF, destData, srcData,
-                                                  getPayloadType(IGF.IGM, T));
-        else
-          getPayloadTypeInfo().initializeWithCopy(IGF, destData, srcData,
-                                                  getPayloadType(IGF.IGM, T));
-        emitInitializeExtraTagBitsForPayload(IGF, dest, T);
-        IGF.Builder.CreateBr(endBB);
+        {
+          ConditionalDominanceScope condition(IGF);
+
+          // Here, the source value has a payload. Initialize the destination
+          // with it, and set the extra tag if any to zero.
+          getPayloadTypeInfo().initialize(IGF, destData, srcData, isTake,
+                                          getPayloadType(IGF.IGM, T));
+          emitInitializeExtraTagBitsForPayload(IGF, dest, T);
+          IGF.Builder.CreateBr(endBB);
+        }
 
         // If the source value has no payload, we can primitive-store the
         // empty-case value.
         IGF.Builder.emitBlock(noSrcPayloadBB);
-        emitPrimitiveCopy(IGF, dest, src, T);
-        IGF.Builder.CreateBr(endBB);
+        {
+          ConditionalDominanceScope condition(IGF);
+          emitPrimitiveCopy(IGF, dest, src, T);
+          IGF.Builder.CreateBr(endBB);        
+        }
 
         IGF.Builder.emitBlock(endBB);
         return;
@@ -3561,6 +3588,8 @@
         auto *caseBB = llvm::BasicBlock::Create(IGF.IGM.getLLVMContext());
         swi->addCase(llvm::ConstantInt::get(tagTy, tagIndex), caseBB);
 
+        ConditionalDominanceScope condition(IGF);
+
         IGF.Builder.emitBlock(caseBB);
         f(tagIndex, payloadCasePair);
         IGF.Builder.CreateBr(endBB);
@@ -3765,6 +3794,7 @@
         auto *noAliasBB = llvm::BasicBlock::Create(C);
         IGF.Builder.CreateCondBr(alias, endBB, noAliasBB);
         IGF.Builder.emitBlock(noAliasBB);
+        ConditionalDominanceScope condition(IGF);
 
         // Destroy the old value.
         destroy(IGF, dest, T);
@@ -3843,6 +3873,8 @@
           swi->addCase(llvm::ConstantInt::get(tagTy, tagIndex), caseBB);
           IGF.Builder.emitBlock(caseBB);
 
+          ConditionalDominanceScope condition(IGF);
+
           // Do the take/copy of the payload.
           Address srcData = IGF.Builder.CreateBitCast(src,
                                   payloadTI.getStorageType()->getPointerTo());
@@ -3869,6 +3901,7 @@
         // For trivial payloads (including no-payload cases), we can just
         // primitive-copy to the destination.
         IGF.Builder.emitBlock(trivialBB);
+        ConditionalDominanceScope condition(IGF);
         emitPrimitiveCopy(IGF, dest, src, T);
         IGF.Builder.CreateBr(endBB);
 
@@ -4114,14 +4147,20 @@
       IGF.Builder.CreateCondBr(cond, noPayloadBB, payloadBB);
 
       IGF.Builder.emitBlock(noPayloadBB);
-      llvm::Value *noPayloadTag = IGF.Builder.CreateSub(tag, numPayloadCases);
-      storeNoPayloadTag(IGF, enumAddr, noPayloadTag, T);
-      IGF.Builder.CreateBr(endBB);
-      
+      {
+        ConditionalDominanceScope condition(IGF);
+        llvm::Value *noPayloadTag = IGF.Builder.CreateSub(tag, numPayloadCases);
+        storeNoPayloadTag(IGF, enumAddr, noPayloadTag, T);
+        IGF.Builder.CreateBr(endBB);
+      }
+
       IGF.Builder.emitBlock(payloadBB);
-      storePayloadTag(IGF, enumAddr, tag, T);
-      IGF.Builder.CreateBr(endBB);
-      
+      {
+        ConditionalDominanceScope condition(IGF);
+        storePayloadTag(IGF, enumAddr, tag, T);
+        IGF.Builder.CreateBr(endBB);
+      }
+
       IGF.Builder.emitBlock(endBB);
     }
 
diff --git a/lib/IRGen/GenEnum.h b/lib/IRGen/GenEnum.h
index 2b3e70b..e9fbe68 100644
--- a/lib/IRGen/GenEnum.h
+++ b/lib/IRGen/GenEnum.h
@@ -1,4 +1,4 @@
-//===--- GenEnum.h - Swift IR Generation For 'enum' Types ---------* C++ *-===//
+//===--- GenEnum.h - Swift IR Generation For 'enum' Types -------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp
index 9d64992..d5265fb 100644
--- a/lib/IRGen/GenExistential.cpp
+++ b/lib/IRGen/GenExistential.cpp
@@ -1501,6 +1501,8 @@
 
     // Project down to the buffers.
     IGF.Builder.emitBlock(contBB);
+    // We don't need a ConditionalDominanceScope here because (1) there's no
+    // code in the other condition and (2) we immediately return.
     Address destBuffer = layout.projectExistentialBuffer(IGF, dest);
     Address srcBuffer = layout.projectExistentialBuffer(IGF, src);
 
@@ -1516,10 +1518,10 @@
       IGF.Builder.CreateICmpEQ(destMetadata, srcMetadata, "sameMetadata");
     IGF.Builder.CreateCondBr(sameMetadata, matchBB, noMatchBB);
 
-    { // (scope to avoid contaminating other branches with these values)
-
-      // If so, do a direct assignment.
-      IGF.Builder.emitBlock(matchBB);
+    // If so, do a direct assignment.
+    IGF.Builder.emitBlock(matchBB);
+    {
+      ConditionalDominanceScope matchCondition(IGF);
 
       llvm::Value *destObject =
         emitProjectBufferCall(IGF, destMetadata, destBuffer);
@@ -1537,30 +1539,33 @@
     // the madnesses that boost::variant has to go through, with the
     // advantage of address-invariance.
     IGF.Builder.emitBlock(noMatchBB);
+    {
+      ConditionalDominanceScope noMatchCondition(IGF);
 
-    // Store the metadata ref.
-    IGF.Builder.CreateStore(srcMetadata, destMetadataSlot);
+      // Store the metadata ref.
+      IGF.Builder.CreateStore(srcMetadata, destMetadataSlot);
 
-    // Store the protocol witness tables.
-    unsigned numTables = layout.getNumTables();
-    for (unsigned i = 0, e = numTables; i != e; ++i) {
-      Address destTableSlot = layout.projectWitnessTable(IGF, dest, i);
-      llvm::Value *srcTable = layout.loadWitnessTable(IGF, src, i);
+      // Store the protocol witness tables.
+      unsigned numTables = layout.getNumTables();
+      for (unsigned i = 0, e = numTables; i != e; ++i) {
+        Address destTableSlot = layout.projectWitnessTable(IGF, dest, i);
+        llvm::Value *srcTable = layout.loadWitnessTable(IGF, src, i);
 
-      // Overwrite the old witness table.
-      IGF.Builder.CreateStore(srcTable, destTableSlot);
+        // Overwrite the old witness table.
+        IGF.Builder.CreateStore(srcTable, destTableSlot);
+      }
+
+      // Destroy the old value.
+      emitDestroyBufferCall(IGF, destMetadata, destBuffer);
+
+      // Copy-initialize with the new value.  Again, pull a value
+      // witness table from the source metadata if we can't use a
+      // protocol witness table.
+      emitInitializeBufferWithCopyOfBufferCall(IGF, srcMetadata,
+                                               destBuffer, srcBuffer);
+      IGF.Builder.CreateBr(doneBB);
     }
 
-    // Destroy the old value.
-    emitDestroyBufferCall(IGF, destMetadata, destBuffer);
-
-    // Copy-initialize with the new value.  Again, pull a value
-    // witness table from the source metadata if we can't use a
-    // protocol witness table.
-    emitInitializeBufferWithCopyOfBufferCall(IGF, srcMetadata,
-                                             destBuffer, srcBuffer);
-    IGF.Builder.CreateBr(doneBB);
-
     // All done.
     IGF.Builder.emitBlock(doneBB);
     IGF.Builder.CreateRetVoid();
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index c88ac9c..efc7097 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -165,20 +165,17 @@
     llvm::Value *metadata = claimNext(IGF.IGM.TypeMetadataPtrTy);
     metadata->setName(archetype->getFullName());
     IGF.setUnscopedLocalTypeData(CanType(archetype),
-                                 LocalTypeData::forMetatype(),
+                                 LocalTypeDataKind::forMetatype(),
                                  metadata);
   }
 
   // Bind all the argument witness tables.
   for (auto archetype : generics.getAllArchetypes()) {
-    unsigned nextProtocolIndex = 0;
     for (auto protocol : archetype->getConformsTo()) {
-      LocalTypeData key
-        = LocalTypeData::forArchetypeProtocolWitness(nextProtocolIndex);
-      nextProtocolIndex++;
       if (!Lowering::TypeConverter::protocolRequiresWitnessTable(protocol))
         continue;
       llvm::Value *wtable = claimNext(IGF.IGM.WitnessTablePtrTy);
+      auto key = LocalTypeDataKind::forArchetypeProtocolWitnessTable(protocol);
       IGF.setUnscopedLocalTypeData(CanType(archetype), key, wtable);
     }
   }
@@ -289,7 +286,7 @@
   // reference already.
   if (isPattern) {
     if (auto cache = IGF.tryGetLocalTypeData(theType,
-                                             LocalTypeData::forMetatype()))
+                                             LocalTypeDataKind::forMetatype()))
       return cache;
   }
 
@@ -325,7 +322,8 @@
     result->setDoesNotThrow();
     result->addAttribute(llvm::AttributeSet::FunctionIndex,
                          llvm::Attribute::ReadNone);
-    IGF.setScopedLocalTypeData(theType, LocalTypeData::forMetatype(), result);
+    IGF.setScopedLocalTypeData(theType, LocalTypeDataKind::forMetatype(),
+                               result);
     return result;
   }
 
@@ -356,7 +354,8 @@
     result->setDoesNotThrow();
     result->addAttribute(llvm::AttributeSet::FunctionIndex,
                          llvm::Attribute::ReadNone);
-    IGF.setScopedLocalTypeData(theType, LocalTypeData::forMetatype(), result);
+    IGF.setScopedLocalTypeData(theType, LocalTypeDataKind::forMetatype(),
+                               result);
     return result;
   }
 
@@ -388,7 +387,7 @@
   IGF.Builder.CreateLifetimeEnd(argsBuffer,
                           IGF.IGM.getPointerSize() * genericArgs.Values.size());
 
-  IGF.setScopedLocalTypeData(theType, LocalTypeData::forMetatype(), result);
+  IGF.setScopedLocalTypeData(theType, LocalTypeDataKind::forMetatype(), result);
   return result;
 }
 
@@ -963,7 +962,7 @@
     }
 
     llvm::Value *visitArchetypeType(CanArchetypeType type) {
-      return IGF.getLocalTypeData(type, LocalTypeData::forMetatype());
+      return IGF.getLocalTypeData(type, LocalTypeDataKind::forMetatype());
     }
 
     llvm::Value *visitGenericTypeParamType(CanGenericTypeParamType type) {
@@ -992,12 +991,12 @@
 
     /// Try to find the metatype in local data.
     llvm::Value *tryGetLocal(CanType type) {
-      return IGF.tryGetLocalTypeData(type, LocalTypeData::forMetatype());
+      return IGF.tryGetLocalTypeData(type, LocalTypeDataKind::forMetatype());
     }
 
     /// Set the metatype in local data.
     llvm::Value *setLocal(CanType type, llvm::Instruction *metatype) {
-      IGF.setScopedLocalTypeData(type,  LocalTypeData::forMetatype(),
+      IGF.setScopedLocalTypeData(type,  LocalTypeDataKind::forMetatype(),
                                  metatype);
       return metatype;
     }
@@ -1156,7 +1155,8 @@
                                                          CanType type,
                                                  ForDefinition_t shouldDefine) {
   // If we already cached the metadata, use it.
-  if (auto local = IGF.tryGetLocalTypeData(type, LocalTypeData::forMetatype()))
+  if (auto local =
+        IGF.tryGetLocalTypeData(type, LocalTypeDataKind::forMetatype()))
     return local;
   
   llvm::Constant *accessor =
@@ -1167,7 +1167,7 @@
   call->setDoesNotThrow();
   
   // Save the metadata for future lookups.
-  IGF.setScopedLocalTypeData(type, LocalTypeData::forMetatype(), call);
+  IGF.setScopedLocalTypeData(type, LocalTypeDataKind::forMetatype(), call);
   
   return call;
 }
@@ -1394,13 +1394,13 @@
     llvm::Value *tryGetLocal(CanType type) {
       return IGF.tryGetLocalTypeDataForLayout(
                                           SILType::getPrimitiveObjectType(type),
-                                          LocalTypeData::forMetatype());
+                                          LocalTypeDataKind::forMetatype());
     }
 
     /// Set the metatype in local data.
     llvm::Value *setLocal(CanType type, llvm::Instruction *metatype) {
       IGF.setScopedLocalTypeDataForLayout(SILType::getPrimitiveObjectType(type),
-                                          LocalTypeData::forMetatype(),
+                                          LocalTypeDataKind::forMetatype(),
                                           metatype);
       return metatype;
     }
@@ -2720,7 +2720,7 @@
           value = emitWitnessTableRef(IGF, fillOp.Archetype, fillOp.Protocol);
         } else {
           value = IGF.getLocalTypeData(fillOp.Archetype,
-                                       LocalTypeData::forMetatype());
+                                       LocalTypeDataKind::forMetatype());
         }
         value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
         auto dest = createPointerSizedGEP(IGF, metadataWords,
@@ -3681,13 +3681,14 @@
 IRGenFunction::emitValueWitnessTableRef(CanType type) {
   // See if we have a cached projection we can use.
   if (auto cached = tryGetLocalTypeData(type,
-                                      LocalTypeData::forValueWitnessTable())) {
+                                  LocalTypeDataKind::forValueWitnessTable())) {
     return cached;
   }
   
   auto metadata = emitTypeMetadataRef(type);
   auto vwtable = emitValueWitnessTableRefForMetadata(metadata);
-  setScopedLocalTypeData(type, LocalTypeData::forValueWitnessTable(), vwtable);
+  setScopedLocalTypeData(type, LocalTypeDataKind::forValueWitnessTable(),
+                         vwtable);
   return vwtable;
 }
 
@@ -3715,14 +3716,14 @@
 IRGenFunction::emitValueWitnessTableRefForLayout(SILType type) {
   // See if we have a cached projection we can use.
   if (auto cached = tryGetLocalTypeDataForLayout(type,
-                                      LocalTypeData::forValueWitnessTable())) {
+                                  LocalTypeDataKind::forValueWitnessTable())) {
     return cached;
   }
   
   auto metadata = emitTypeMetadataRefForLayout(type);
   auto vwtable = emitValueWitnessTableRefForMetadata(metadata);
   setScopedLocalTypeDataForLayout(type,
-                                  LocalTypeData::forValueWitnessTable(),
+                                  LocalTypeDataKind::forValueWitnessTable(),
                                   vwtable);
   return vwtable;
 }
diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp
index 94c49cf..d39498f 100644
--- a/lib/IRGen/GenOpaque.cpp
+++ b/lib/IRGen/GenOpaque.cpp
@@ -320,25 +320,26 @@
 
 llvm::Value *IRGenFunction::emitValueWitness(CanType type, ValueWitness index) {
   if (auto witness =
-        tryGetLocalTypeData(type, LocalTypeData::forValueWitness(index)))
+        tryGetLocalTypeData(type, LocalTypeDataKind::forValueWitness(index)))
     return witness;
   
   auto vwtable = emitValueWitnessTableRef(type);
   auto witness = emitLoadOfValueWitness(*this, vwtable, index);
-  setScopedLocalTypeData(type, LocalTypeData::forValueWitness(index), witness);
+  setScopedLocalTypeData(type, LocalTypeDataKind::forValueWitness(index),
+                         witness);
   return witness;
 }
 
 llvm::Value *IRGenFunction::emitValueWitnessForLayout(SILType type,
                                                       ValueWitness index) {
   if (auto witness = tryGetLocalTypeDataForLayout(type,
-                                         LocalTypeData::forValueWitness(index)))
+                                    LocalTypeDataKind::forValueWitness(index)))
     return witness;
   
   auto vwtable = emitValueWitnessTableRefForLayout(type);
   auto witness = emitLoadOfValueWitness(*this, vwtable, index);
   setScopedLocalTypeDataForLayout(type,
-                                LocalTypeData::forValueWitness(index), witness);
+                           LocalTypeDataKind::forValueWitness(index), witness);
   return witness;
 }
 
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 207a382..d7a7f12 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -559,14 +559,18 @@
   IGF.Builder.CreateCondBr(isInline, directBB, indirectBB);
 
   // Emit the indirect path.
-  IGF.Builder.emitBlock(indirectBB);
-  operation.emitForPacking(IGF, T, type, FixedPacking::Allocate);
-  IGF.Builder.CreateBr(contBB);
+  IGF.Builder.emitBlock(indirectBB); {
+    ConditionalDominanceScope condition(IGF);
+    operation.emitForPacking(IGF, T, type, FixedPacking::Allocate);
+    IGF.Builder.CreateBr(contBB);
+  }
 
   // Emit the direct path.
-  IGF.Builder.emitBlock(directBB);
-  operation.emitForPacking(IGF, T, type, FixedPacking::OffsetZero);
-  IGF.Builder.CreateBr(contBB);
+  IGF.Builder.emitBlock(directBB); {
+    ConditionalDominanceScope condition(IGF);
+    operation.emitForPacking(IGF, T, type, FixedPacking::OffsetZero);
+    IGF.Builder.CreateBr(contBB);
+  }
 
   // Enter the continuation block and add the PHI if required.
   IGF.Builder.emitBlock(contBB);
@@ -973,6 +977,7 @@
     IGF.Builder.CreateCondBr(done, exit, loop);
 
     IGF.Builder.emitBlock(loop);
+    ConditionalDominanceScope condition(IGF);
     type.destroy(IGF, element, concreteType);
     auto nextCounter = IGF.Builder.CreateSub(counter,
                                      llvm::ConstantInt::get(IGM.SizeTy, 1));
@@ -2956,7 +2961,7 @@
 
         // Mark this as the cached metatype for the l-value's object type.
         CanType argTy = getArgTypeInContext(source.getParamIndex());
-        IGF.setUnscopedLocalTypeData(argTy, LocalTypeData::forMetatype(),
+        IGF.setUnscopedLocalTypeData(argTy, LocalTypeDataKind::forMetatype(),
                                      metatype);
         return metatype;
       }
@@ -2969,7 +2974,7 @@
         // Mark this as the cached metatype for Self.
         CanType argTy = getArgTypeInContext(FnType->getParameters().size() - 1);
         IGF.setUnscopedLocalTypeData(argTy,
-                                     LocalTypeData::forMetatype(), metatype);
+                                    LocalTypeDataKind::forMetatype(), metatype);
         return metatype;
       }
           
@@ -3260,7 +3265,7 @@
   EmitPolymorphicParameters(IGF, ntd).emitForGenericValueWitness(selfMeta);
   // Register the 'Self' argument as generic metadata for the type.
   IGF.setUnscopedLocalTypeData(ntd->getDeclaredTypeInContext()->getCanonicalType(),
-                               LocalTypeData::forMetatype(), selfMeta);
+                               LocalTypeDataKind::forMetatype(), selfMeta);
 }
 
 /// Get the next argument and use it as the 'self' type metadata.
@@ -3442,14 +3447,13 @@
 
     // Find the metatype for the appropriate archetype and store it in
     // the slot.
-    llvm::Value *metatype =
-      IGF.getLocalTypeData(CanType(archetype), LocalTypeData::forMetatype());
+    llvm::Value *metatype = IGF.getLocalTypeData(CanType(archetype),
+                                              LocalTypeDataKind::forMetatype());
     IGF.Builder.CreateStore(metatype, slot);
 
     // Find the witness tables for the archetype's protocol constraints and
     // store them in the slot.
-    for (unsigned protocolI : indices(archetype->getConformsTo())) {
-      auto protocol = archetype->getConformsTo()[protocolI];
+    for (auto protocol : archetype->getConformsTo()) {
       if (!Lowering::TypeConverter::protocolRequiresWitnessTable(protocol))
         continue;
       Address witnessSlot = IGF.Builder.CreateConstArrayGEP(buffer, metadataI,
@@ -3459,7 +3463,7 @@
       ++metadataI;
       llvm::Value *witness =
         IGF.getLocalTypeData(CanType(archetype),
-                         LocalTypeData::forArchetypeProtocolWitness(protocolI));
+                 LocalTypeDataKind::forArchetypeProtocolWitnessTable(protocol));
       IGF.Builder.CreateStore(witness, witnessSlot);
     }
   }
diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp
index 53ac36e..b97086b 100644
--- a/lib/IRGen/GenType.cpp
+++ b/lib/IRGen/GenType.cpp
@@ -50,6 +50,24 @@
   return t->hasTypeParameter() ? DependentCache : IndependentCache;
 }
 
+void TypeInfo:: assign(IRGenFunction &IGF, Address dest, Address src,
+                       IsTake_t isTake, SILType T) const {
+  if (isTake) {
+    assignWithTake(IGF, dest, src, T);
+  } else {
+    assignWithCopy(IGF, dest, src, T);
+  }
+}
+
+void TypeInfo::initialize(IRGenFunction &IGF, Address dest, Address src,
+                          IsTake_t isTake, SILType T) const {
+  if (isTake) {
+    initializeWithTake(IGF, dest, src, T);
+  } else {
+    initializeWithCopy(IGF, dest, src, T);
+  }
+}
+
 Address TypeInfo::initializeBufferWithTake(IRGenFunction &IGF,
                                            Address destBuffer,
                                            Address srcAddr,
@@ -152,12 +170,14 @@
   auto elementVal = IGF.Builder.CreatePHI(array.getType(), 2);
   elementVal->addIncoming(array.getAddress(), entry);
   Address element(elementVal, array.getAlignment());
-  
+ 
   auto done = IGF.Builder.CreateICmpEQ(counter,
                                      llvm::ConstantInt::get(IGF.IGM.SizeTy, 0));
   IGF.Builder.CreateCondBr(done, exit, loop);
   
   IGF.Builder.emitBlock(loop);
+  ConditionalDominanceScope condition(IGF);
+
   destroy(IGF, element, T);
   auto nextCounter = IGF.Builder.CreateSub(counter,
                                    llvm::ConstantInt::get(IGF.IGM.SizeTy, 1));
@@ -196,16 +216,14 @@
   srcVal->addIncoming(srcArray.getAddress(), entry);
   Address dest(destVal, destArray.getAlignment());
   Address src(srcVal, srcArray.getAlignment());
-  
+
   auto done = IGF.Builder.CreateICmpEQ(counter,
                                        llvm::ConstantInt::get(IGM.SizeTy, 0));
   IGF.Builder.CreateCondBr(done, exit, loop);
   
   IGF.Builder.emitBlock(loop);
-  if (take)
-    type.initializeWithTake(IGF, dest, src, T);
-  else
-    type.initializeWithCopy(IGF, dest, src, T);
+  ConditionalDominanceScope condition(IGF);
+  type.initialize(IGF, dest, src, take, T);
 
   auto nextCounter = IGF.Builder.CreateSub(counter,
                                    llvm::ConstantInt::get(IGM.SizeTy, 1));
@@ -250,21 +268,19 @@
   srcVal->addIncoming(srcEnd.getAddress(), entry);
   Address dest(destVal, destArray.getAlignment());
   Address src(srcVal, srcArray.getAlignment());
-  
+
   auto done = IGF.Builder.CreateICmpEQ(counter,
                                        llvm::ConstantInt::get(IGM.SizeTy, 0));
   IGF.Builder.CreateCondBr(done, exit, loop);
   
   IGF.Builder.emitBlock(loop);
+  ConditionalDominanceScope condition(IGF);
   auto prevDest = type.indexArray(IGF, dest,
                               llvm::ConstantInt::getSigned(IGM.SizeTy, -1), T);
   auto prevSrc = type.indexArray(IGF, src,
                               llvm::ConstantInt::getSigned(IGM.SizeTy, -1), T);
   
-  if (take)
-    type.initializeWithTake(IGF, prevDest, prevSrc, T);
-  else
-    type.initializeWithCopy(IGF, prevDest, prevSrc, T);
+  type.initialize(IGF, prevDest, prevSrc, take, T);
   
   auto nextCounter = IGF.Builder.CreateSub(counter,
                                    llvm::ConstantInt::get(IGM.SizeTy, 1));
@@ -536,6 +552,7 @@
   IGF.Builder.CreateCondBr(isValid, endBB, spareBB);
 
   IGF.Builder.emitBlock(spareBB);
+  ConditionalDominanceScope condition(IGF);
   
   // Gather the occupied bits.
   auto OccupiedBits = SpareBits;
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index faddcf5..f041be7 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -1,4 +1,4 @@
-//===--- IRGenDebugInfo.cpp - Debug Info Support---------------------------===//
+//===--- IRGenDebugInfo.cpp - Debug Info Support --------------------------===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/IRGen/IRGenDebugInfo.h b/lib/IRGen/IRGenDebugInfo.h
index 0324eb0..177b85a 100644
--- a/lib/IRGen/IRGenDebugInfo.h
+++ b/lib/IRGen/IRGenDebugInfo.h
@@ -1,4 +1,4 @@
-//===--- IRGenDebugInfo.h - Debug Info Support-------------------*- C++ -*-===//
+//===--- IRGenDebugInfo.h - Debug Info Support ------------------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index d96f7f0..d919764 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -52,8 +52,12 @@
 
 IRGenFunction::~IRGenFunction() {
   emitEpilogue();
+
   // Restore the debug location.
   if (IGM.DebugInfo) IGM.DebugInfo->popLoc();
+
+  // Tear down any side-table data structures.
+  if (LocalTypeData) destroyLocalTypeData();
 }
 
 /// Call the llvm.memcpy intrinsic.  The arguments need not already
@@ -212,40 +216,6 @@
   }
 }
 
-llvm::Value *IRGenFunction::lookupTypeDataMap(CanType type, LocalTypeData index,
-                                              const TypeDataMap &scopedMap) {
-  
-  // First try to lookup in the unscoped cache (= definitions in the entry block
-  // of the function).
-  auto key = getLocalTypeDataKey(type, index);
-  auto it = LocalTypeDataMap.find(key);
-  if (it != LocalTypeDataMap.end())
-    return it->second;
-  
-  // Now try to lookup in the scoped cache.
-  auto it2 = scopedMap.find(key);
-  if (it2 == scopedMap.end())
-    return nullptr;
-  
-  if (auto *I = dyn_cast<llvm::Instruction>(it2->second)) {
-    // This is a very very simple dominance check: either the definition is in the
-    // entry block or in the current block.
-    // TODO: do a better dominance check.
-    if (I->getParent() == &CurFn->getEntryBlock() ||
-        I->getParent() == Builder.GetInsertBlock()) {
-      return I;
-    }
-    return nullptr;
-  }
-  
-  if (isa<llvm::Constant>(it2->second)) {
-    return it2->second;
-  }
-  
-  // TODO: other kinds of value?
-  return nullptr;
-}
-
 void IRGenFunction::unimplemented(SourceLoc Loc, StringRef Message) {
   return IGM.unimplemented(Loc, Message);
 }
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index 5fe1903..5ba09d5 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -25,7 +25,8 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/IR/CallingConv.h"
 #include "IRBuilder.h"
-
+#include "LocalTypeDataKind.h"
+#include "DominancePoint.h"
 
 namespace llvm {
   class AllocaInst;
@@ -60,53 +61,12 @@
   class HeapNonFixedOffsets;
   class IRGenModule;
   class LinkEntity;
+  class LocalTypeDataCache;
   class Scope;
   class TypeInfo;
   enum class ValueWitness : unsigned;
   enum class ReferenceCounting : unsigned char;
 
-/// A nonce value for storing some sort of locally-known information about a type.
-class LocalTypeData {
-  unsigned Value;
-  
-  explicit LocalTypeData(unsigned Value) : Value(Value) {}
-  
-  /// Magic values for special kinds of index.
-  enum : unsigned {
-    Metatype = ~0U,
-    ValueWitnessTable = ~1U,
-
-    ValueWitnessBase = 0xFFFFFF00U,
-  };
-  
-public:
-  LocalTypeData() = default;
-  
-  // The magic values are all in the "negative" range and so do
-  // not collide with reasonable index values.
-  
-  /// A reference to the type metadata.
-  static LocalTypeData forMetatype() { return LocalTypeData(Metatype); }
-  /// A reference to the value witness table.
-  static LocalTypeData forValueWitnessTable() {
-    return LocalTypeData(ValueWitnessTable);
-  }
-
-  /// A reference to a specific value witness.
-  static LocalTypeData forValueWitness(ValueWitness witness) {
-    return LocalTypeData((unsigned)witness + ValueWitnessBase);
-  }
-  
-  /// A reference to a protocol witness table for an archetype.
-  static LocalTypeData forArchetypeProtocolWitness(unsigned index) {
-    return LocalTypeData(index);
-  }
-  
-  unsigned getValue() const {
-    return Value;
-  }
-};
-
 /// IRGenFunction - Primary class for emitting LLVM instructions for a
 /// specific function.
 class IRGenFunction {
@@ -404,54 +364,127 @@
   /// Look for a mapping for a local type-metadata reference.
   /// The lookup is done for the current block which is the Builder's
   /// insert-block.
-  llvm::Value *tryGetLocalTypeData(CanType type, LocalTypeData index) {
-    return lookupTypeDataMap(type, index, ScopedTypeDataMap);
-  }
-
-  /// The same as tryGetLocalTypeData, just for the Layout metadata.
-  llvm::Value *tryGetLocalTypeDataForLayout(SILType type, LocalTypeData index) {
-    return lookupTypeDataMap(type.getSwiftRValueType(), index,
-                             ScopedTypeDataMapForLayout);
-  }
+  llvm::Value *tryGetLocalTypeData(CanType type, LocalTypeDataKind kind);
 
   /// Retrieve a local type-metadata reference which is known to exist.
-  llvm::Value *getLocalTypeData(CanType type, LocalTypeData index) {
-    auto key = getLocalTypeDataKey(type, index);
-    assert(LocalTypeDataMap.count(key) && "no mapping for local type data");
-    return LocalTypeDataMap.find(key)->second;
-  }
+  llvm::Value *getLocalTypeData(CanType type, LocalTypeDataKind kind);
 
-  /// Add a local type-metadata reference at a point which dominates
-  /// the entire function.
-  void setUnscopedLocalTypeData(CanType type, LocalTypeData index,
-                                llvm::Value *data) {
-    assert(data && "setting a null value for type data!");
-
-    auto key = getLocalTypeDataKey(type, index);
-    assert(!LocalTypeDataMap.count(key) &&
-           "existing mapping for local type data");
-    LocalTypeDataMap.insert({key, data});
-  }
+  /// Add a local type-metadata reference at a point which definitely
+  /// dominates all of its uses.
+  void setUnscopedLocalTypeData(CanType type, LocalTypeDataKind kind,
+                                llvm::Value *data);
   
-  /// Add a local type-metadata reference, which is valid for the containing
-  /// block.
-  void setScopedLocalTypeData(CanType type, LocalTypeData index,
-                              llvm::Value *data) {
-    assert(_isValidScopedLocalTypeData(data) &&
-           "metadata instruction not inserted into the Builder's insert-block");
-    ScopedTypeDataMap[getLocalTypeDataKey(type, index)] = data;
+  /// Add a local type-metadata reference, valid at the current insertion
+  /// point.
+  void setScopedLocalTypeData(CanType type, LocalTypeDataKind kind,
+                              llvm::Value *data);
+
+  /// The same as tryGetLocalTypeData, just for the Layout metadata.
+  ///
+  /// We use a separate function name for this to clarify that you should
+  /// only ever be looking type metadata for a lowered SILType for the
+  /// purposes of local layout (e.g. of a tuple).
+  llvm::Value *tryGetLocalTypeDataForLayout(SILType type,
+                                            LocalTypeDataKind kind) {
+    return tryGetLocalTypeData(type.getSwiftRValueType(), kind);
   }
 
   /// Add a local type-metadata reference, which is valid for the containing
   /// block.
-  void setScopedLocalTypeDataForLayout(SILType type, LocalTypeData index,
+  void setScopedLocalTypeDataForLayout(SILType type, LocalTypeDataKind kind,
                                        llvm::Value *data) {
-    assert(_isValidScopedLocalTypeData(data) &&
-           "metadata instruction not inserted into the Builder's insert-block");
-    ScopedTypeDataMapForLayout[
-                  getLocalTypeDataKey(type.getSwiftRValueType(), index)] = data;
+    setScopedLocalTypeData(type.getSwiftRValueType(), kind, data);
   }
 
+  void setDominanceResolver(DominanceResolverFunction resolver) {
+    assert(DominanceResolver == nullptr);
+    DominanceResolver = resolver;
+  }
+
+  bool isActiveDominancePointDominatedBy(DominancePoint point) {
+    // If the point is universal, it dominates.
+    if (point.isUniversal()) return true;
+
+    assert(!ActiveDominancePoint.isUniversal() &&
+           "active dominance point is universal but there exists a"
+           "non-universal point?");
+
+    // If we don't have a resolver, we're emitting a simple helper
+    // function; just assume dominance.
+    if (!DominanceResolver) return true;
+
+    // Otherwise, ask the resolver.
+    return DominanceResolver(*this, ActiveDominancePoint, point);
+  }
+
+  /// Is the current dominance point conditional in some way not
+  /// tracked by the active dominance point?
+  ///
+  /// This should only be used by the local type data cache code.
+  bool isConditionalDominancePoint() const {
+    return ConditionalDominance != nullptr;
+  }
+
+  void registerConditionalLocalTypeDataKey(LocalTypeDataKey key) {
+    assert(ConditionalDominance != nullptr &&
+           "not in a conditional dominance scope");
+    ConditionalDominance->registerConditionalLocalTypeDataKey(key);
+  }
+
+  /// Return the currently-active dominance point.
+  DominancePoint getActiveDominancePoint() const {
+    return ActiveDominancePoint;
+  }
+
+  /// A RAII object for temporarily changing the dominance of the active
+  /// definition point.
+  class DominanceScope {
+    IRGenFunction &IGF;
+    DominancePoint OldDominancePoint;
+  public:
+    explicit DominanceScope(IRGenFunction &IGF, DominancePoint newPoint)
+        : IGF(IGF), OldDominancePoint(IGF.ActiveDominancePoint) {
+      IGF.ActiveDominancePoint = newPoint;
+      assert(!newPoint.isOrdinary() || IGF.DominanceResolver);
+    }
+
+    DominanceScope(const DominanceScope &other) = delete;
+    DominanceScope &operator=(const DominanceScope &other) = delete;
+
+    ~DominanceScope() {
+      IGF.ActiveDominancePoint = OldDominancePoint;
+    }
+  };
+
+  /// A RAII object for temporarily suppressing type-data caching at the
+  /// active definition point.  Do this if you're adding local control flow
+  /// that isn't modeled by the dominance system.
+  class ConditionalDominanceScope {
+    IRGenFunction &IGF;
+    ConditionalDominanceScope *OldScope;
+    SmallVector<LocalTypeDataKey, 2> RegisteredKeys;
+  public:
+    explicit ConditionalDominanceScope(IRGenFunction &IGF)
+        : IGF(IGF), OldScope(IGF.ConditionalDominance) {
+      IGF.ConditionalDominance = this;
+    }
+
+    ConditionalDominanceScope(const ConditionalDominanceScope &other) = delete;
+    ConditionalDominanceScope &operator=(const ConditionalDominanceScope &other)
+      = delete;
+
+    void registerConditionalLocalTypeDataKey(LocalTypeDataKey key) {
+      RegisteredKeys.push_back(key);
+    }
+
+    ~ConditionalDominanceScope() {
+      IGF.ConditionalDominance = OldScope;
+      if (!RegisteredKeys.empty()) {
+        IGF.unregisterConditionalLocalTypeDataKeys(RegisteredKeys);
+      }
+    }
+  };
+
   /// The kind of value LocalSelf is.
   enum LocalSelfKind {
     /// An object reference.
@@ -466,35 +499,17 @@
   void setLocalSelfMetadata(llvm::Value *value, LocalSelfKind kind);
   
 private:
-#ifndef NDEBUG
-  bool _isValidScopedLocalTypeData(llvm::Value *v) {
-    // Constants are valid anywhere.
-    if (isa<llvm::Constant>(v))
-      return true;
-    // Instructions are valid only in the current insert block.
-    if (auto inst = dyn_cast<llvm::Instruction>(v))
-      return inst->getParent() == Builder.GetInsertBlock();
-    // TODO: Other kinds of value?
-    return false;
-  }
-#endif
+  LocalTypeDataCache &getOrCreateLocalTypeData();
+  void destroyLocalTypeData();
+  void unregisterConditionalLocalTypeDataKeys(ArrayRef<LocalTypeDataKey> keys);
 
-  typedef unsigned LocalTypeDataDepth;
-  typedef std::pair<TypeBase*,unsigned> LocalTypeDataPair;
-  LocalTypeDataPair getLocalTypeDataKey(CanType type, LocalTypeData index) {
-    return LocalTypeDataPair(type.getPointer(), index.getValue());
-  }
+  LocalTypeDataCache *LocalTypeData = nullptr;
 
-  typedef llvm::DenseMap<LocalTypeDataPair, llvm::Value*> TypeDataMap;
-
-  llvm::Value *lookupTypeDataMap(CanType type, LocalTypeData index,
-                                 const TypeDataMap &scopedMap);
-
-  TypeDataMap LocalTypeDataMap;
-
-  TypeDataMap ScopedTypeDataMap;
-
-  TypeDataMap ScopedTypeDataMapForLayout;
+  /// The dominance resolver.  This can be set at most once; when it's not
+  /// set, this emission must never have a non-null active definition point.
+  DominanceResolverFunction DominanceResolver = nullptr;
+  DominancePoint ActiveDominancePoint = DominancePoint::universal();
+  ConditionalDominanceScope *ConditionalDominance = nullptr;
   
   /// The value that satisfies metadata lookups for dynamic Self.
   llvm::Value *LocalSelf = nullptr;
@@ -502,6 +517,8 @@
   LocalSelfKind SelfKind;
 };
 
+using ConditionalDominanceScope = IRGenFunction::ConditionalDominanceScope;
+
 } // end namespace irgen
 } // end namespace swift
 
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index e00a8b7..df74ad8 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -33,6 +33,7 @@
 #include "swift/AST/Pattern.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/Types.h"
+#include "swift/SIL/Dominance.h"
 #include "swift/SIL/PrettyStackTrace.h"
 #include "swift/SIL/SILDebugScope.h"
 #include "swift/SIL/SILDeclRef.h"
@@ -312,6 +313,9 @@
 
   SILFunction *CurSILFn;
   Address IndirectReturn;
+
+  // A cached dominance analysis.
+  std::unique_ptr<DominanceInfo> Dominance;
   
   IRGenSILFunction(IRGenModule &IGM, SILFunction *f);
   ~IRGenSILFunction();
@@ -1286,6 +1290,20 @@
         CurSILFn->print(llvm::dbgs()));
   
   assert(!CurSILFn->empty() && "function has no basic blocks?!");
+
+  // Configure the dominance resolver.
+  // TODO: consider re-using a dom analysis from the PassManager
+  // TODO: consider using a cheaper analysis at -O0
+  setDominanceResolver([](IRGenFunction &IGF_,
+                          DominancePoint activePoint,
+                          DominancePoint dominatingPoint) -> bool {
+    IRGenSILFunction &IGF = static_cast<IRGenSILFunction&>(IGF_);
+    if (!IGF.Dominance) {
+      IGF.Dominance.reset(new DominanceInfo(IGF.CurSILFn));
+    }
+    return IGF.Dominance->dominates(dominatingPoint.as<SILBasicBlock>(),
+                                    activePoint.as<SILBasicBlock>());
+  });
   
   // FIXME: Or if this is a witness. DebugInfo doesn't have an interface to
   // correctly handle the generic parameters of a witness, which can come from
@@ -1324,7 +1342,7 @@
     break;
   }
   emitLocalSelfMetadata(*this);
-  
+
   assert(params.empty() && "did not map all llvm params to SIL params?!");
 
   // It's really nice to be able to assume that we've already emitted
@@ -1454,6 +1472,11 @@
   bool InEntryBlock = BB->pred_empty();
   bool ArgsEmitted = false;
 
+  // Set this block as the dominance point.  This implicitly communicates
+  // with the dominance resolver configured in emitSILFunction.
+  DominanceScope dominance(*this, InEntryBlock ? DominancePoint::universal()
+                                               : DominancePoint(BB));
+
   // The basic blocks are visited in a random order. Reset the debug location.
   std::unique_ptr<AutoRestoreLocation> ScopedLoc;
   if (InEntryBlock)
diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp
new file mode 100644
index 0000000..f7ccd69
--- /dev/null
+++ b/lib/IRGen/LocalTypeData.cpp
@@ -0,0 +1,303 @@
+//===--- LocalTypeData.cpp - Local type data search -----------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements routines for finding and caching local type data
+//  for a search.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LocalTypeData.h"
+#include "Fulfillment.h"
+#include "IRGenFunction.h"
+#include "IRGenModule.h"
+#include "swift/SIL/SILModule.h"
+
+using namespace swift;
+using namespace irgen;
+
+LocalTypeDataCache &IRGenFunction::getOrCreateLocalTypeData() {
+  // Lazily allocate it.
+  if (LocalTypeData) return *LocalTypeData;
+  LocalTypeData = new LocalTypeDataCache();
+  return *LocalTypeData;
+}
+
+void IRGenFunction::destroyLocalTypeData() {
+  delete LocalTypeData;
+}
+
+unsigned LocalTypeDataCache::CacheEntry::cost() const {
+  switch (getKind()) {
+  case Kind::Concrete:
+    return static_cast<const ConcreteCacheEntry*>(this)->cost();
+  case Kind::Abstract:
+    return static_cast<const AbstractCacheEntry*>(this)->cost();
+  }
+  llvm_unreachable("bad cache entry kind");
+}
+
+void LocalTypeDataCache::CacheEntry::erase() const {
+  switch (getKind()) {
+  case Kind::Concrete:
+    delete static_cast<const ConcreteCacheEntry*>(this);
+    return;
+  case Kind::Abstract:
+    delete static_cast<const AbstractCacheEntry*>(this);
+    return;
+  }
+  llvm_unreachable("bad cache entry kind");
+}
+
+llvm::Value *IRGenFunction::getLocalTypeData(CanType type,
+                                             LocalTypeDataKind kind) {
+  assert(LocalTypeData);
+  return LocalTypeData->get(*this, LocalTypeDataCache::getKey(type, kind));
+}
+
+llvm::Value *IRGenFunction::tryGetLocalTypeData(CanType type,
+                                                LocalTypeDataKind kind) {
+  if (!LocalTypeData) return nullptr;
+  return LocalTypeData->tryGet(*this, LocalTypeDataCache::getKey(type, kind));
+}
+
+llvm::Value *LocalTypeDataCache::tryGet(IRGenFunction &IGF, Key key) {
+  auto it = Map.find(key);
+  if (it == Map.end()) return nullptr;
+  auto &chain = it->second;
+
+  CacheEntry *best = nullptr, *bestPrev = nullptr;
+  Optional<unsigned> bestCost;
+
+  CacheEntry *next = chain.Root, *nextPrev = nullptr;
+  do {
+    assert(next);
+    CacheEntry *cur = next, *curPrev = nextPrev;
+    nextPrev = cur;
+    next = cur->getNext();
+
+    // Ignore unacceptable entries.
+    if (!IGF.isActiveDominancePointDominatedBy(cur->DefinitionPoint))
+      continue;
+
+    // If there's a collision, compare by cost, ignoring higher-cost entries.
+    if (best) {
+      // Compute the cost of the best entry if we haven't done so already.
+      // If that's zero, go ahead and short-circuit out.
+      if (!bestCost) {
+        bestCost = best->cost();
+        if (*bestCost == 0) break;
+      }
+
+      auto curCost = cur->cost();
+      if (curCost >= *bestCost) continue;
+
+      // Replace the best cost and fall through.
+      bestCost = curCost;
+    }
+    best = cur;
+    bestPrev = curPrev;
+  } while (next);
+
+  // If we didn't find anything, we're done.
+  if (!best) return nullptr;
+
+  // Okay, we've found the best entry available.
+  switch (best->getKind()) {
+
+  // For concrete caches, this is easy.
+  case CacheEntry::Kind::Concrete:
+    return static_cast<ConcreteCacheEntry*>(best)->Value;
+
+  // For abstract caches, we need to follow a path.
+  case CacheEntry::Kind::Abstract: {
+    auto entry = static_cast<AbstractCacheEntry*>(best);
+
+    // Follow the path.
+    auto &source = AbstractSources[entry->SourceIndex];
+    auto result = entry->follow(IGF, source);
+
+    // Make a new concrete entry at the active definition point.
+    auto newEntry =
+      new ConcreteCacheEntry(IGF.getActiveDominancePoint(),
+                             IGF.isConditionalDominancePoint(), result);
+
+    // If the active definition point is the same as the old entry's
+    // definition point, delete the old entry.
+    if (best->DefinitionPoint == IGF.getActiveDominancePoint() &&
+        !best->isConditional()) {
+      chain.eraseEntry(bestPrev, best);
+    }
+
+    // Add the new entry to the front of the chain.
+    chain.push_front(newEntry);
+
+    return result;
+  }
+
+  }
+  llvm_unreachable("bad cache entry kind");
+}
+
+llvm::Value *
+LocalTypeDataCache::AbstractCacheEntry::follow(IRGenFunction &IGF,
+                                               AbstractSource &source) const {
+  switch (source.getKind()) {
+  case AbstractSource::Kind::TypeMetadata:
+    return Path.followFromTypeMetadata(IGF, source.getType(),
+                                       source.getValue(), &source.getCache());  
+
+  case AbstractSource::Kind::WitnessTable:
+    return Path.followFromWitnessTable(IGF, source.getProtocol(),
+                                       source.getValue(), &source.getCache());  
+  }
+  llvm_unreachable("bad source kind");
+}
+
+void IRGenFunction::setScopedLocalTypeData(CanType type, LocalTypeDataKind kind,
+                                           llvm::Value *data) {
+  if (isConditionalDominancePoint())
+    return;
+
+  getOrCreateLocalTypeData().addConcrete(getActiveDominancePoint(),
+                                         isConditionalDominancePoint(),
+                                         LocalTypeDataCache::getKey(type, kind),
+                                         data);
+}
+
+void IRGenFunction::setUnscopedLocalTypeData(CanType type,
+                                             LocalTypeDataKind kind,
+                                             llvm::Value *data) {
+  getOrCreateLocalTypeData()
+    .addConcrete(DominancePoint::universal(), /*conditional*/ false,
+                 LocalTypeDataCache::getKey(type, kind), data);
+}
+
+void LocalTypeDataCache::addAbstractForTypeMetadata(IRGenFunction &IGF,
+                                                    CanType type,
+                                                    llvm::Value *metadata) {
+  // Don't bother doing this at a conditional dominance point; we're too
+  // likely to throw it all away.
+  if (IGF.isConditionalDominancePoint())
+    return;
+
+  // Look for anything at all that's fulfilled by this.  If we don't find
+  // anything, stop.
+  FulfillmentMap fulfillments;
+  if (!fulfillments.searchTypeMetadata(*IGF.IGM.SILMod->getSwiftModule(),
+                                       type, FulfillmentMap::IsExact,
+                                       /*source*/ 0, MetadataPath(),
+                                       FulfillmentMap::Everything())) {
+    return;
+  }
+
+  addAbstractForFullfillments(IGF, std::move(fulfillments),
+                              [&]() -> AbstractSource {
+    return AbstractSource(AbstractSource::Kind::TypeMetadata, type, metadata);
+  });
+}
+
+void LocalTypeDataCache::
+addAbstractForFullfillments(IRGenFunction &IGF, FulfillmentMap &&fulfillments,
+                            llvm::function_ref<AbstractSource()> createSource) {
+  // Add the source lazily.
+  Optional<unsigned> sourceIndex;
+  auto getSourceIndex = [&]() -> unsigned {
+    if (!sourceIndex) {
+      AbstractSources.emplace_back(createSource());
+      sourceIndex = AbstractSources.size() - 1;
+    }
+    return *sourceIndex;
+  };
+
+  for (auto &fulfillment : fulfillments) {
+    CanType type = CanType(fulfillment.first.first);
+    LocalTypeDataKind localDataKind;
+
+    // For now, ignore witness-table fulfillments when they're not for
+    // archetypes.
+    if (ProtocolDecl *protocol = fulfillment.first.second) {
+      if (auto archetype = dyn_cast<ArchetypeType>(type)) {
+        auto conformsTo = archetype->getConformsTo();
+        auto it = std::find(conformsTo.begin(), conformsTo.end(), protocol);
+        if (it == conformsTo.end()) continue;
+        localDataKind =LocalTypeDataKind::forArchetypeProtocolWitnessTable(*it);
+      } else {
+        continue;
+      }
+    } else {
+      localDataKind = LocalTypeDataKind::forMetatype();
+    }
+
+    // Find the chain for the key.
+    auto key = getKey(type, localDataKind);
+    auto &chain = Map[key];
+
+    // Check whether there's already an entr that's at least as good as the
+    // fulfillment.
+    Optional<unsigned> fulfillmentCost;
+    auto getFulfillmentCost = [&]() -> unsigned {
+      if (!fulfillmentCost)
+        fulfillmentCost = fulfillment.second.Path.cost();
+      return *fulfillmentCost;
+    };
+
+    bool foundBetter = false;
+    for (CacheEntry *cur = chain.Root, *last = nullptr; cur;
+         last = cur, cur = cur->getNext()) {
+      // Ensure the entry is acceptable.
+      if (!IGF.isActiveDominancePointDominatedBy(cur->DefinitionPoint))
+        continue;
+
+      // Ensure that the entry isn't better than the fulfillment.
+      auto curCost = cur->cost();
+      if (curCost == 0 || curCost <= getFulfillmentCost()) {
+        foundBetter = true;
+        break;
+      }
+
+      // If the entry is defined at the current point, (1) we know there
+      // won't be a better entry and (2) we should remove it.
+      if (cur->DefinitionPoint == IGF.getActiveDominancePoint() &&
+          !cur->isConditional()) {
+        // Splice it out of the chain.
+        chain.eraseEntry(last, cur);
+        break;
+      }
+    }
+    if (foundBetter) continue;
+
+    // Okay, make a new entry.
+    auto newEntry = new AbstractCacheEntry(IGF.getActiveDominancePoint(),
+                                           IGF.isConditionalDominancePoint(),
+                                           getSourceIndex(),
+                                           std::move(fulfillment.second.Path));
+
+    // Add it to the front of the chain.
+    chain.push_front(newEntry);
+  }
+}
+
+void IRGenFunction::unregisterConditionalLocalTypeDataKeys(
+                                             ArrayRef<LocalTypeDataKey> keys) {
+  assert(!keys.empty());
+  assert(LocalTypeData);
+  LocalTypeData->eraseConditional(keys);
+}
+
+void LocalTypeDataCache::eraseConditional(ArrayRef<LocalTypeDataKey> keys) {
+  for (auto &key : keys) {
+    auto &chain = Map[key];
+    assert(chain.Root);
+    assert(chain.Root->isConditional());
+    chain.eraseEntry(nullptr, chain.Root);
+  }
+}
diff --git a/lib/IRGen/LocalTypeData.h b/lib/IRGen/LocalTypeData.h
new file mode 100644
index 0000000..9c478b9
--- /dev/null
+++ b/lib/IRGen/LocalTypeData.h
@@ -0,0 +1,264 @@
+//===--- LocalTypeData.h - Dominance-scoped type data -------------*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines types relating to the local caching of type data,
+//  such as type metadata, value witness tables, and protocol witness tables.
+//
+//  Type data may be cached concretely, meaning that it was already fully
+//  computed, or abstractly, meaning that we remember how to recreate it
+//  but haven't actually done so yet.
+//
+//  Type data may be cached at different points within a function.
+//  Some of these points may not dominate all possible use sites.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_LOCALTYPEDATA_H
+#define SWIFT_IRGEN_LOCALTYPEDATA_H
+
+#include "LocalTypeDataKind.h"
+#include "DominancePoint.h"
+#include "MetadataPath.h"
+#include "swift/AST/Type.h"
+#include "llvm/ADT/STLExtras.h"
+#include <utility>
+
+namespace swift {
+  class TypeBase;
+
+namespace irgen {
+  class FulfillmentMap;
+
+/// A cache of local type data.
+///
+/// Basic design considerations:
+///
+///   - We want to be able to efficiently look up a key and find something.
+///     Generally this will find something from the entry block.  We shouldn't
+///     have to scan all the dominating points first.
+///
+///   - We don't expect to have multiple definitions for a key very often.
+///     Therefore, given a collision, it should be okay to scan a list and
+///     ask whether each is acceptable.
+class LocalTypeDataCache {
+public:
+  using Key = LocalTypeDataKey;
+
+  static Key getKey(CanType type, LocalTypeDataKind index) {
+    return { type, index };
+  }
+
+private:
+  struct CacheEntry {
+    enum class Kind {
+      Concrete, Abstract
+    };
+
+    DominancePoint DefinitionPoint;
+
+  private:
+    enum { KindMask = 0x1, ConditionalMask = 0x2 };
+    llvm::PointerIntPair<CacheEntry*, 2, unsigned> NextAndFlags;
+
+  public:
+    Kind getKind() const {
+      return Kind(NextAndFlags.getInt() & KindMask);
+    }
+    CacheEntry *getNext() const { return NextAndFlags.getPointer(); }
+    void setNext(CacheEntry *next) { NextAndFlags.setPointer(next); }
+
+    /// Return the abstract cost of evaluating this cache entry.
+    unsigned cost() const;
+
+    /// Destruct and deallocate this cache entry.
+    void erase() const;
+
+    bool isConditional() const {
+      return NextAndFlags.getInt() & ConditionalMask;
+    }
+
+  protected:
+    CacheEntry(Kind kind, DominancePoint point, bool isConditional)
+        : DefinitionPoint(point),
+          NextAndFlags(nullptr,
+                       unsigned(kind) | (isConditional ? ConditionalMask : 0)) {
+    }
+    ~CacheEntry() = default;
+  };
+
+  /// A concrete entry in the cache, which directly stores the desired value.
+  struct ConcreteCacheEntry : CacheEntry {
+    llvm::Value *Value;
+
+    ConcreteCacheEntry(DominancePoint point, bool isConditional,
+                       llvm::Value *value)
+      : CacheEntry(Kind::Concrete, point, isConditional), Value(value) {}
+
+    unsigned cost() const { return 0; }
+  };
+
+  /// A source of concrete data from which abstract cache entries can be
+  /// derived.
+  class AbstractSource {
+  public:
+    enum class Kind {
+      /// Type metadata.  The payload is a CanType.
+      TypeMetadata,
+
+      /// A protocol witness table.  The payload is a ProtocolDecl*.
+      WitnessTable,
+    };
+
+  private:
+    uintptr_t Payload;
+    MetadataPath::Map<llvm::Value*> Cache;
+    llvm::Value *Value;
+
+    enum : uintptr_t { KindMask = 0x3 };
+
+    explicit AbstractSource(Kind kind, void *ptr, llvm::Value *value)
+      : Payload(uintptr_t(ptr) | unsigned(kind)), Value(value) {}
+
+  public:
+    explicit AbstractSource(Kind kind, CanType type, llvm::Value *metadata)
+      : AbstractSource(kind, type.getPointer(), metadata) {}
+    explicit AbstractSource(Kind kind, ProtocolDecl *protocol,
+                            llvm::Value *witnessTable)
+      : AbstractSource(kind, (void*) protocol, witnessTable) {}
+
+    Kind getKind() const {
+      return Kind(Payload & KindMask);
+    }
+
+    CanType getType() const {
+      assert(getKind() == Kind::TypeMetadata);
+      return CanType(reinterpret_cast<TypeBase*>(Payload & ~KindMask));
+    }
+    ProtocolDecl *getProtocol() const {
+      assert(getKind() == Kind::WitnessTable);
+      return reinterpret_cast<ProtocolDecl*>(Payload & ~KindMask);
+    }
+
+    llvm::Value *getValue() const {
+      return Value;
+    }
+
+    MetadataPath::Map<llvm::Value*> &getCache() {
+      return Cache;
+    }
+  };
+
+  /// An abstract entry in the cache, which requires some amount of
+  /// non-trivial evaluation to derive the desired value.
+  struct AbstractCacheEntry : CacheEntry {
+    unsigned SourceIndex;
+    MetadataPath Path;
+
+    AbstractCacheEntry(DominancePoint point, bool isConditional,
+                       unsigned sourceIndex, MetadataPath &&path)
+      : CacheEntry(Kind::Abstract, point, isConditional),
+        SourceIndex(sourceIndex), Path(std::move(path)) {}
+
+    llvm::Value *follow(IRGenFunction &IGF, AbstractSource &source) const;
+
+    unsigned cost() const { return Path.cost(); }
+  };
+
+  /// The linked list of cache entries corresponding to a particular key.
+  struct CacheEntryChain {
+    CacheEntry *Root;
+
+    explicit CacheEntryChain(CacheEntry *root = nullptr) : Root(root) {}
+
+    CacheEntryChain(const CacheEntryChain &other) = delete;
+    CacheEntryChain &operator=(const CacheEntryChain &other) = delete;
+
+    CacheEntryChain(CacheEntryChain &&other) : Root(other.Root) {
+      other.Root = nullptr;
+    }
+    CacheEntryChain &operator=(CacheEntryChain &&other) {
+      Root = other.Root;
+      other.Root = nullptr;
+      return *this;
+    }
+
+    void push_front(CacheEntry *entry) {
+      entry->setNext(Root);
+      Root = entry;
+    }
+
+    void eraseEntry(CacheEntry *prev, CacheEntry *entry) {
+      if (prev) {
+        assert(prev->getNext() == entry);
+        prev->setNext(entry->getNext());
+      } else {
+        assert(Root == entry);
+        Root = entry->getNext();
+      }
+      entry->erase();
+    }
+
+    /// Delete the linked list.
+    ~CacheEntryChain() {
+      auto next = Root;
+      while (next) {
+        auto cur = next;
+        next = cur->getNext();
+        cur->erase();
+      }
+    }
+  };
+
+  llvm::DenseMap<Key, CacheEntryChain> Map;
+
+  std::vector<AbstractSource> AbstractSources;
+
+  void addAbstractForFullfillments(IRGenFunction &IGF,
+                                   FulfillmentMap &&fulfillments,
+                            llvm::function_ref<AbstractSource()> createSource);
+
+
+public:
+  LocalTypeDataCache() = default;
+  LocalTypeDataCache(const LocalTypeDataCache &other) = delete;
+  LocalTypeDataCache &operator=(const LocalTypeDataCache &other) = delete;
+
+  /// Load the value from cache if possible.  This may require emitting
+  /// code if the value is cached abstractly.
+  llvm::Value *tryGet(IRGenFunction &IGF, Key key);
+
+  /// Load the value from cache, asserting its presence.
+  llvm::Value *get(IRGenFunction &IGF, Key key) {
+    auto result = tryGet(IGF, key);
+    assert(result && "get() on unmapped entry?");
+    return result;
+  }
+
+  /// Add a new concrete entry to the cache at the given definition point.
+  void addConcrete(DominancePoint point, bool isConditional,
+                   Key key, llvm::Value *value) {
+    auto newEntry = new ConcreteCacheEntry(point, isConditional, value);
+    Map[key].push_front(newEntry);
+  }
+
+  /// Add abstract entries based on what can be fulfilled from the given
+  /// type metadata.
+  void addAbstractForTypeMetadata(IRGenFunction &IGF, CanType type,
+                                  llvm::Value *metadata);
+
+  void eraseConditional(ArrayRef<LocalTypeDataKey> keys);
+};
+
+}
+}
+
+#endif
diff --git a/lib/IRGen/LocalTypeDataCache.h b/lib/IRGen/LocalTypeDataCache.h
new file mode 100644
index 0000000..f44b703
--- /dev/null
+++ b/lib/IRGen/LocalTypeDataCache.h
@@ -0,0 +1,141 @@
+//===--- LocalTypeDataCache.h - Dominance-scoped type data cache --*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the LocalTypeDataCache type, which is used by
+//  IRGenFunction to cache the information available for types in a local
+//  context.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_LOCALTYPEDATACACHE_H
+#define SWIFT_IRGEN_LOCALTYPEDATACACHE_H
+
+#include "swift/AST/Type.h"
+#include <utility>
+
+namespace swift {
+class TypeBase;
+
+namespace irgen {
+enum class ValueWitness : unsigned;
+
+/// A nonce value for storing some sort of locally-known information
+/// about a type.
+class LocalTypeData {
+public:
+  using RawType = unsigned;
+private:
+  RawType Value;
+  
+  explicit LocalTypeData(unsigned Value) : Value(Value) {}
+  
+  /// Magic values for special kinds of index.
+  enum : RawType {
+    Metatype = ~0U,
+    ValueWitnessTable = ~1U,
+
+    ValueWitnessBase = 0xFFFFFF00U,
+  };
+  
+public:
+  LocalTypeData() = default;
+  
+  // The magic values are all in the "negative" range and so do
+  // not collide with reasonable index values.
+  
+  /// A reference to the type metadata.
+  static LocalTypeData forMetatype() { return LocalTypeData(Metatype); }
+  /// A reference to the value witness table.
+  static LocalTypeData forValueWitnessTable() {
+    return LocalTypeData(ValueWitnessTable);
+  }
+
+  /// A reference to a specific value witness.
+  static LocalTypeData forValueWitness(ValueWitness witness) {
+    return LocalTypeData((unsigned)witness + ValueWitnessBase);
+  }
+  
+  /// A reference to a protocol witness table for an archetype.
+  static LocalTypeData forArchetypeProtocolWitness(unsigned index) {
+    return LocalTypeData(index);
+  }
+  
+  RawType getRawValue() const {
+    return Value;
+  }
+};
+
+class LocalTypeDataCache {
+public:
+  using Key = std::pair<TypeBase*, LocalTypeData::RawType>;
+
+  static Key getKey(CanType type, LocalTypeData index) {
+    return Key(type.getPointer(), index.getRawValue());
+  }
+
+  /// An opaque class for storing keys for the dominance callback.  The
+  /// key is assumed to be something like a pointer, and a null pointer is
+  /// assumed to mean a non-dominating point.
+  class DominanceKey {
+    void *Value;
+  public:
+    explicit DominanceKey(void *value = nullptr) : Value(value) {}
+    template <class T> T* as() const { return reinterpret_cast<T*>(Value); }
+    explicit operator bool() const { return Value != nullptr; }
+  };
+
+  /// A RAII object for managing a dominance scope.
+  class DominanceScope {
+    LocalTypeDataCache &Cache;
+    DominanceKey OldDefinitionPoint;
+  public:
+    explicit DominanceScope(LocalTypeDataCache &cache, DominanceKey newPoint)
+        : Cache(cache), OldDefinitionPoint(cache.ActiveDefinitionPoint) {
+      cache.ActiveDefinitionPoint = newPoint;
+      assert(!newPoint || cache.Callback);
+    }
+
+    DominanceScope(const DominanceScope &other) = delete;
+    DominanceScope &operator=(const DominanceScope &other) = delete;
+
+    ~DominanceScope() {
+      Cache.ActiveDefinitionPoint = OldDefinitionPoint;
+    }
+  };
+
+  using DominanceCallback = bool(IRGenFunction &IGF, DominanceKey key);
+
+private:
+  /// The dominance callback.  This can be set at most once; when it's not
+  /// set, the cache must never have a non-null active definition point.
+  DominanceCallback *Callback = nullptr;
+  DominanceKey ActiveDefinitionPoint;
+
+  struct CacheEntryBase {
+    DominanceKey DefinitionPoint;
+
+  };
+
+  struct Source {
+    llvm::Value *Value;
+    MetadataPath::Map<llvm::Value*> Path;
+  };
+
+  std::vector<
+
+public:
+};
+
+}
+}
+
+#endif
diff --git a/lib/IRGen/LocalTypeDataKind.h b/lib/IRGen/LocalTypeDataKind.h
new file mode 100644
index 0000000..cb9cc2b
--- /dev/null
+++ b/lib/IRGen/LocalTypeDataKind.h
@@ -0,0 +1,139 @@
+//===--- LocalTypeDataKind.h - Kinds of locally-cached type data --*- C++ -*-=//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the LocalTypeDataKind class, which opaquely
+//  represents a particular kind of local type data that we might
+//  want to cache during emission.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_IRGEN_LOCALTYPEDATAKIND_H
+#define SWIFT_IRGEN_LOCALTYPEDATAKIND_H
+
+#include "swift/AST/Type.h"
+#include <stdint.h>
+#include "llvm/ADT/DenseMapInfo.h"
+
+namespace swift {
+  class NormalProtocolConformance;
+  class ProtocolDecl;
+
+namespace irgen {
+  enum class ValueWitness : unsigned;
+
+/// The kind of local type data we might want to store for a type.
+class LocalTypeDataKind {
+public:
+  using RawType = uintptr_t;
+private:
+  RawType Value;
+  
+  explicit LocalTypeDataKind(unsigned Value) : Value(Value) {}
+  
+  /// Magic values for special kinds of type metadata.  These should be
+  /// small so that they should never conflict with a valid pointer.
+  ///
+  /// Since this representation is opaque, we don't worry about being able
+  /// to distinguish different kinds of pointer; we just assume that e.g. a
+  /// ProtocolConformance will never have the same address as a Decl.
+  enum : RawType {
+    Metatype,
+    ValueWitnessTable,
+    // <- add more special cases here
+
+    // The first enumerator for an individual value witness.
+    ValueWitnessBase,
+  };
+  
+public:
+  LocalTypeDataKind() = default;
+  
+  // The magic values are all odd and so do not collide with pointer values.
+  
+  /// A reference to the type metadata.
+  static LocalTypeDataKind forMetatype() {
+    return LocalTypeDataKind(Metatype);
+  }
+
+  /// A reference to the value witness table.
+  static LocalTypeDataKind forValueWitnessTable() {
+    return LocalTypeDataKind(ValueWitnessTable);
+  }
+
+  /// A reference to a specific value witness.
+  static LocalTypeDataKind forValueWitness(ValueWitness witness) {
+    return LocalTypeDataKind(ValueWitnessBase + (unsigned)witness);
+  }
+  
+  /// A reference to a protocol witness table for an archetype.
+  ///
+  /// This only works for non-concrete types because in principle we might
+  /// have multiple concrete conformoances for a concrete type used in the
+  /// same function.
+  static LocalTypeDataKind
+  forArchetypeProtocolWitnessTable(ProtocolDecl *protocol) {
+    return LocalTypeDataKind(uintptr_t(protocol));
+  }
+
+  /// A reference to a protocol witness table for an archetype.
+  ///
+  /// We assume that the protocol conformance is a sufficiently unique key.
+  /// This implicitly assumes that we don't care about having multiple
+  /// specializations of a conditional conformance for different
+  /// conformances.
+  static LocalTypeDataKind
+  forConcreteProtocolWitnessTable(NormalProtocolConformance *conformance) {
+    return LocalTypeDataKind(uintptr_t(conformance));
+  }
+  
+  RawType getRawValue() const {
+    return Value;
+  }
+
+  bool operator==(LocalTypeDataKind other) const {
+    return Value == other.Value;
+  }
+};
+
+struct LocalTypeDataKey {
+  CanType Type;
+  LocalTypeDataKind Kind;
+
+  bool operator==(const LocalTypeDataKey &other) const {
+    return Type == other.Type && Kind == other.Kind;
+  }
+};
+
+}
+}
+
+template <> struct llvm::DenseMapInfo<swift::irgen::LocalTypeDataKey> {
+  using LocalTypeDataKey = swift::irgen::LocalTypeDataKey;
+  using CanTypeInfo = DenseMapInfo<swift::CanType>;
+  static inline LocalTypeDataKey getEmptyKey() {
+    return { CanTypeInfo::getEmptyKey(),
+             swift::irgen::LocalTypeDataKind::forMetatype() };
+  }
+  static inline LocalTypeDataKey getTombstoneKey() {
+    return { CanTypeInfo::getTombstoneKey(),
+             swift::irgen::LocalTypeDataKind::forMetatype() };
+  }
+  static unsigned getHashValue(const LocalTypeDataKey &key) {
+    return combineHashValue(CanTypeInfo::getHashValue(key.Type),
+                            key.Kind.getRawValue());
+  }
+  static bool isEqual(const LocalTypeDataKey &a, const LocalTypeDataKey &b) {
+    return a == b;
+  }
+};
+
+#endif
\ No newline at end of file
diff --git a/lib/IRGen/MetadataPath.h b/lib/IRGen/MetadataPath.h
index 8a6a0e6..79fc99a 100644
--- a/lib/IRGen/MetadataPath.h
+++ b/lib/IRGen/MetadataPath.h
@@ -25,7 +25,9 @@
 }
 
 namespace swift {
+  class ProtocolDecl;
   class CanType;
+  class Decl;
 
 namespace irgen {
   class IRGenFunction;
diff --git a/lib/IRGen/TypeInfo.h b/lib/IRGen/TypeInfo.h
index 705133f..ba28779 100644
--- a/lib/IRGen/TypeInfo.h
+++ b/lib/IRGen/TypeInfo.h
@@ -34,6 +34,9 @@
 }
 
 namespace swift {
+  enum IsTake_t : bool;
+  class SILType;
+
 namespace irgen {
   class Address;
   class ContainedAddress;
@@ -260,6 +263,12 @@
   virtual void deallocateStack(IRGenFunction &IGF, Address addr,
                                SILType T) const = 0;
 
+  /// Copy or take a value out of one address and into another, destroying
+  /// old value in the destination.  Equivalent to either assignWithCopy
+  /// or assignWithTake depending on the value of isTake.
+  void assign(IRGenFunction &IGF, Address dest, Address src, IsTake_t isTake,
+              SILType T) const;
+
   /// Copy a value out of an object and into another, destroying the
   /// old value in the destination.
   virtual void assignWithCopy(IRGenFunction &IGF, Address dest,
@@ -270,6 +279,13 @@
   virtual void assignWithTake(IRGenFunction &IGF, Address dest,
                               Address src, SILType T) const = 0;
 
+  /// Copy-initialize or take-initialize an uninitialized object
+  /// with the value from a different object.  Equivalent to either
+  /// initializeWithCopy or initializeWithTake depending on the value
+  /// of isTake.
+  void initialize(IRGenFunction &IGF, Address dest, Address src,
+                  IsTake_t isTake, SILType T) const;
+
   /// Perform a "take-initialization" from the given object.  A
   /// take-initialization is like a C++ move-initialization, except that
   /// the old object is actually no longer permitted to be destroyed.
diff --git a/lib/Immediate/ImmediateImpl.h b/lib/Immediate/ImmediateImpl.h
index aba1e3b..5bc40f0 100644
--- a/lib/Immediate/ImmediateImpl.h
+++ b/lib/Immediate/ImmediateImpl.h
@@ -1,4 +1,4 @@
-//===-- ImmediateImpl.h - Support functions for immediate mode --*- C++ -*-===//
+//===--- ImmediateImpl.h - Support functions for immediate mode -*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/LLVMPasses/LLVMARCOpts.h b/lib/LLVMPasses/LLVMARCOpts.h
index 05b7f25..fe84bab 100644
--- a/lib/LLVMPasses/LLVMARCOpts.h
+++ b/lib/LLVMPasses/LLVMARCOpts.h
@@ -1,4 +1,4 @@
-//===- LLVMARCOpts.h - LLVM level ARC Opts Utility Declarations -*- C++ -*-===//
+//===--- LLVMARCOpts.h - LLVM level ARC Opts Util. Declarations -*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index ae0cdd8..caebdf8 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2877,7 +2877,7 @@
 
     case AccessorKind::IsMaterializeForSet:
     case AccessorKind::NotAccessor:
-      llvm_unreachable("not parsable accessors");
+      llvm_unreachable("not parseable accessors");
     }
   }
 
diff --git a/lib/SIL/Verifier.cpp b/lib/SIL/Verifier.cpp
index b2f2e13..ee2b584 100644
--- a/lib/SIL/Verifier.cpp
+++ b/lib/SIL/Verifier.cpp
@@ -2018,6 +2018,18 @@
             "failure dest of checked_cast_br must take no arguments");
   }
 
+  void checkCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
+    require(CCABI->getSrc().getType().isAddress(),
+            "checked_cast_addr_br src must be an address");
+    require(CCABI->getDest().getType().isAddress(),
+            "checked_cast_addr_br dest must be an address");
+
+    require(CCABI->getSuccessBB()->bbarg_size() == 0,
+        "success dest block of checked_cast_addr_br must not take an argument");
+    require(CCABI->getFailureBB()->bbarg_size() == 0,
+        "failure dest block of checked_cast_addr_br must not take an argument");
+  }
+
   void checkThinToThickFunctionInst(ThinToThickFunctionInst *TTFI) {
     auto opFTy = requireObjectType(SILFunctionType, TTFI->getOperand(),
                                    "thin_to_thick_function operand");
@@ -2542,7 +2554,7 @@
 
   void checkSwitchEnumAddrInst(SwitchEnumAddrInst *SOI){
     require(SOI->getOperand().getType().isAddress(),
-            "switch_enum_addr operand must be an object");
+            "switch_enum_addr operand must be an address");
 
     SILType uTy = SOI->getOperand().getType();
     EnumDecl *uDecl = uTy.getEnumOrBoundGenericEnum();
diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h
index fd3fa14..548f81d 100644
--- a/lib/SILGen/ArgumentSource.h
+++ b/lib/SILGen/ArgumentSource.h
@@ -1,4 +1,4 @@
-//===--- ArgumentSource.h - Abstracted source of an argument 000-*- C++ -*-===//
+//===--- ArgumentSource.h - Abstracted source of an argument ----*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/SILOptimizer/ARC/GlobalARCPairingAnalysis.cpp b/lib/SILOptimizer/ARC/GlobalARCPairingAnalysis.cpp
index af7f67c..3e0fe42 100644
--- a/lib/SILOptimizer/ARC/GlobalARCPairingAnalysis.cpp
+++ b/lib/SILOptimizer/ARC/GlobalARCPairingAnalysis.cpp
@@ -1,4 +1,4 @@
-//===-- GlobalARCPairingAnalysis.cpp - Global ARC Retain Release Pairing --===//
+//===--- GlobalARCPairingAnalysis.cpp - Global ARC Retain Release Pairing -===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp b/lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp
index 31085d9..fd90cb3 100644
--- a/lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/ClassHierarchyAnalysis.cpp
@@ -1,4 +1,4 @@
-//===- ClassHierarchyAnalysis.cpp - Analysis of class hierarchy -*- C++ -*-===//
+//===--- ClassHierarchyAnalysis.cpp - Class hierarchy analysis --*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/SILOptimizer/IPO/PerformanceInliner.cpp b/lib/SILOptimizer/IPO/PerformanceInliner.cpp
index f477bb2..6fffb12 100644
--- a/lib/SILOptimizer/IPO/PerformanceInliner.cpp
+++ b/lib/SILOptimizer/IPO/PerformanceInliner.cpp
@@ -1,4 +1,4 @@
-//===- PerformanceInliner.cpp - Basic cost based inlining for performance -===//
+//===--- PerformanceInliner.cpp - Basic cost based performance inlining ---===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -562,7 +562,7 @@
   return false;
 }
 
-// Returns the callee of an apply_inst if it is basically inlinable.
+// Returns the callee of an apply_inst if it is basically inlineable.
 SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
 
   SILFunction *Callee = AI.getCalleeFunction();
diff --git a/lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp b/lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp
index b165499..8665cad 100644
--- a/lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp
+++ b/lib/SILOptimizer/Mandatory/DataflowDiagnostics.cpp
@@ -1,4 +1,4 @@
-//===-- DataflowDiagnostics.cpp - Emits diagnostics based on SIL analysis -===//
+//===--- DataflowDiagnostics.cpp - Emits diagnostics based on SIL analysis ===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
index ab8fac5..6f26549 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
@@ -268,7 +268,7 @@
         }
 
       // Not fully covered switches will be diagnosed later. SILGen represents
-      // them with a Default basic block with an unrechable instruction.
+      // them with a Default basic block with an unreachable instruction.
       // We are going to produce an error on all unreachable instructions not
       // eliminated by DCE.
       if (!TheSuccessorBlock)
diff --git a/lib/SILOptimizer/SILCombiner/SILCombine.cpp b/lib/SILOptimizer/SILCombiner/SILCombine.cpp
index eb17934..27b7a4b 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombine.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombine.cpp
@@ -212,7 +212,7 @@
     auto &TrackingList = *Builder.getTrackingList();
     for (SILInstruction *I : TrackingList) {
       DEBUG(llvm::dbgs() << "SC: add " << *I <<
-            " from trackinglist to worklist\n");
+            " from tracking list to worklist\n");
       Worklist.add(I);
     }
     TrackingList.clear();
diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
index ffa3fca..1277daf 100644
--- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
@@ -283,13 +283,13 @@
   switch (Term->getTermKind()) {
   case TermKind::ReturnInst:
   case TermKind::ThrowInst:
-  case TermKind::SwitchEnumAddrInst:
-  case TermKind::CheckedCastAddrBranchInst:
   case TermKind::Invalid:
     llvm_unreachable("Unexpected terminator kind!");
 
   case TermKind::UnreachableInst:
   case TermKind::SwitchValueInst:
+  case TermKind::SwitchEnumAddrInst:
+  case TermKind::CheckedCastAddrBranchInst:
     llvm_unreachable("Unexpected argument for terminator kind!");
     break;
 
diff --git a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
index 99460f9..d020f47 100644
--- a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp
@@ -145,7 +145,7 @@
 /// which is a large function.  
 constexpr unsigned MaxLSLocationBBMultiplicationNone = 256*256;
 
-/// we could run optimsitic DSE on functions with less than 64 basic blocks
+/// we could run optimistic DSE on functions with less than 64 basic blocks
 /// and 64 locations which is a sizeable function.
 constexpr unsigned MaxLSLocationBBMultiplicationPessimistic = 64*64;
 
diff --git a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
index f3be266..24bfb44 100644
--- a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
+++ b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp
@@ -141,7 +141,7 @@
 /// \brief Find a root value for operand \p In. This function inspects a sil
 /// value and strips trivial conversions such as values that are passed
 /// as arguments to basic blocks with a single predecessor or type casts.
-/// This is a shallow one-spet search and not a deep recursive search.
+/// This is a shallow one-step search and not a deep recursive search.
 ///
 /// For example, in the SIL code below, the root of %10 is %3, because it is
 /// the only possible incoming value.
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index aa9bb60..aaa6c8d 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -1,4 +1,4 @@
-//===-- SpeculativeDevirtualizer.cpp -- Speculatively devirtualize calls --===//
+//===--- SpeculativeDevirtualizer.cpp - Speculatively devirtualize calls --===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -15,7 +15,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#define DEBUG_TYPE "sil-speculative-devirtualizer-pass"
+#define DEBUG_TYPE "sil-speculative-devirtualizer"
 #include "swift/Basic/DemangleWrappers.h"
 #include "swift/Basic/Fallthrough.h"
 #include "swift/SIL/SILArgument.h"
diff --git a/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp b/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp
index fef3e77..b05195f 100644
--- a/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp
+++ b/lib/SILOptimizer/UtilityPasses/LSLocationPrinter.cpp
@@ -1,19 +1,19 @@
-///===--- LSLocationPrinter.cpp - Dump all memory locations in program ---===//
-///
-/// This source file is part of the Swift.org open source project
-///
-/// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
-/// Licensed under Apache License v2.0 with Runtime Library Exception
-///
-/// See http://swift.org/LICENSE.txt for license information
-/// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-///
-///===---------------------------------------------------------------------===//
-///
-/// This pass tests type expansion, memlocation expansion and memlocation
-/// reduction.
-///
-///===---------------------------------------------------------------------===//
+//===--- LSLocationPrinter.cpp - Dump all memory locations in program -----===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass tests type expansion, memlocation expansion and memlocation
+// reduction.
+//
+//===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "sil-memlocation-dumper"
 #include "swift/SILOptimizer/PassManager/Passes.h"
diff --git a/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp b/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
index 04cf943..49a15f4 100644
--- a/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
+++ b/lib/SILOptimizer/UtilityPasses/MemBehaviorDumper.cpp
@@ -2,7 +2,7 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
 // See http://swift.org/LICENSE.txt for license information
diff --git a/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp b/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
index 1fffa6b..1bc9b6b 100644
--- a/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
+++ b/lib/SILOptimizer/UtilityPasses/RCIdentityDumper.cpp
@@ -2,7 +2,7 @@
 //
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
 // See http://swift.org/LICENSE.txt for license information
diff --git a/lib/SILOptimizer/Utils/ConstantFolding.cpp b/lib/SILOptimizer/Utils/ConstantFolding.cpp
index 4fa5941..2ed3f9e 100644
--- a/lib/SILOptimizer/Utils/ConstantFolding.cpp
+++ b/lib/SILOptimizer/Utils/ConstantFolding.cpp
@@ -1,4 +1,4 @@
-//===- ConstantFolding.cpp - Utilities for SIL constant folding -*- C++ -*-===//
+//===--- ConstantFolding.cpp - Utils for SIL constant folding ---*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 7032475..388e43a 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -5667,7 +5667,8 @@
 
         // Coerce the pattern, in case we resolved something.
         auto fnType = closure->getType()->castTo<FunctionType>();
-        if (tc.coerceParameterListToType(closure, fnType))
+        auto *params = closure->getParameters();
+        if (tc.coerceParameterListToType(params, closure, fnType->getInput()))
           return { false, nullptr };
 
         // If this is a single-expression closure, convert the expression
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 8e17f1f..57f3981 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -4164,7 +4164,61 @@
       CS->getContextualType()->is<AnyFunctionType>()) {
 
     auto fnType = CS->getContextualType()->castTo<AnyFunctionType>();
-    if (CS->TC.coerceParameterListToType(CE, fnType))
+    auto *params = CE->getParameters();
+    Type inferredArgType = fnType->getInput();
+    
+    // It is very common for a contextual type to disagree with the argument
+    // list built into the closure expr.  This can be because the closure expr
+    // had an explicitly specified pattern, a la:
+    //    { a,b in ... }
+    // or could be because the closure has an implicitly generated one:
+    //    { $0 + $1 }
+    // in either case, we want to produce nice and clear diagnostics.
+    unsigned actualArgCount = params->size();
+    unsigned inferredArgCount = 1;
+    if (auto *argTupleTy = inferredArgType->getAs<TupleType>())
+      inferredArgCount = argTupleTy->getNumElements();
+    
+    // If the actual argument count is 1, it can match a tuple as a whole.
+    if (actualArgCount != 1 && actualArgCount != inferredArgCount) {
+      // If the closure didn't specify any arguments and it is in a context that
+      // needs some, produce a fixit to turn "{...}" into "{ _,_ in ...}".
+      if (actualArgCount == 0 && CE->getInLoc().isInvalid()) {
+        auto diag =
+          diagnose(CE->getStartLoc(), diag::closure_argument_list_missing,
+                   inferredArgCount);
+        StringRef fixText;  // We only handle the most common cases.
+        if (inferredArgCount == 1)
+          fixText = " _ in ";
+        else if (inferredArgCount == 2)
+          fixText = " _,_ in ";
+        else if (inferredArgCount == 3)
+          fixText = " _,_,_ in ";
+        
+        if (!fixText.empty()) {
+          // Determine if there is already a space after the { in the closure to
+          // make sure we introduce the right whitespace.
+          auto afterBrace = CE->getStartLoc().getAdvancedLoc(1);
+          auto text = CS->TC.Context.SourceMgr.extractText({afterBrace, 1});
+          if (text.size() == 1 && text == " ")
+            fixText = fixText.drop_back();
+          else
+            fixText = fixText.drop_front();
+          diag.fixItInsertAfter(CE->getStartLoc(), fixText);
+        }
+        return true;
+      }
+      
+      // Okay, the wrong number of arguments was used, complain about that.
+      // Before doing so, strip attributes off the function type so that they
+      // don't confuse the issue.
+      fnType = FunctionType::get(fnType->getInput(), fnType->getResult());
+      diagnose(params->getStartLoc(), diag::closure_argument_list_tuple,
+               fnType, inferredArgCount, actualArgCount);
+      return true;
+    }
+
+    if (CS->TC.coerceParameterListToType(params, CE, inferredArgType))
       return true;
 
     expectedResultType = fnType->getResult();
@@ -4282,6 +4336,16 @@
     }
     
     if (!foundConformance) {
+      // If the contextual type conforms to DictionaryLiteralConvertible and
+      // this is an empty array, then they meant "[:]".
+      if (E->getNumElements() == 0 &&
+          isDictionaryLiteralCompatible(contextualType, CS, E->getLoc())) {
+        diagnose(E->getStartLoc(), diag::should_use_empty_dictionary_literal)
+          .fixItInsert(E->getEndLoc(), ":");
+        return true;
+      }
+
+
       diagnose(E->getStartLoc(), diag::type_is_not_array, contextualType)
         .highlight(E->getSourceRange());
 
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 5fde0e7..c77266c 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -1593,12 +1593,16 @@
       // containing a single element if the scalar type is a subtype of
       // the type of that tuple's element.
       //
-      // A scalar type can be converted to a tuple so long as there is at
-      // most one non-defaulted element.
+      // A scalar type can be converted to an argument tuple so long as
+      // there is at most one non-defaulted element.
+      // For non-argument tuples, we can do the same conversion but not
+      // to a tuple with varargs.
       if ((tuple2->getNumElements() == 1 &&
            !tuple2->getElement(0).isVararg()) ||
           (kind >= TypeMatchKind::Conversion &&
-           tuple2->getElementForScalarInit() >= 0)) {
+           tuple2->getElementForScalarInit() >= 0 &&
+           (isArgumentTupleConversion ||
+            !tuple2->getVarArgsBaseType()))) {
         conversionsOrFixes.push_back(
           ConversionRestrictionKind::ScalarToTuple);
 
diff --git a/lib/Sema/ConstraintGraphScope.h b/lib/Sema/ConstraintGraphScope.h
index 7c09a43..213ca89 100644
--- a/lib/Sema/ConstraintGraphScope.h
+++ b/lib/Sema/ConstraintGraphScope.h
@@ -1,4 +1,4 @@
-//===--- ConstraintGraphScope.h - Constraint Graph Scope---------*- C++ -*-===//
+//===--- ConstraintGraphScope.h - Constraint Graph Scope --------*- C++ -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/lib/Sema/ITCDecl.cpp b/lib/Sema/ITCDecl.cpp
index b7c4354..1371b77 100644
--- a/lib/Sema/ITCDecl.cpp
+++ b/lib/Sema/ITCDecl.cpp
@@ -22,9 +22,9 @@
 #include <tuple>
 using namespace swift;
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Inheritance clause handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 static std::tuple<TypeResolutionOptions, DeclContext *,
                   MutableArrayRef<TypeLoc>>
 decomposeInheritedClauseDecl(
@@ -116,9 +116,9 @@
   return true;
 }
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Superclass handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 bool IterativeTypeChecker::isTypeCheckSuperclassSatisfied(ClassDecl *payload) {
   return payload->LazySemanticInfo.Superclass.getInt();
 }
@@ -162,9 +162,9 @@
   return true;
 }
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Raw type handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 bool IterativeTypeChecker::isTypeCheckRawTypeSatisfied(EnumDecl *payload) {
   return payload->LazySemanticInfo.RawType.getInt();
 }
@@ -205,9 +205,9 @@
   return true;
 }
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Inherited protocols
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 bool IterativeTypeChecker::isInheritedProtocolsSatisfied(ProtocolDecl *payload){
   return payload->isInheritedProtocolsValid();
 }
@@ -280,9 +280,9 @@
   return true;
 }
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Resolve a type declaration
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 bool IterativeTypeChecker::isResolveTypeDeclSatisfied(TypeDecl *typeDecl) {
   if (auto typeAliasDecl = dyn_cast<TypeAliasDecl>(typeDecl)) {
     // If the underlying type was validated, we're done.
diff --git a/lib/Sema/ITCNameLookup.cpp b/lib/Sema/ITCNameLookup.cpp
index 894d6b44..87ab725 100644
--- a/lib/Sema/ITCNameLookup.cpp
+++ b/lib/Sema/ITCNameLookup.cpp
@@ -21,9 +21,9 @@
 #include <tuple>
 using namespace swift;
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Qualified name lookup handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 bool IterativeTypeChecker::isQualifiedLookupInDeclContextSatisfied(
        TypeCheckRequest::DeclContextLookupPayloadType payload) {
   auto dc = payload.DC;
@@ -123,9 +123,9 @@
   return false;
 }
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Qualified name lookup handling
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 bool IterativeTypeChecker::isUnqualifiedLookupInDeclContextSatisfied(
        TypeCheckRequest::DeclContextLookupPayloadType payload) {
   auto dc = payload.DC;
diff --git a/lib/Sema/ITCType.cpp b/lib/Sema/ITCType.cpp
index 03aae1d..8a8c4bd 100644
--- a/lib/Sema/ITCType.cpp
+++ b/lib/Sema/ITCType.cpp
@@ -22,9 +22,9 @@
 #include "swift/AST/Decl.h"
 using namespace swift;
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Type resolution.
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 bool IterativeTypeChecker::isResolveTypeReprSatisfied(
        std::tuple<TypeRepr *, DeclContext *, unsigned> payload) {
   auto typeRepr = std::get<0>(payload);
diff --git a/lib/Sema/IterativeTypeChecker.cpp b/lib/Sema/IterativeTypeChecker.cpp
index e86281d..0cd26e9 100644
--- a/lib/Sema/IterativeTypeChecker.cpp
+++ b/lib/Sema/IterativeTypeChecker.cpp
@@ -112,9 +112,9 @@
   }
 }
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Diagnostics
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 void IterativeTypeChecker::diagnoseCircularReference(
        ArrayRef<TypeCheckRequest> requests) {
   bool isFirst = true;
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index da35319..a77f619 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -1360,10 +1360,23 @@
 
   // Attempt to solve the constraint system.
   SmallVector<Solution, 4> viable;
+  const Type originalType = expr->getType();
+  const bool needClearType = originalType && originalType->is<ErrorType>();
+  const auto recoverOriginalType = [&] () {
+    if (needClearType)
+      expr->setType(originalType);
+  };
+
+  // If the previous checking gives the expr error type, clear the result and
+  // re-check.
+  if (needClearType)
+    expr->setType(Type());
   if (solveForExpression(expr, dc, /*convertType*/Type(),
                          allowFreeTypeVariables, listener, cs, viable,
-                         TypeCheckExprFlags::SuppressDiagnostics))
+                         TypeCheckExprFlags::SuppressDiagnostics)) {
+    recoverOriginalType();
     return None;
+  }
 
   // Get the expression's simplified type.
   auto &solution = viable[0];
@@ -1373,6 +1386,8 @@
   assert(!exprType->hasTypeVariable() &&
          "free type variable with FreeTypeVariableBinding::GenericParameters?");
 
+  // Recover the original type if needed.
+  recoverOriginalType();
   return exprType;
 }
 
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 19574e0..8a4e6f5 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -1548,11 +1548,11 @@
 ///
 /// \returns true if an error occurred, false otherwise.
 ///
-bool TypeChecker::coerceParameterListToType(ClosureExpr *CE,
-                                            AnyFunctionType *closureType) {
-  auto paramListType = closureType->getInput();
-  
-  ParameterList *P = CE->getParameters();  
+/// TODO: These diagnostics should be a lot better now that we know this is
+/// all specific to closures.
+///
+bool TypeChecker::coerceParameterListToType(ParameterList *P, DeclContext *DC,
+                                            Type paramListType) {
   bool hadError = paramListType->is<ErrorType>();
 
   // Sometimes a scalar type gets applied to a single-argument parameter list.
@@ -1561,7 +1561,7 @@
     
     // Check that the type, if explicitly spelled, is ok.
     if (param->getTypeLoc().getTypeRepr()) {
-      hadError |= validateParameterType(param, CE, TypeResolutionOptions(),
+      hadError |= validateParameterType(param, DC, TypeResolutionOptions(),
                                         nullptr, *this);
       
       // Now that we've type checked the explicit argument type, see if it
@@ -1582,74 +1582,29 @@
     return hadError;
   };
 
-  // If there is one parameter to the closure, then it gets inferred to be the
-  // complete type presented.
-  if (P->size() == 1)
-    return handleParameter(P->get(0), paramListType);
-
-  // The context type must be a tuple if we have multiple parameters, and match
-  // in element count.  If it doesn't, we'll diagnose it and force the
-  // parameters to ErrorType.
-  TupleType *tupleTy = paramListType->getAs<TupleType>();
-  unsigned inferredArgCount = 1;
-  if (tupleTy)
-    inferredArgCount = tupleTy->getNumElements();
-
-  // If we already emitted a diagnostic, or if our argument count matches up,
-  // then there is nothing to do.
-  if (hadError || P->size() == inferredArgCount) {
-    // I just said, nothing to do!
-    
-  // It is very common for a contextual type to disagree with the closure
-  // argument list.  This can be because the closure expr had an explicitly
-  // specified parameter list, a la:
-  //    { a,b in ... }
-  // or could be because the closure has an implicitly generated one:
-  //    { $0 + $1 }
-  // in either case, we want to produce nice and clear diagnostics.
   
-  // If the closure didn't specify any arguments and it is in a context that
-  // needs some, produce a fixit to turn "{...}" into "{ _,_ in ...}".
-  } else if (P->size() == 0 && CE->getInLoc().isInvalid()) {
-    auto diag =
-      diagnose(CE->getStartLoc(), diag::closure_argument_list_missing,
-               inferredArgCount);
-    StringRef fixText;  // We only handle the most common cases.
-    if (inferredArgCount == 1)
-      fixText = " _ in ";
-    else if (inferredArgCount == 2)
-      fixText = " _,_ in ";
-    else if (inferredArgCount == 3)
-      fixText = " _,_,_ in ";
-    
-    if (!fixText.empty()) {
-      // Determine if there is already a space after the { in the closure to
-      // make sure we introduce the right whitespace.
-      auto afterBrace = CE->getStartLoc().getAdvancedLoc(1);
-      auto text = Context.SourceMgr.extractText({afterBrace, 1});
-      if (text.size() == 1 && text == " ")
-        fixText = fixText.drop_back();
-      else
-        fixText = fixText.drop_front();
-      diag.fixItInsertAfter(CE->getStartLoc(), fixText);
-    }
+  // The context type must be a tuple.
+  TupleType *tupleTy = paramListType->getAs<TupleType>();
+  if (!tupleTy && !hadError) {
+    if (P->size() == 1)
+      return handleParameter(P->get(0), paramListType);
+    diagnose(P->getStartLoc(), diag::tuple_pattern_in_non_tuple_context,
+             paramListType);
     hadError = true;
-  } else {
-    // Okay, the wrong number of arguments was used, so complain about that
-    // generically.  We should try even harder here :-)
-    //
-    // Before doing so, strip attributes off the function type so that they
-    // don't confuse the issue.
-    auto fnType = FunctionType::get(closureType->getInput(),
-                                    closureType->getResult());
+  }
+  
+  // The number of elements must match exactly.
+  // TODO: incomplete tuple patterns, with some syntax.
+  if (!hadError && tupleTy->getNumElements() != P->size()) {
+    if (P->size() == 1)
+      return handleParameter(P->get(0), paramListType);
     
-    diagnose(P->getStartLoc(), diag::closure_argument_list_tuple,
-             fnType, inferredArgCount, P->size());
+    diagnose(P->getStartLoc(), diag::tuple_pattern_length_mismatch,
+             paramListType);
     hadError = true;
   }
 
-  // Coerce each parameter to the respective type, or ErrorType if we already
-  // detected and diagnosed an error.
+  // Coerce each parameter to the respective type.
   for (unsigned i = 0, e = P->size(); i != e; ++i) {
     auto &param = P->get(i);
     
@@ -1658,10 +1613,9 @@
       CoercionType = ErrorType::get(Context);
     else
       CoercionType = tupleTy->getElement(i).getType();
-
+    
     // If the tuple pattern had a label for the tuple element, it must match
     // the label for the tuple type being matched.
-    // FIXME: closure should probably not be allowed to have API/argument names.
     auto argName = param->getArgumentName();
     if (!hadError && !argName.empty() &&
         argName != tupleTy->getElement(i).getName()) {
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 8712a21..a47cd06 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -331,7 +331,7 @@
 
   /// Type-check an entire function body.
   bool typeCheckBody(BraceStmt *&S) {
-    if (typeCheckStmt(S)) return true;
+    typeCheckStmt(S);
     setAutoClosureDiscriminators(DC, S);
     return false;
   }
@@ -402,7 +402,6 @@
     if (hadTypeError) {
       tryDiagnoseUnnecessaryCastOverOptionSet(TC.Context, E, ResultTy,
                                               DC->getParentModule());
-      return nullptr;
     }
     
     return RS;
@@ -415,55 +414,52 @@
     Type exnType = TC.getExceptionType(DC, TS->getThrowLoc());
     if (!exnType) return TS;
     
-    auto hadTypeError = TC.typeCheckExpression(E, DC, exnType, CTP_ThrowStmt);
+    TC.typeCheckExpression(E, DC, exnType, CTP_ThrowStmt);
     TS->setSubExpr(E);
     
-    return hadTypeError ? nullptr : TS;
+    return TS;
   }
     
   Stmt *visitDeferStmt(DeferStmt *DS) {
     TC.typeCheckDecl(DS->getTempDecl(), /*isFirstPass*/false);
 
     Expr *theCall = DS->getCallExpr();
-    auto hadTypeError = TC.typeCheckExpression(theCall, DC);
+    TC.typeCheckExpression(theCall, DC);
     DS->setCallExpr(theCall);
     
-    return hadTypeError ? nullptr : DS;
+    return DS;
   }
   
   Stmt *visitIfStmt(IfStmt *IS) {
-    bool hadTypeError = false;
-
     StmtCondition C = IS->getCond();
-    hadTypeError |= TC.typeCheckStmtCondition(C, DC, diag::if_always_true);
+    TC.typeCheckStmtCondition(C, DC, diag::if_always_true);
     IS->setCond(C);
 
     AddLabeledStmt ifNest(*this, IS);
 
     Stmt *S = IS->getThenStmt();
-    hadTypeError |= typeCheckStmt(S);
+    typeCheckStmt(S);
     IS->setThenStmt(S);
 
     if ((S = IS->getElseStmt())) {
-      hadTypeError |= typeCheckStmt(S);
+      typeCheckStmt(S);
       IS->setElseStmt(S);
     }
     
-    return hadTypeError ? nullptr : IS;
+    return IS;
   }
   
   Stmt *visitGuardStmt(GuardStmt *GS) {
-    bool hadTypeError = false;
     StmtCondition C = GS->getCond();
-    hadTypeError |= TC.typeCheckStmtCondition(C, DC, diag::guard_always_succeeds);
+    TC.typeCheckStmtCondition(C, DC, diag::guard_always_succeeds);
     GS->setCond(C);
     
     AddLabeledStmt ifNest(*this, GS);
     
     Stmt *S = GS->getBody();
-    hadTypeError |= typeCheckStmt(S);
+    typeCheckStmt(S);
     GS->setBody(S);
-    return hadTypeError ? nullptr : GS;
+    return GS;
   }
 
   Stmt *visitIfConfigStmt(IfConfigStmt *ICS) {
@@ -477,69 +473,66 @@
   Stmt *visitDoStmt(DoStmt *DS) {
     AddLabeledStmt loopNest(*this, DS);
     Stmt *S = DS->getBody();
-    bool hadTypeError = typeCheckStmt(S);
+    typeCheckStmt(S);
     DS->setBody(S);
-    return hadTypeError ? nullptr : DS;
+    return DS;
   }
   
   Stmt *visitWhileStmt(WhileStmt *WS) {
-    bool hadTypeError = false;
     StmtCondition C = WS->getCond();
-    hadTypeError |= TC.typeCheckStmtCondition(C, DC, diag::while_always_true);
+    TC.typeCheckStmtCondition(C, DC, diag::while_always_true);
     WS->setCond(C);
 
     AddLabeledStmt loopNest(*this, WS);
     Stmt *S = WS->getBody();
-    hadTypeError |= typeCheckStmt(S);
+    typeCheckStmt(S);
     WS->setBody(S);
     
-    return hadTypeError ? nullptr : WS;
+    return WS;
   }
   Stmt *visitRepeatWhileStmt(RepeatWhileStmt *RWS) {
-    bool hadTypeError = false;
     {
       AddLabeledStmt loopNest(*this, RWS);
       Stmt *S = RWS->getBody();
-      hadTypeError |= typeCheckStmt(S);
+      typeCheckStmt(S);
       RWS->setBody(S);
     }
     
     Expr *E = RWS->getCond();
-    hadTypeError |= TC.typeCheckCondition(E, DC);
+    TC.typeCheckCondition(E, DC);
     RWS->setCond(E);
-    return hadTypeError ? nullptr : RWS;
+    return RWS;
   }
   Stmt *visitForStmt(ForStmt *FS) {
-    bool hadTypeError = false;
     // Type check any var decls in the initializer.
     for (auto D : FS->getInitializerVarDecls())
       TC.typeCheckDecl(D, /*isFirstPass*/false);
 
     if (auto *Initializer = FS->getInitializer().getPtrOrNull()) {
-      hadTypeError |= TC.typeCheckExpression(Initializer, DC, Type(), CTP_Unused,
-                                       TypeCheckExprFlags::IsDiscarded);
+      TC.typeCheckExpression(Initializer, DC, Type(), CTP_Unused,
+                             TypeCheckExprFlags::IsDiscarded);
       FS->setInitializer(Initializer);
       TC.checkIgnoredExpr(Initializer);
     }
 
     if (auto *Cond = FS->getCond().getPtrOrNull()) {
-      hadTypeError |= TC.typeCheckCondition(Cond, DC);
+      TC.typeCheckCondition(Cond, DC);
       FS->setCond(Cond);
     }
 
     if (auto *Increment = FS->getIncrement().getPtrOrNull()) {
-      hadTypeError |= TC.typeCheckExpression(Increment, DC, Type(), CTP_Unused,
-                                       TypeCheckExprFlags::IsDiscarded);
+      TC.typeCheckExpression(Increment, DC, Type(), CTP_Unused,
+                             TypeCheckExprFlags::IsDiscarded);
       FS->setIncrement(Increment);
       TC.checkIgnoredExpr(Increment);
     }
 
     AddLabeledStmt loopNest(*this, FS);
     Stmt *S = FS->getBody();
-    hadTypeError |= typeCheckStmt(S);
+    typeCheckStmt(S);
     FS->setBody(S);
     
-    return hadTypeError ? nullptr : FS;
+    return FS;
   }
   
   Stmt *visitForEachStmt(ForEachStmt *S) {
@@ -689,7 +682,7 @@
     // Type-check the body of the loop.
     AddLabeledStmt loopNest(*this, S);
     BraceStmt *Body = S->getBody();
-    if (typeCheckStmt(Body)) return nullptr;
+    typeCheckStmt(Body);
     S->setBody(Body);
     
     return S;
@@ -806,14 +799,12 @@
   }
   
   Stmt *visitSwitchStmt(SwitchStmt *S) {
-    bool hadTypeError = false;
     // Type-check the subject expression.
     Expr *subjectExpr = S->getSubjectExpr();
-    hadTypeError |= TC.typeCheckExpression(subjectExpr, DC);
-    subjectExpr = TC.coerceToMaterializable(subjectExpr);
-    if (subjectExpr) {
-      S->setSubjectExpr(subjectExpr);
-    }
+    TC.typeCheckExpression(subjectExpr, DC);
+    if (Expr *newSubjectExpr = TC.coerceToMaterializable(subjectExpr))
+      subjectExpr = newSubjectExpr;
+    S->setSubjectExpr(subjectExpr);
     Type subjectType = S->getSubjectExpr()->getType();
 
     // Type-check the case blocks.
@@ -841,27 +832,24 @@
               VD->overwriteType(ErrorType::get(TC.Context));
               VD->setInvalid();
             });
-            hadTypeError = true;
           }
           labelItem.setPattern(pattern);
-        } else {
-          hadTypeError = true;
         }
 
         // Check the guard expression, if present.
         if (auto *guard = labelItem.getGuardExpr()) {
-          hadTypeError |= TC.typeCheckCondition(guard, DC);
+          TC.typeCheckCondition(guard, DC);
           labelItem.setGuardExpr(guard);
         }
       }
       
       // Type-check the body statements.
       Stmt *body = caseBlock->getBody();
-      hadTypeError |= typeCheckStmt(body);
+      typeCheckStmt(body);
       caseBlock->setBody(body);
     }
     
-    return hadTypeError ? nullptr : S;
+    return S;
   }
 
   Stmt *visitCaseStmt(CaseStmt *S) {
@@ -874,23 +862,20 @@
     llvm_unreachable("catch stmt outside of do-catch?!");
   }
 
-  bool checkCatchStmt(CatchStmt *S) {
-    bool hadTypeError = false;
+  void checkCatchStmt(CatchStmt *S) {
     // Check the catch pattern.
-    hadTypeError |= TC.typeCheckCatchPattern(S, DC);
+    TC.typeCheckCatchPattern(S, DC);
 
     // Check the guard expression, if present.
     if (Expr *guard = S->getGuardExpr()) {
-      hadTypeError |= TC.typeCheckCondition(guard, DC);
+      TC.typeCheckCondition(guard, DC);
       S->setGuardExpr(guard);
     }
       
     // Type-check the clause body.
     Stmt *body = S->getBody();
-    hadTypeError |= typeCheckStmt(body);
+    typeCheckStmt(body);
     S->setBody(body);
-
-    return hadTypeError;
   }
 
   Stmt *visitDoCatchStmt(DoCatchStmt *S) {
@@ -899,20 +884,18 @@
     // entire construct.
     AddLabeledStmt loopNest(*this, S);
 
-    bool hadTypeError = false;
-
     // Type-check the 'do' body.  Type failures in here will generally
     // not cause type failures in the 'catch' clauses.
     Stmt *newBody = S->getBody();
-    hadTypeError |= typeCheckStmt(newBody);
+    typeCheckStmt(newBody);
     S->setBody(newBody);
 
     // Check all the catch clauses independently.
     for (auto clause : S->getCatches()) {
-      hadTypeError |= checkCatchStmt(clause);
+      checkCatchStmt(clause);
     }
     
-    return hadTypeError ? nullptr : S;
+    return S;
   }
 
   Stmt *visitFailStmt(FailStmt *S) {
@@ -925,8 +908,6 @@
 } // end anonymous namespace
 
 bool TypeChecker::typeCheckCatchPattern(CatchStmt *S, DeclContext *DC) {
-  bool hadTypeError = false;
-
   // Grab the standard exception type.
   Type exnType = getExceptionType(DC, S->getCatchLoc());
 
@@ -945,15 +926,11 @@
             var->overwriteType(ErrorType::get(Context));
             var->setInvalid();
         });
-      hadTypeError = true;
     }
 
     S->setErrorPattern(pattern);
-  } else {
-    hadTypeError = true;
   }
-
-  return hadTypeError;
+  return false;
 }
   
 void TypeChecker::checkIgnoredExpr(Expr *E) {
@@ -1073,14 +1050,10 @@
       if (isDiscarded)
         options |= TypeCheckExprFlags::IsDiscarded;
 
-      if (TC.typeCheckExpression(SubExpr, DC, Type(), CTP_Unused, options)) {
-        elem = SubExpr;
-        continue;
-      }
-      
-      if (isDiscarded)
+      bool hadTypeError = TC.typeCheckExpression(SubExpr, DC, Type(),
+                                                 CTP_Unused, options);
+      if (isDiscarded && !hadTypeError)
         TC.checkIgnoredExpr(SubExpr);
-      
       elem = SubExpr;
       continue;
     }
@@ -1091,8 +1064,8 @@
           (Loc == EndTypeCheckLoc || SM.isBeforeInBuffer(EndTypeCheckLoc, Loc)))
         break;
 
-      if (!typeCheckStmt(SubStmt))
-        elem = SubStmt;
+      typeCheckStmt(SubStmt);
+      elem = SubStmt;
       continue;
     }
 
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 2feeef7..5ed768a 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -1220,7 +1220,7 @@
 
   // We allow a type to conform to a protocol that is less available than
   // the type itself. This enables a type to retroactively model or directly
-  // conform to a protocl only available on newer OSes and yet still be used on
+  // conform to a protocol only available on newer OSes and yet still be used on
   // older OSes.
   // To support this, inside inheritance clauses we allow references to
   // protocols that are unavailable in the current type refinement context.
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 94fe210..ea44419 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1225,7 +1225,7 @@
   /// contextual type.
   ///
   /// \returns true if an error occurred, false otherwise.
-  bool coerceParameterListToType(ClosureExpr *CE, AnyFunctionType *closureType);
+  bool coerceParameterListToType(ParameterList *P, DeclContext *dc, Type type);
 
   
   /// Type-check an initialized variable pattern declaration.
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index d93738d..e0d9b4e 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -2278,6 +2278,8 @@
     }
 
     auto *bodyParams0 = readParameterList();
+    bodyParams0->get(0)->setImplicit();  // self is implicit.
+    
     auto *bodyParams1 = readParameterList();
     assert(bodyParams0 && bodyParams1 && "missing parameters for constructor");
     ctor->setParameterLists(bodyParams0->get(0), bodyParams1);
@@ -2541,6 +2543,10 @@
     for (unsigned i = 0, e = numParamPatterns; i != e; ++i)
       paramLists.push_back(readParameterList());
 
+    // If the first parameter list is (self), mark it implicit.
+    if (numParamPatterns && DC->isTypeContext())
+      paramLists[0]->get(0)->setImplicit();
+    
     fn->setDeserializedSignature(paramLists,
                                  TypeLoc::withoutLoc(signature->getResult()));
 
@@ -2967,7 +2973,7 @@
                                                SourceLoc(), TypeLoc(), DC);
     declOrOffset = subscript;
 
-    subscript->setIndices(readParameterList());    
+    subscript->setIndices(readParameterList());
     subscript->getElementTypeLoc() = TypeLoc::withoutLoc(getType(elemTypeID));
     
     configureStorage(subscript, rawStorageKind,
@@ -3095,6 +3101,8 @@
 
     dtor->setAccessibility(cast<ClassDecl>(DC)->getFormalAccess());
     auto *selfParams = readParameterList();
+    selfParams->get(0)->setImplicit();  // self is implicit.
+
     assert(selfParams && "Didn't get self pattern?");
     dtor->setSelfDecl(selfParams->get(0));
 
diff --git a/stdlib/public/core/FloatingPoint.swift.gyb b/stdlib/public/core/FloatingPoint.swift.gyb
index 545837a..08f5fe7 100644
--- a/stdlib/public/core/FloatingPoint.swift.gyb
+++ b/stdlib/public/core/FloatingPoint.swift.gyb
@@ -181,7 +181,7 @@
   @_transparent public
   init() {
     let zero: Int64 = 0
-    self._value = Builtin.uitofp_Int64_FPIEEE${bits}(zero._value)
+    self._value = Builtin.sitofp_Int64_FPIEEE${bits}(zero._value)
   }
 
   @_transparent 
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 8f1ca5a..a953be7 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -2632,13 +2632,8 @@
 swift::swift_conformsToProtocol(const Metadata *type,
                                 const ProtocolDescriptor *protocol) {
   auto &C = Conformances.get();
-  
-  // Install callbacks for tracking when a new dylib is loaded so we can
-  // scan it.
   auto origType = type;
-  
   unsigned numSections = 0;
-
   ConformanceCacheEntry *foundEntry;
 
 recur:
diff --git a/stdlib/public/stubs/Availability.mm b/stdlib/public/stubs/Availability.mm
index 3bd99b9..3d13741 100644
--- a/stdlib/public/stubs/Availability.mm
+++ b/stdlib/public/stubs/Availability.mm
@@ -1,4 +1,4 @@
-//===--- Availability.mm - Swift Language API Availability Support---------===//
+//===--- Availability.mm - Swift Language API Availability Support --------===//
 //
 // This source file is part of the Swift.org open source project
 //
diff --git a/test/1_stdlib/StringTraps.swift b/test/1_stdlib/StringTraps.swift
index be16998..3fb0f04 100644
--- a/test/1_stdlib/StringTraps.swift
+++ b/test/1_stdlib/StringTraps.swift
@@ -7,10 +7,7 @@
 // RUN: %target-run %t/a.out_Release
 // REQUIRES: executable_test
 
-// XFAIL: linux
-
 import StdlibUnittest
-import Foundation
 
 // Also import modules which are used by StdlibUnittest internally. This
 // workaround is needed to link all required libraries in case we compile
diff --git a/test/BuildConfigurations/pound-if-top-level-3.swift b/test/BuildConfigurations/pound-if-top-level-3.swift
index 9d66539..86f21c8 100644
--- a/test/BuildConfigurations/pound-if-top-level-3.swift
+++ b/test/BuildConfigurations/pound-if-top-level-3.swift
@@ -1,6 +1,5 @@
 // RUN: %target-parse-verify-swift
 
-// e xpected-error@+1{{unexpected configuration expression type}}
 #if arch(x86_64)
 // expected-error@+2{{expected '{' in protocol type}}
 // expected-error@+1{{expected #else or #endif at end of configuration block}}
diff --git a/test/Constraints/dictionary_literal.swift b/test/Constraints/dictionary_literal.swift
index 6c3b6c4..579f7ff 100644
--- a/test/Constraints/dictionary_literal.swift
+++ b/test/Constraints/dictionary_literal.swift
@@ -59,3 +59,6 @@
 var _: Dictionary<String, Int>? = ["foo" : 1.0]  // expected-error {{cannot convert value of type 'Double' to expected dictionary value type 'Int'}}
 
 
+// <rdar://problem/24058895> QoI: Should handle [] in dictionary contexts better
+var _: [Int: Int] = []  // expected-error {{use [:] to get an empty dictionary literal}} {{22-22=:}}
+
diff --git a/test/IDE/coloring.swift b/test/IDE/coloring.swift
index 5d8f65a..cff1b68 100644
--- a/test/IDE/coloring.swift
+++ b/test/IDE/coloring.swift
@@ -433,6 +433,10 @@
 // CHECK: <doc-comment-block>/**/</doc-comment-block>
 // CHECK: <kw>func</kw> malformedBlockComment(f : () <kw>throws</kw> -> ()) <attr-builtin>rethrows</attr-builtin> {}
 
+//: playground doc comment line
+func playgroundCommentLine(f : () throws -> ()) rethrows {}
+// CHECK: <comment-line>//: playground doc comment line</comment-line>
+
 
 "--\"\(x) --"
 // CHECK: <str>"--\"</str>\<anchor>(</anchor>x<anchor>)</anchor><str> --"</str>
diff --git a/test/IDE/coloring_playground.swift b/test/IDE/coloring_playground.swift
new file mode 100644
index 0000000..61c666e
--- /dev/null
+++ b/test/IDE/coloring_playground.swift
@@ -0,0 +1,16 @@
+// RUN: %target-swift-ide-test -syntax-coloring -playground -source-filename %s | FileCheck %s
+// RUN: %target-swift-ide-test -syntax-coloring -playground -typecheck -source-filename %s | FileCheck %s
+
+//: playground doc comment line
+func playgroundCommentLine(f : () throws -> ()) rethrows {}
+// CHECK: <doc-comment-line>//: playground doc comment line
+
+// Keep this as the last test
+/**
+  Trailing off ...
+func unterminatedBlockComment() {}
+// CHECK: <comment-line>// Keep this as the last test</comment-line>
+// CHECK: <doc-comment-block>/**
+// CHECK:  Trailing off ...
+// CHECK:  func unterminatedBlockComment() {}
+// CHECK:  </doc-comment-block>
diff --git a/test/IDE/complete_literal.swift b/test/IDE/complete_literal.swift
index 85b46a5..43a1e4e 100644
--- a/test/IDE/complete_literal.swift
+++ b/test/IDE/complete_literal.swift
@@ -2,6 +2,7 @@
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LITERAL2 | FileCheck %s -check-prefix=LITERAL2
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LITERAL3 | FileCheck %s -check-prefix=LITERAL3
 // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LITERAL4 | FileCheck %s -check-prefix=LITERAL4
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=LITERAL5 | FileCheck %s -check-prefix=LITERAL5
 
 {
   1.#^LITERAL1^#
@@ -48,3 +49,14 @@
 // LITERAL4-DAG:     Decl[InstanceMethod]/CurrNominal:   insertContentsOf({#(newElements): S#}, {#at: Index#})[#Void#]; name=insertContentsOf(newElements: S, at: Index){{$}}
 // LITERAL4-DAG:     Decl[InstanceMethod]/CurrNominal:   removeAtIndex({#(i): Index#})[#Character#]; name=removeAtIndex(i: Index){{$}}
 // LITERAL4-DAG:     Decl[InstanceVar]/CurrNominal:      lowercaseString[#String#]; name=lowercaseString{{$}}
+
+func giveMeAString() -> Int {
+  // rdar://22637799
+  return "Here's a string".#^LITERAL5^# // try .characters.count here
+}
+
+// LITERAL5-DAG:     Decl[InstanceVar]/CurrNominal:      characters[#String.CharacterView#]{{; name=.+$}}
+// LITERAL5-DAG:     Decl[InstanceVar]/CurrNominal:      endIndex[#Index#]{{; name=.+$}}
+// LITERAL5-DAG:     Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: reserveCapacity({#(n): Int#})[#Void#]{{; name=.+$}}
+// LITERAL5-DAG:     Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: append({#(c): Character#})[#Void#]{{; name=.+$}}
+// LITERAL5-DAG:     Decl[InstanceMethod]/CurrNominal/TypeRelation[Invalid]: appendContentsOf({#(newElements): S#})[#Void#]{{; name=.+$}}
diff --git a/test/IDE/print_omit_needless_words.swift b/test/IDE/print_omit_needless_words.swift
index ddf0a56..a4469dc 100644
--- a/test/IDE/print_omit_needless_words.swift
+++ b/test/IDE/print_omit_needless_words.swift
@@ -64,6 +64,9 @@
 // Note: Typedefs with a "_t" suffix".
 // CHECK-FOUNDATION: func subtract(_: Int32) -> NSNumber
 
+// Note: Respect the getter name for BOOL properties.
+// CHECK-FOUNDATION: var isMakingHoney: Bool
+
 // Note: multi-word enum name matching; "with" splits the first piece.
 // CHECK-FOUNDATION: func someMethod(deprecatedOptions _: NSDeprecatedOptions = [])
 
@@ -138,8 +141,8 @@
 // Collection element types.
 // CHECK-FOUNDATION: func adding(_: AnyObject) -> Set<NSObject>
 
-// Boolean properties get an "is" prefix.
-// CHECK-FOUNDATION: var isEmpty: Bool { get }
+// Boolean properties follow the getter.
+// CHECK-FOUNDATION: var empty: Bool { get }
 // CHECK-FOUNDATION: func nonEmpty() -> Bool
 // CHECK-FOUNDATION: var isStringSet: Bool { get }
 // CHECK-FOUNDATION: var wantsAUnion: Bool { get }
@@ -147,6 +150,9 @@
 // CHECK-FOUNDATION: var appliesForAJob: Bool { get }
 // CHECK-FOUNDATION: var setShouldBeInfinite: Bool { get }
 
+// "UTF8" initialisms.
+// CHECK-FOUNDATION: init?(utf8String: UnsafePointer<Int8>)
+
 // Note: class method name stripping context type.
 // CHECK-APPKIT: class func red() -> NSColor
 
diff --git a/test/IRGen/metadata_dominance.swift b/test/IRGen/metadata_dominance.swift
new file mode 100644
index 0000000..5e07095
--- /dev/null
+++ b/test/IRGen/metadata_dominance.swift
@@ -0,0 +1,51 @@
+// RUN: %target-swift-frontend -emit-ir -primary-file %s | FileCheck %s
+
+func use_metadata<F>(f: F) {}
+
+func voidToVoid() {}
+func intToInt(x: Int) -> Int { return x }
+
+func cond() -> Bool { return true }
+
+// CHECK: define hidden void @_TF18metadata_dominance5test1FT_T_()
+func test1() {
+// CHECK: call i1 @_TF18metadata_dominance4condFT_Sb()
+  if cond() {
+// CHECK: [[T0:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T0]])
+    use_metadata(voidToVoid)
+// CHECK: call i1 @_TF18metadata_dominance4condFT_Sb()
+// CHECK-NOT: @_TMaFT_T_
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T0]])
+    if cond() {
+      use_metadata(voidToVoid)
+    } else {
+// CHECK-NOT: @_TMaFT_T_
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T0]])
+      use_metadata(voidToVoid)
+    }
+  }
+// CHECK: [[T1:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T1]])
+  use_metadata(voidToVoid)
+}
+
+// CHECK: define hidden void @_TF18metadata_dominance5test2FT_T_()
+func test2() {
+// CHECK: call i1 @_TF18metadata_dominance4condFT_Sb()
+  if cond() {
+// CHECK: call i1 @_TF18metadata_dominance4condFT_Sb()
+// CHECK: [[T0:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T0]])
+    if cond() {
+      use_metadata(voidToVoid)
+    } else {
+// CHECK: [[T1:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T1]])
+      use_metadata(voidToVoid)
+    }
+  }
+// CHECK: [[T2:%.*]] = call %swift.type* @_TMaFT_T_()
+// CHECK: call void @_TF18metadata_dominance12use_metadataurFxT_(%swift.opaque* {{.*}}, %swift.type* [[T2]])
+  use_metadata(voidToVoid)
+}
diff --git a/test/Inputs/clang-importer-sdk/usr/include/Foundation.h b/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
index ac3d8cd..785dfcb 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
@@ -985,3 +985,7 @@
 int variadicFunc1(int A, ...);
 
 int variadicFunc2(int A, ...);
+
+@interface NSString (UTF8)
+-(nullable instancetype)initWithUTF8String:(const char *)bytes;
+@end
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index 2d20044..1201a70 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -318,7 +318,7 @@
   // CHECK-NEXT: return %2 : $Int
 }
 
-// Make sure that we generate direct function calls for out struct protocl
+// Make sure that we generate direct function calls for out struct protocol
 // witness since structs don't do virtual calls for methods.
 //
 // *NOTE* Even though at first glance the copy_addr looks like a leak
diff --git a/test/SILOptimizer/devirt_default_case.swift b/test/SILOptimizer/devirt_default_case.swift
index 871e64e..fc0d989 100644
--- a/test/SILOptimizer/devirt_default_case.swift
+++ b/test/SILOptimizer/devirt_default_case.swift
@@ -106,7 +106,7 @@
 // B has its own implementation.
 @inline(never)
 func foo(a: A3) -> Int {
-// Check that call to A3.f() can be devirualized.
+// Check that call to A3.f() can be devirtualized.
 //
 // CHECK-LABEL: sil{{( hidden)?}} [noinline] @_TF19devirt_default_case3fooFCS_2A3Si
 // CHECK: function_ref @{{.*}}TFC19devirt_default_case2B31f
diff --git a/test/SILOptimizer/postdomtree_verification_crash.sil b/test/SILOptimizer/postdomtree_verification_crash.sil
new file mode 100644
index 0000000..96fcd1d
--- /dev/null
+++ b/test/SILOptimizer/postdomtree_verification_crash.sil
@@ -0,0 +1,22 @@
+// RUN: %target-sil-opt -enable-sil-verify-all  -sil-verify-without-invalidation %s -stack-promotion
+
+// Check if post-dominator verification does not crash on multiple roots.
+// We run stack promotion because it requests the post-dominator analysis.
+
+sil_stage canonical
+
+import Builtin
+import Swift
+
+sil @testit : $@convention(thin) () -> () {
+bb0:
+  cond_br undef, bb1, bb2
+
+bb1:
+  br bb1
+
+bb2:
+  %r = tuple ()
+  return %r : $()
+}
+
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index 662f7fc..0e66985 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -2,7 +2,6 @@
 
 import Builtin
 import Swift
-import Foundation
 
 // Test SIL Global variable.
 // TODO: Handling of global variables has changed: the globalinit_* symbols are now mangled.
@@ -212,19 +211,6 @@
   %7 = return %6 : $()
 }
 
-// CHECK-LABEL: @objc_classes : $@convention(thin) (@thick NSObject.Type) -> ()
-sil [fragile] @objc_classes : $@convention(thin) (@thick NSObject.Type) -> () {
-bb0(%0 : $@thick NSObject.Type):
-  %1 = thick_to_objc_metatype %0 : $@thick NSObject.Type to $@objc_metatype NSObject.Type
-  // CHECK: %2 = alloc_ref_dynamic [objc] %1 : $@objc_metatype NSObject.Type, $NSObject
-  %2 = alloc_ref_dynamic [objc] %1 : $@objc_metatype NSObject.Type, $NSObject
-  %3 = value_metatype $@thick NSObject.Type, %2 : $NSObject
-  dealloc_partial_ref %2 : $NSObject, %3 : $@thick NSObject.Type
-
-  %void = tuple ()
-  return %void : $()
-} // CHECK: {{^}$}}
-
 // Generated from:
 // func archetype_member_ref<T : Runcible>(x: T) {
 //   x.free_method()
@@ -610,15 +596,6 @@
   return %4 : $Int
 }
 
-class Bas : NSObject {
-  var strRealProp : String
-  override init()
-}
-sil [fragile] @test_super_method : $@convention(method) (@guaranteed Bas) -> Bas
-
-sil [fragile] @swift_StringToNSString : $@convention(thin) (@inout String) -> @owned NSString
-sil [fragile] @_TFSSCfMSSFT_SS : $@convention(thin) (@thin String.Type) -> @owned String
-
 // CHECK-LABEL: sil public_external [fragile] @test_builtin_func_ref
 sil [fragile] @test_builtin_func_ref : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> Builtin.Int1 {
 bb0(%0 : $Builtin.Int1, %1 : $Builtin.Int1):
@@ -969,19 +946,6 @@
   return %b : $@convention(block) () -> ()
 }
 
-protocol SomeClassProtocol : class {}
-
-// CHECK-LABEL: sil public_external [fragile] @metatype_to_object
-// CHECK:         {{%.*}} = objc_metatype_to_object {{%.*}} : $@objc_metatype SomeClass.Type to $AnyObject
-// CHECK:         {{%.*}} = objc_existential_metatype_to_object {{%.*}} : $@objc_metatype SomeClassProtocol.Type to $AnyObject
-sil [fragile] @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject) {
-entry(%a : $@objc_metatype SomeClass.Type, %b : $@objc_metatype SomeClassProtocol.Type):
-  %x = objc_metatype_to_object %a : $@objc_metatype SomeClass.Type to $AnyObject
-  %y = objc_existential_metatype_to_object %b : $@objc_metatype SomeClassProtocol.Type to $AnyObject
-  %z = tuple (%x : $AnyObject, %y : $AnyObject)
-  return %z : $(AnyObject, AnyObject)
-}
-
 // CHECK-LABEL: sil public_external [fragile] @bitcasts : $@convention(thin) (@owned Class1) -> @owned (Class2, Int) {
 // CHECK:  bb0(%0 : $Class1):
 // CHECK-NEXT:    %1 = unchecked_ref_cast %0 : $Class1 to $Class2
@@ -996,16 +960,6 @@
   return %3 : $(Class2, Int)
 }
 
-@objc protocol ObjCProto {}
-
-// CHECK-LABEL: sil public_external [fragile] @protocol_conversion
-sil [fragile] @protocol_conversion : $@convention(thin) () -> @owned Protocol {
-entry:
-  // CHECK: {{%.*}} = objc_protocol #ObjCProto : $Protocol
-  %p = objc_protocol #ObjCProto : $Protocol
-  return %p : $Protocol
-}
-
 sil [fragile] @block_invoke : $@convention(c) (@inout_aliasable @block_storage Int) -> ()
 
 
@@ -1310,7 +1264,6 @@
   %13 = function_ref @return_constant : $@convention(thin) () -> Int
   %23 = function_ref @existentials : $@convention(thin) (@in P) -> ()
   %25 = function_ref @classes : $@convention(thin) () -> ()
-  %26 = function_ref @objc_classes : $@convention(thin) (@thick NSObject.Type) -> ()
   %27 = function_ref @_TF4todo18erasure_from_protoFT1xPS_8RuncibleS_8Bendable__PS0__ : $@convention(thin) (@out Runcible, @in protocol<Bendable, Runcible>) -> ()
   %29 = function_ref @_TF4todo18class_bound_methodFT1xPS_10ClassBound__T_ : $@convention(thin) (@owned ClassBound) -> ()
   %31 = function_ref @_TFV6struct5AlephCfMS0_FT1aCS_3Ref1bVS_3Val_S0_ : $@convention(thin) (Ref, Val, @thin Aleph.Type) -> Aleph
@@ -1336,7 +1289,6 @@
   %73 = function_ref @test_basic_block_arguments : $@convention(thin) (Builtin.Int1) -> Builtin.Word
   %75 = function_ref @test_cond_branch_basic_block_args : $@convention(thin) (Int, Builtin.Int1) -> Int
 
-  %79 = function_ref @test_super_method : $@convention(method) (@guaranteed Bas) -> Bas
   %81 = function_ref @test_builtin_func_ref : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> Builtin.Int1
   %83 = function_ref @test_dealloc_ref : $@convention(thin) () -> ()
   %84 = function_ref @test_dealloc_partial_ref : $@convention(thin) () -> ()
@@ -1362,9 +1314,7 @@
   %118 = function_ref @cond_fail_test : $@convention(thin) Builtin.Int1 -> ()
 
   %124 = function_ref @block_storage_type : $@convention(thin) Int -> @convention(block) () -> ()
-  %125 = function_ref @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject)
   %127 = function_ref @bitcasts : $@convention(thin) (@owned Class1) -> @owned (Class2, Int)
-  %126 = function_ref @protocol_conversion : $@convention(thin) () -> @owned Protocol
   %133 = function_ref @test_try_apply : $@convention(thin) (@convention(thin) () -> @error ErrorType) -> @error ErrorType
   %135 = function_ref @test_try_nothrow : $@convention(thin) (@convention(thin) () -> @error ErrorType) -> ()
   %134 = function_ref @box_type : $@convention(thin) (@box Int, Int) -> ()
diff --git a/test/Serialization/Inputs/def_basic_objc.sil b/test/Serialization/Inputs/def_basic_objc.sil
new file mode 100644
index 0000000..7f20e7d
--- /dev/null
+++ b/test/Serialization/Inputs/def_basic_objc.sil
@@ -0,0 +1,70 @@
+sil_stage raw // CHECK: sil_stage raw
+
+import Builtin
+import Swift
+import Foundation
+
+protocol SomeProtocol { }
+class SomeClass : SomeProtocol { }
+
+// CHECK-LABEL: @objc_classes : $@convention(thin) (@thick NSObject.Type) -> ()
+sil [fragile] @objc_classes : $@convention(thin) (@thick NSObject.Type) -> () {
+bb0(%0 : $@thick NSObject.Type):
+  %1 = thick_to_objc_metatype %0 : $@thick NSObject.Type to $@objc_metatype NSObject.Type
+  // CHECK: %2 = alloc_ref_dynamic [objc] %1 : $@objc_metatype NSObject.Type, $NSObject
+  %2 = alloc_ref_dynamic [objc] %1 : $@objc_metatype NSObject.Type, $NSObject
+  %3 = value_metatype $@thick NSObject.Type, %2 : $NSObject
+  dealloc_partial_ref %2 : $NSObject, %3 : $@thick NSObject.Type
+
+  %void = tuple ()
+  return %void : $()
+} // CHECK: {{^}$}}
+
+class Bas : NSObject {
+  var strRealProp : String
+  override init()
+}
+
+sil [fragile] @test_super_method : $@convention(method) (@guaranteed Bas) -> Bas
+sil [fragile] @swift_StringToNSString : $@convention(thin) (@inout String) -> @owned NSString
+sil [fragile] @_TFSSCfMSSFT_SS : $@convention(thin) (@thin String.Type) -> @owned String
+
+protocol SomeClassProtocol : class {}
+
+// CHECK-LABEL: sil public_external [fragile] @metatype_to_object
+// CHECK:         {{%.*}} = objc_metatype_to_object {{%.*}} : $@objc_metatype SomeClass.Type to $AnyObject
+// CHECK:         {{%.*}} = objc_existential_metatype_to_object {{%.*}} : $@objc_metatype SomeClassProtocol.Type to $AnyObject
+sil [fragile] @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject) {
+entry(%a : $@objc_metatype SomeClass.Type, %b : $@objc_metatype SomeClassProtocol.Type):
+  %x = objc_metatype_to_object %a : $@objc_metatype SomeClass.Type to $AnyObject
+  %y = objc_existential_metatype_to_object %b : $@objc_metatype SomeClassProtocol.Type to $AnyObject
+  %z = tuple (%x : $AnyObject, %y : $AnyObject)
+  return %z : $(AnyObject, AnyObject)
+}
+
+@objc protocol ObjCProto {}
+
+// CHECK-LABEL: sil public_external [fragile] @protocol_conversion
+sil [fragile] @protocol_conversion : $@convention(thin) () -> @owned Protocol {
+entry:
+  // CHECK: {{%.*}} = objc_protocol #ObjCProto : $Protocol
+  %p = objc_protocol #ObjCProto : $Protocol
+  return %p : $Protocol
+}
+
+public func serialize_all() {
+}
+
+sil [fragile] [transparent] @_TF14def_basic_objc13serialize_allFT_T_ : $@convention(thin) () -> () {
+bb0:
+  %26 = function_ref @objc_classes : $@convention(thin) (@thick NSObject.Type) -> ()
+
+  %79 = function_ref @test_super_method : $@convention(method) (@guaranteed Bas) -> Bas
+
+  %125 = function_ref @metatype_to_object : $@convention(thin) (@objc_metatype SomeClass.Type, @objc_metatype SomeClassProtocol.Type) -> @owned (AnyObject, AnyObject)
+
+  %126 = function_ref @protocol_conversion : $@convention(thin) () -> @owned Protocol
+
+  %119 = tuple ()
+  return %119 : $()
+}
diff --git a/test/Serialization/basic_sil.swift b/test/Serialization/basic_sil.swift
index 731f5ab..3d10937 100644
--- a/test/Serialization/basic_sil.swift
+++ b/test/Serialization/basic_sil.swift
@@ -1,15 +1,13 @@
 // RUN: rm -rf %t
 // RUN: mkdir %t
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -I %S/../Inputs/clang-importer-sdk/swift-modules -emit-module -Xfrontend -disable-diagnostic-passes -Xfrontend -sil-serialize-all -force-single-frontend-invocation -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
+// RUN: %target-build-swift -emit-module -Xfrontend -disable-diagnostic-passes -Xfrontend -sil-serialize-all -force-single-frontend-invocation -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
 // RUN: llvm-bcanalyzer %t/def_basic.swiftmodule | FileCheck %s
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck %S/Inputs/def_basic.sil
+// RUN: %target-build-swift -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck %S/Inputs/def_basic.sil
 
 // RUN: rm -rf %t
 // RUN: mkdir %t
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-module -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -Xfrontend -sil-serialize-all -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
-// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck -check-prefix=CHECK_DECL %S/Inputs/def_basic.sil
-
-// XFAIL: linux
+// RUN: %target-build-swift -emit-module -Xfrontend -disable-diagnostic-passes -force-single-frontend-invocation -Xfrontend -sil-serialize-all -o %t/def_basic.swiftmodule %S/Inputs/def_basic.sil
+// RUN: %target-build-swift -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck -check-prefix=CHECK_DECL %S/Inputs/def_basic.sil
 
 // This test currently is written such that no optimizations are assumed.
 // REQUIRES: swift_test_mode_optimize_none
diff --git a/test/Serialization/basic_sil_objc.swift b/test/Serialization/basic_sil_objc.swift
new file mode 100644
index 0000000..998f110
--- /dev/null
+++ b/test/Serialization/basic_sil_objc.swift
@@ -0,0 +1,17 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -I %S/../Inputs/clang-importer-sdk/swift-modules -emit-module -Xfrontend -disable-diagnostic-passes -Xfrontend -sil-serialize-all -force-single-frontend-invocation -o %t/def_basic_objc.swiftmodule %S/Inputs/def_basic_objc.sil
+// RUN: llvm-bcanalyzer %t/def_basic_objc.swiftmodule | FileCheck %s
+// RUN: %target-build-swift -Xfrontend %clang-importer-sdk -emit-silgen -Xfrontend -sil-link-all -I %t %s | FileCheck %S/Inputs/def_basic_objc.sil
+
+// This test currently is written such that no optimizations are assumed.
+// REQUIRES: swift_test_mode_optimize_none
+// REQUIRES: objc_interop
+
+// CHECK-NOT: UnknownCode
+
+import def_basic_objc
+
+func test_all() {
+  serialize_all()
+}
diff --git a/test/expr/closure/basic.swift b/test/expr/closure/basic.swift
index e68d9d5..800922b 100644
--- a/test/expr/closure/basic.swift
+++ b/test/expr/closure/basic.swift
@@ -37,7 +37,6 @@
 // Closures with argument and parameter names.
 func argAndParamNames() -> Int {
   let f1: (x: Int, y: Int) -> Int = { (a x, b y) in x + y }
-  let _: (x: Int, z: Int) -> Int = { (a x, b y) in x + y }
   f1(x: 1, y: 2)
   return f1(x: 1, y: 2)
 }
diff --git a/tools/SourceKit/lib/Support/Tracing.cpp b/tools/SourceKit/lib/Support/Tracing.cpp
index c50f65c..00321e8 100644
--- a/tools/SourceKit/lib/Support/Tracing.cpp
+++ b/tools/SourceKit/lib/Support/Tracing.cpp
@@ -22,16 +22,16 @@
 
 
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // General
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 static std::atomic<bool> tracing_enabled(false);
 static std::atomic<uint64_t> operation_id(0);
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Consumers
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 struct TraceConsumerListNode {
   trace::TraceConsumer *const Consumer;
   TraceConsumerListNode *Next;
@@ -39,9 +39,9 @@
 static std::atomic<TraceConsumerListNode *> consumers(nullptr);
 
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Trace commands
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 // Is tracing enabled
 bool trace::enabled() {
diff --git a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp
index 214ae46..d5ee3b2 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp
@@ -97,9 +97,9 @@
                           sourcekitd_interrupted_connection_handler_t handler) {
 }
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // sourcekitd_request_sync
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 sourcekitd_response_t sourcekitd_send_request_sync(sourcekitd_object_t req) {
   dispatch_semaphore_t sema = dispatch_semaphore_create(0);
diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
index 64b9e43..0e4191f 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
@@ -108,9 +108,9 @@
   });
 }
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // sourcekitd_request_sync
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 static xpc_connection_t getGlobalConnection();
 
diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/tracer.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/tracer.cpp
index 1d518de..e7be374 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/tracer.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/tracer.cpp
@@ -38,9 +38,9 @@
 
 
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Generic
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 static std::string trace_root_dir;
 
@@ -150,9 +150,9 @@
 
 
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // State
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 class State {
   typedef std::map<uint64_t, OperationInfo> OperationsType;
@@ -307,9 +307,9 @@
 
 
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Init & trace
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 void initializeTracing() {
   const char *EnvOpt = ::getenv("SOURCEKIT_TRACE_ROOT");
diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XpcTracing.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XpcTracing.cpp
index 2a767e0..d64dba2 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XpcTracing.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XpcTracing.cpp
@@ -25,9 +25,9 @@
 
 
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // General
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 static std::atomic<uint64_t> operation_id(0);
 static uint64_t tracing_session = llvm::sys::TimeValue::now().msec();
@@ -92,9 +92,9 @@
 
 
 
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 // Trace consumer
-//----------------------------------------------------------------------------//
+//===----------------------------------------------------------------------===//
 
 class XpcTraceConsumer : public SourceKit::trace::TraceConsumer {
 public:
diff --git a/tools/swift-ide-test/KnownObjCMethods.def b/tools/swift-ide-test/KnownObjCMethods.def
index 2cde179..4ecd53e 100644
--- a/tools/swift-ide-test/KnownObjCMethods.def
+++ b/tools/swift-ide-test/KnownObjCMethods.def
@@ -13,7 +13,7 @@
 // This file defines the database of known methods for various
 // Objective-C classes, along with flags that describe how their
 // import into Swift should be altered.
-// ===---------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 
 // INSTANCE_METHOD(ClassName, Selector, Options)
 // CLASS_METHOD(ClassName, Selector, Options)
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index 354af1b..b9f29ef 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -333,6 +333,11 @@
           llvm::cl::desc("Type check the AST"),
           llvm::cl::init(false));
 
+static llvm::cl::opt<bool>
+Playground("playground",
+           llvm::cl::desc("Whether coloring in playground"),
+           llvm::cl::init(false));
+
 // AST printing options.
 
 static llvm::cl::opt<bool>
@@ -769,7 +774,8 @@
 static int doSyntaxColoring(const CompilerInvocation &InitInvok,
                             StringRef SourceFilename,
                             bool TerminalOutput,
-                            bool RunTypeChecker) {
+                            bool RunTypeChecker,
+                            bool Playground) {
   CompilerInvocation Invocation(InitInvok);
   Invocation.addInputFilename(SourceFilename);
   Invocation.getLangOptions().DisableAvailabilityChecking = false;
@@ -779,6 +785,7 @@
   // Display diagnostics to stderr.
   PrintingDiagnosticConsumer PrintDiags;
   CI.addDiagnosticConsumer(&PrintDiags);
+  Invocation.getLangOptions().Playground = Playground;
   if (CI.setup(Invocation))
     return 1;
   if (!RunTypeChecker)
@@ -2501,7 +2508,8 @@
     ExitCode = doSyntaxColoring(InitInvok,
                                 options::SourceFilename,
                                 options::TerminalOutput,
-                                options::Typecheck);
+                                options::Typecheck,
+                                options::Playground);
     break;
 
   case ActionType::DumpImporterLookupTable:
diff --git a/utils/GYBUnicodeDataUtils.py b/utils/GYBUnicodeDataUtils.py
index 8f2fdff..2007e37 100644
--- a/utils/GYBUnicodeDataUtils.py
+++ b/utils/GYBUnicodeDataUtils.py
@@ -70,7 +70,7 @@
             self.symbolic_values[v] = k
 
         # Load the data file.
-        with codecs.open(grapheme_break_property_file_name, encoding=sys.getfilesystemencoding(), errors='strict') as f:
+        with codecs.open(grapheme_break_property_file_name, encoding='utf-8', errors='strict') as f:
             for line in f:
                 # Strip comments.
                 line = re.sub('#.*', '', line)
@@ -548,7 +548,7 @@
 
     result = []
 
-    with codecs.open(grapheme_break_test_file_name, encoding=sys.getfilesystemencoding(), errors='strict') as f:
+    with codecs.open(grapheme_break_test_file_name, encoding='utf-8', errors='strict') as f:
         for line in f:
             test = _convert_line(line)
             if test:
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 89180b7..e19af46 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -783,7 +783,7 @@
             )
             ;;
         *)
-            echo "Unknown deployment target"
+            echo "Unknown deployment target: ${t}"
             exit 1
             ;;
     esac
diff --git a/utils/name-compression/CBCGen.py b/utils/name-compression/CBCGen.py
index 763ad5d..eb1b36f 100644
--- a/utils/name-compression/CBCGen.py
+++ b/utils/name-compression/CBCGen.py
@@ -82,7 +82,7 @@
     first_letter = word[0]
 
     # Create a new entry in the Trie node if needed.
-    if not first_letter in self.children:
+    if first_letter not in self.children:
       self.children[first_letter] = Trie()
 
     # Insert the rest of the string recursively.
diff --git a/validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift b/validation-test/IDE/crashers/067-swift-constraints-constraintsystem-resolveoverload.swift
similarity index 69%
copy from validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
copy to validation-test/IDE/crashers/067-swift-constraints-constraintsystem-resolveoverload.swift
index addcef7..cd0e8f9 100644
--- a/validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
+++ b/validation-test/IDE/crashers/067-swift-constraints-constraintsystem-resolveoverload.swift
@@ -1,3 +1,4 @@
 // RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
 // REQUIRES: asserts
-t=0.#^A^#
\ No newline at end of file
+struct d{func b
+let g=b<a let a=enum b<j where g:p:#^A^#
\ No newline at end of file
diff --git a/validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift b/validation-test/IDE/crashers/068-swift-typechecker-resolvetypewitness.swift
similarity index 71%
rename from validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
rename to validation-test/IDE/crashers/068-swift-typechecker-resolvetypewitness.swift
index addcef7..9e9c07d 100644
--- a/validation-test/IDE/crashers/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
+++ b/validation-test/IDE/crashers/068-swift-typechecker-resolvetypewitness.swift
@@ -1,3 +1,5 @@
 // RUN: not --crash %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
 // REQUIRES: asserts
-t=0.#^A^#
\ No newline at end of file
+:#^A^#func a
+protocol a{class A:a
+typealias e:A.e
\ No newline at end of file
diff --git a/validation-test/IDE/crashers_fixed/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift b/validation-test/IDE/crashers_fixed/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
new file mode 100644
index 0000000..d5ca599
--- /dev/null
+++ b/validation-test/IDE/crashers_fixed/005-swift-typechecker-gettypeofexpressionwithoutapplying.swift
@@ -0,0 +1,3 @@
+// RUN: %target-swift-ide-test -code-completion -code-completion-token=A -source-filename=%s
+// REQUIRES: asserts
+t=0.#^A^#
\ No newline at end of file
diff --git a/validation-test/SIL/crashers/023-swift-parser-parseexpridentifier.sil b/validation-test/SIL/crashers/023-swift-parser-parseexpridentifier.sil
new file mode 100644
index 0000000..c760397
--- /dev/null
+++ b/validation-test/SIL/crashers/023-swift-parser-parseexpridentifier.sil
@@ -0,0 +1,3 @@
+// RUN: not --crash %target-sil-opt %s
+// REQUIRES: asserts
+enum n{func p<p{p<@convention()>
\ No newline at end of file
diff --git a/validation-test/compiler_crashers/16694-swift-constraints-constraintsystem-opentype.swift b/validation-test/compiler_crashers/16694-swift-constraints-constraintsystem-opentype.swift
index 67185b2..0262c4b 100644
--- a/validation-test/compiler_crashers/16694-swift-constraints-constraintsystem-opentype.swift
+++ b/validation-test/compiler_crashers/16694-swift-constraints-constraintsystem-opentype.swift
@@ -4,4 +4,5 @@
 // Test case submitted to project by https://github.com/practicalswift (practicalswift)
 // Test case found by fuzzing
 
+// Crash type: memory error ("Invalid read of size 4")
 var a{class d{var b=B{}let c=(x:d<T{{}}class B<T where h=d>:a
diff --git a/validation-test/compiler_crashers/24394-swift-typevariabletype-implementation-getrepresentative.swift b/validation-test/compiler_crashers/24394-swift-typevariabletype-implementation-getrepresentative.swift
index 3c022a1..37c7eae 100644
--- a/validation-test/compiler_crashers/24394-swift-typevariabletype-implementation-getrepresentative.swift
+++ b/validation-test/compiler_crashers/24394-swift-typevariabletype-implementation-getrepresentative.swift
@@ -4,6 +4,7 @@
 // Test case submitted to project by https://github.com/practicalswift (practicalswift)
 // Test case found by fuzzing
 
+// Crash type: memory error ("Invalid read of size 8")
 [Void{}}struct A
 protocol A{typealias b:A func b
 class A<S:e
diff --git a/validation-test/compiler_crashers/25458-swift-archetypetype-getnestedtype.swift b/validation-test/compiler_crashers/25458-swift-archetypetype-getnestedtype.swift
index 31c97a9..f235a07 100644
--- a/validation-test/compiler_crashers/25458-swift-archetypetype-getnestedtype.swift
+++ b/validation-test/compiler_crashers/25458-swift-archetypetype-getnestedtype.swift
@@ -4,6 +4,7 @@
 // Test case submitted to project by https://github.com/practicalswift (practicalswift)
 // Test case found by fuzzing
 
+// Crash type: memory error ("Invalid read of size 8")
 class a{
 class c
 class B:A
diff --git a/validation-test/compiler_crashers/27203-swift-typeloc-iserror.swift b/validation-test/compiler_crashers/27203-swift-typeloc-iserror.swift
index 2c9a97b..b336d90 100644
--- a/validation-test/compiler_crashers/27203-swift-typeloc-iserror.swift
+++ b/validation-test/compiler_crashers/27203-swift-typeloc-iserror.swift
@@ -4,4 +4,5 @@
 // Test case submitted to project by https://github.com/practicalswift (practicalswift)
 // Test case found by fuzzing
 
+// Crash type: memory error ("Invalid read of size 4")
 class n{protocol a:d var d={class b:a
diff --git a/validation-test/compiler_crashers/27443-matchwitness.swift b/validation-test/compiler_crashers/27443-matchwitness.swift
index 667040c..e3abefd 100644
--- a/validation-test/compiler_crashers/27443-matchwitness.swift
+++ b/validation-test/compiler_crashers/27443-matchwitness.swift
@@ -4,6 +4,7 @@
 // Test case submitted to project by https://github.com/practicalswift (practicalswift)
 // Test case found by fuzzing
 
+// Crash type: memory error ("Invalid read of size 8")
 {e
 struct B:a{let t:a}
 protocol a{let t:a
diff --git a/validation-test/compiler_crashers/27754-swift-typechecker-resolvetypeincontext.swift b/validation-test/compiler_crashers/27754-swift-typechecker-resolvetypeincontext.swift
index 4d6f6e5..af1a117 100644
--- a/validation-test/compiler_crashers/27754-swift-typechecker-resolvetypeincontext.swift
+++ b/validation-test/compiler_crashers/27754-swift-typechecker-resolvetypeincontext.swift
@@ -4,4 +4,5 @@
 // Test case submitted to project by https://github.com/practicalswift (practicalswift)
 // Test case found by fuzzing
 
+// Crash type: memory error ("Invalid read of size 8")
 class d{let f=a< class a{extension{struct Q<h:a{protocol P{func<
diff --git a/validation-test/compiler_crashers/28155-swift-typechecker-validategenericfuncsignature.swift b/validation-test/compiler_crashers/28155-swift-typechecker-validategenericfuncsignature.swift
index 82709da..fe042ce 100644
--- a/validation-test/compiler_crashers/28155-swift-typechecker-validategenericfuncsignature.swift
+++ b/validation-test/compiler_crashers/28155-swift-typechecker-validategenericfuncsignature.swift
@@ -4,4 +4,5 @@
 // Test case submitted to project by https://github.com/practicalswift (practicalswift)
 // Test case found by fuzzing
 
+// Crash type: memory error ("Invalid read of size 2")
 class A{func b->Self{{{}}class B<n{let a=self
diff --git a/validation-test/compiler_crashers/28189-swift-valuedecl-settype.swift b/validation-test/compiler_crashers/28189-swift-valuedecl-settype.swift
new file mode 100644
index 0000000..d444fa9
--- /dev/null
+++ b/validation-test/compiler_crashers/28189-swift-valuedecl-settype.swift
@@ -0,0 +1,8 @@
+// RUN: not --crash %target-swift-frontend %s -parse
+// REQUIRES: asserts
+
+// Distributed under the terms of the MIT license
+// Test case submitted to project by https://github.com/practicalswift (practicalswift)
+// Test case found by fuzzing
+
+func f{{for b{}{String($0
diff --git a/validation-test/compiler_crashers/28190-swift-conformancelookuptable-expandimpliedconformances.swift b/validation-test/compiler_crashers/28190-swift-conformancelookuptable-expandimpliedconformances.swift
new file mode 100644
index 0000000..b8c5465
--- /dev/null
+++ b/validation-test/compiler_crashers/28190-swift-conformancelookuptable-expandimpliedconformances.swift
@@ -0,0 +1,11 @@
+// RUN: not --crash %target-swift-frontend %s -parse
+// REQUIRES: asserts
+
+// Distributed under the terms of the MIT license
+// Test case submitted to project by https://github.com/practicalswift (practicalswift)
+// Test case found by fuzzing
+
+protocol A:A
+protocol a:A
+struct c:a{
+let h=D
diff --git a/validation-test/compiler_crashers/26298-llvm-densemapbase.swift b/validation-test/compiler_crashers_fixed/26298-llvm-densemapbase.swift
similarity index 73%
rename from validation-test/compiler_crashers/26298-llvm-densemapbase.swift
rename to validation-test/compiler_crashers_fixed/26298-llvm-densemapbase.swift
index 5e97bbb..ee2f70a 100644
--- a/validation-test/compiler_crashers/26298-llvm-densemapbase.swift
+++ b/validation-test/compiler_crashers_fixed/26298-llvm-densemapbase.swift
@@ -1,4 +1,4 @@
-// RUN: not --crash %target-swift-frontend %s -emit-silgen
+// RUN: %target-swift-frontend %s -emit-silgen
 // Distributed under the terms of the MIT license
 // Test case submitted to project by https://github.com/airspeedswift (airspeedswift)