Merge pull request #9933 from jckarter/partial-key-path-application

Support application of AnyKeyPath/PartialKeyPath.
diff --git a/benchmark/single-source/Substring.swift b/benchmark/single-source/Substring.swift
index cb520fd..011866c 100644
--- a/benchmark/single-source/Substring.swift
+++ b/benchmark/single-source/Substring.swift
@@ -59,3 +59,155 @@
   }
 }
 
+private func equivalentWithDistinctBuffers() -> (String, Substring) {
+  var s0 = longWide
+  withUnsafeMutablePointer(to: &s0) { blackHole($0) }
+  s0 += "!"
+  
+  // These two should be equal but with distinct buffers, both refcounted.
+  let a = Substring(s0).dropFirst()
+  let b = String(a)
+  return (b, a)
+}
+
+@inline(never)
+public func run_EqualStringSubstring(_ N: Int) {
+  let (a, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    blackHole(a == b)
+  }
+}
+
+@inline(never)
+public func run_EqualSubstringString(_ N: Int) {
+  let (a, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    blackHole(b == a)
+  }
+}
+
+@inline(never)
+public func run_EqualSubstringSubstring(_ N: Int) {
+  let (_, a) = equivalentWithDistinctBuffers()
+  let (_, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    blackHole(a == b)
+  }
+}
+
+@inline(never)
+public func run_EqualSubstringSubstringGenericEquatable(_ N: Int) {
+  let (_, a) = equivalentWithDistinctBuffers()
+  let (_, b) = equivalentWithDistinctBuffers()
+  func check<T>(_ x: T, _ y: T) where T : Equatable {
+    blackHole(x == y)
+  }
+  for _ in 1...N*500 {
+    check(a, b)
+  }
+}
+
+/*
+func checkEqual<T, U>(_ x: T, _ y: U)
+where T : StringProtocol, U : StringProtocol {
+  blackHole(x == y)
+}
+
+@inline(never)
+public func run _EqualStringSubstringGenericStringProtocol(_ N: Int) {
+  let (a, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    checkEqual(a, b)
+  }
+}
+
+@inline(never)
+public func run _EqualSubstringStringGenericStringProtocol(_ N: Int) {
+  let (a, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    checkEqual(b, a)
+  }
+}
+
+@inline(never)
+public func run _EqualSubstringSubstringGenericStringProtocol(_ N: Int) {
+  let (_, a) = equivalentWithDistinctBuffers()
+  let (_, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    checkEqual(a, b)
+  }
+}
+*/
+
+//===----------------------------------------------------------------------===//
+
+/*
+@inline(never)
+public func run _LessStringSubstring(_ N: Int) {
+  let (a, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    blackHole(a < b)
+  }
+}
+
+@inline(never)
+public func run _LessSubstringString(_ N: Int) {
+  let (a, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    blackHole(b < a)
+  }
+}
+*/
+
+@inline(never)
+public func run_LessSubstringSubstring(_ N: Int) {
+  let (_, a) = equivalentWithDistinctBuffers()
+  let (_, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    blackHole(a < b)
+  }
+}
+
+@inline(never)
+public func run_LessSubstringSubstringGenericComparable(_ N: Int) {
+  let (_, a) = equivalentWithDistinctBuffers()
+  let (_, b) = equivalentWithDistinctBuffers()
+  func check<T>(_ x: T, _ y: T) where T : Comparable {
+    blackHole(x < y)
+  }
+  for _ in 1...N*500 {
+    check(a, b)
+  }
+}
+
+/*
+func checkLess<T, U>(_ x: T, _ y: U)
+where T : StringProtocol, U : StringProtocol {
+  blackHole(x < y)
+}
+
+@inline(never)
+public func run _LessStringSubstringGenericStringProtocol(_ N: Int) {
+  let (a, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    checkLess(a, b)
+  }
+}
+
+@inline(never)
+public func run _LessSubstringStringGenericStringProtocol(_ N: Int) {
+  let (a, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    checkLess(b, a)
+  }
+}
+
+@inline(never)
+public func run _LessSubstringSubstringGenericStringProtocol(_ N: Int) {
+  let (_, a) = equivalentWithDistinctBuffers()
+  let (_, b) = equivalentWithDistinctBuffers()
+  for _ in 1...N*500 {
+    checkLess(a, b)
+  }
+}
+*/
diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift
index 70a90a7..420e753 100644
--- a/benchmark/utils/main.swift
+++ b/benchmark/utils/main.swift
@@ -229,6 +229,10 @@
 addTo(&precommitTests, "DropWhileCountableRangeLazy", run_DropWhileCountableRangeLazy)
 addTo(&precommitTests, "DropWhileSequence", run_DropWhileSequence)
 addTo(&precommitTests, "DropWhileSequenceLazy", run_DropWhileSequenceLazy)
+addTo(&precommitTests, "EqualStringSubstring", run_EqualStringSubstring)
+addTo(&precommitTests, "EqualSubstringString", run_EqualSubstringString)
+addTo(&precommitTests, "EqualSubstringSubstring", run_EqualSubstringSubstring)
+addTo(&precommitTests, "EqualSubstringSubstringGenericEquatable", run_EqualSubstringSubstringGenericEquatable)
 addTo(&precommitTests, "ErrorHandling", run_ErrorHandling)
 addTo(&precommitTests, "GlobalClass", run_GlobalClass)
 addTo(&precommitTests, "Hanoi", run_Hanoi)
@@ -239,6 +243,8 @@
 addTo(&precommitTests, "Join", run_Join)
 addTo(&precommitTests, "LazilyFilteredArrays", run_LazilyFilteredArrays)
 addTo(&precommitTests, "LazilyFilteredRange", run_LazilyFilteredRange)
+addTo(&precommitTests, "LessSubstringSubstring", run_LessSubstringSubstring)
+addTo(&precommitTests, "LessSubstringSubstringGenericComparable", run_LessSubstringSubstringGenericComparable)
 addTo(&precommitTests, "LinkedList", run_LinkedList)
 addTo(&precommitTests, "MapReduce", run_MapReduce)
 addTo(&precommitTests, "MapReduceAnyCollection", run_MapReduceAnyCollection)
diff --git a/docs/ABI.rst b/docs/ABI.rst
index 58e2b5d..a3a3fc6 100644
--- a/docs/ABI.rst
+++ b/docs/ABI.rst
@@ -826,7 +826,8 @@
   global ::= protocol-conformance entity 'TW' // protocol witness thunk
   global ::= context identifier identifier 'TB' // property behavior initializer thunk (not used currently)
   global ::= context identifier identifier 'Tb' // property behavior setter thunk (not used currently)
-  global ::= global 'T_' specialization  // reset substitutions before demangling specialization
+  global ::= global specialization       // function specialization
+  global ::= global 'Tm'                 // merged function
   global ::= entity                      // some identifiable thing
   global ::= type type generic-signature? 'T' REABSTRACT-THUNK-TYPE   // reabstraction thunk helper function
 
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index d96613b..22b0dbb 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -286,6 +286,11 @@
                  OnClass | NotSerialized | LongAttribute,
                  /*Not serialized */ 70)
 
+// HACK: Attribute needed to preserve source compatibility by downgrading errors
+// due to an SDK change in Dispatch
+SIMPLE_DECL_ATTR(_downgrade_exhaustivity_check, DowngradeExhaustivityCheck,
+                 OnEnumElement | LongAttribute | UserInaccessible, 71)
+
 #undef TYPE_ATTR
 #undef DECL_ATTR_ALIAS
 #undef SIMPLE_DECL_ATTR
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 0292fb5..46660fa 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -3724,6 +3724,10 @@
 WARNING(redundant_particular_case,none,
         "case is already handled by previous patterns; consider removing it",())
 
+// HACK: Downgrades the above to warnings if any of the cases is marked
+// @_downgrade_exhaustivity_check.
+WARNING(non_exhaustive_switch_warn_swift3,none, "switch must be exhaustive", ())
+
 #ifndef DIAG_NO_UNDEF
 # if defined(DIAG)
 #  undef DIAG
diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h
index a6933fb..2482540 100644
--- a/include/swift/AST/Expr.h
+++ b/include/swift/AST/Expr.h
@@ -179,10 +179,9 @@
     friend class UnresolvedDeclRefExpr;
     unsigned : NumExprBits;
     unsigned DeclRefKind : 2;
-    unsigned IsSpecialized : 1;
     unsigned FunctionRefKind : 2;
   };
-  enum { NumUnresolvedDeclRefExprBits = NumExprBits + 5 };
+  enum { NumUnresolvedDeclRefExprBits = NumExprBits + 4 };
   static_assert(NumUnresolvedDeclRefExprBits <= 32, "fits in an unsigned");
 
   class MemberRefExprBitfields {
@@ -272,14 +271,6 @@
   enum { NumOverloadSetRefExprBits = NumExprBits + 2};
   static_assert(NumOverloadSetRefExprBits <= 32, "fits in an unsigned");
 
-  class OverloadedDeclRefExprBitfields {
-    friend class OverloadedDeclRefExpr;
-    unsigned : NumOverloadSetRefExprBits;
-    unsigned IsSpecialized : 1;
-  };
-  enum { NumOverloadedDeclRefExprBits = NumOverloadSetRefExprBits + 1 };
-  static_assert(NumOverloadedDeclRefExprBits <= 32, "fits in an unsigned");
-
   class BooleanLiteralExprBitfields {
     friend class BooleanLiteralExpr;
     unsigned : NumLiteralExprBits;
@@ -432,7 +423,6 @@
     DynamicSubscriptExprBitfields DynamicSubscriptExprBits;
     UnresolvedMemberExprBitfields UnresolvedMemberExprBits;
     OverloadSetRefExprBitfields OverloadSetRefExprBits;
-    OverloadedDeclRefExprBitfields OverloadedDeclRefExprBits;
     BooleanLiteralExprBitfields BooleanLiteralExprBits;
     MagicIdentifierLiteralExprBitfields MagicIdentifierLiteralExprBits;
     ObjectLiteralExprBitfields ObjectLiteralExprBits;
@@ -1249,27 +1239,15 @@
 
 /// DeclRefExpr - A reference to a value, "x".
 class DeclRefExpr : public Expr {
-  /// This is used when the reference is specialized, e.g "GenCls<Int>", to
-  /// hold information about the generic arguments.
-  struct SpecializeInfo {
-    ConcreteDeclRef D;
-    ArrayRef<TypeRepr*> GenericArgs;
-  };
-
-  /// \brief The declaration pointer or SpecializeInfo pointer if it was
-  /// explicitly specialized with <...>.
-  llvm::PointerUnion<ConcreteDeclRef, SpecializeInfo *> DOrSpecialized;
+  /// \brief The declaration pointer.
+  ConcreteDeclRef D;
   DeclNameLoc Loc;
 
-  SpecializeInfo *getSpecInfo() const {
-    return DOrSpecialized.dyn_cast<SpecializeInfo*>();
-  }
-
 public:
   DeclRefExpr(ConcreteDeclRef D, DeclNameLoc Loc, bool Implicit,
               AccessSemantics semantics = AccessSemantics::Ordinary,
               Type Ty = Type())
-    : Expr(ExprKind::DeclRef, Implicit, Ty), DOrSpecialized(D), Loc(Loc) {
+    : Expr(ExprKind::DeclRef, Implicit, Ty), D(D), Loc(Loc) {
     DeclRefExprBits.Semantics = (unsigned) semantics;
     DeclRefExprBits.FunctionRefKind =
       static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
@@ -1289,29 +1267,9 @@
 
   /// Retrieve the concrete declaration reference.
   ConcreteDeclRef getDeclRef() const {
-    if (auto Spec = getSpecInfo())
-      return Spec->D;
-    return DOrSpecialized.get<ConcreteDeclRef>();
+    return D;
   }
 
-  void setSpecialized();
-
-  /// \brief Determine whether this declaration reference was immediately
-  /// specialized by <...>.
-  bool isSpecialized() const { return getSpecInfo() != nullptr; }
-
-  /// Set the generic arguments.
-  ///
-  /// This copies the array using ASTContext's allocator.
-  void setGenericArgs(ArrayRef<TypeRepr*> GenericArgs);
-
-  /// Returns the generic arguments if it was specialized or an empty array
-  /// otherwise.
-  ArrayRef<TypeRepr *> getGenericArgs() const {
-    if (auto Spec = getSpecInfo())
-      return Spec->GenericArgs;
-    return ArrayRef<TypeRepr *>();
-  }
   SourceRange getSourceRange() const { return Loc.getSourceRange(); }
   SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
   DeclNameLoc getNameLoc() const { return Loc; }
@@ -1507,25 +1465,17 @@
 
 public:
   OverloadedDeclRefExpr(ArrayRef<ValueDecl*> Decls, DeclNameLoc Loc,
-                        bool isSpecialized,
                         FunctionRefKind functionRefKind,
                         bool Implicit, Type Ty = Type())
       : OverloadSetRefExpr(ExprKind::OverloadedDeclRef, Decls, functionRefKind,
                            Implicit, Ty),
         Loc(Loc) {
-    OverloadedDeclRefExprBits.IsSpecialized = isSpecialized;
   }
   
   DeclNameLoc getNameLoc() const { return Loc; }
   SourceLoc getLoc() const { return Loc.getBaseNameLoc(); }
   SourceRange getSourceRange() const { return Loc.getSourceRange(); }
 
-  /// \brief Determine whether this declaration reference was immediately
-  /// specialized by <...>.
-  bool isSpecialized() const {
-    return OverloadedDeclRefExprBits.IsSpecialized;
-  }
-
   static bool classof(const Expr *E) {
     return E->getKind() == ExprKind::OverloadedDeclRef;
   }
@@ -1545,7 +1495,6 @@
       : Expr(ExprKind::UnresolvedDeclRef, /*Implicit=*/loc.isInvalid()),
         Name(name), Loc(loc) {
     UnresolvedDeclRefExprBits.DeclRefKind = static_cast<unsigned>(refKind);
-    UnresolvedDeclRefExprBits.IsSpecialized = false;
     UnresolvedDeclRefExprBits.FunctionRefKind =
       static_cast<unsigned>(Loc.isCompound() ? FunctionRefKind::Compound
                                              : FunctionRefKind::Unapplied);
@@ -1558,14 +1507,6 @@
     return static_cast<DeclRefKind>(UnresolvedDeclRefExprBits.DeclRefKind);
   }
 
-  void setSpecialized(bool specialized) {
-    UnresolvedDeclRefExprBits.IsSpecialized = specialized;
-  }
-
-  /// \brief Determine whether this declaration reference was immediately
-  /// specialized by <...>.
-  bool isSpecialized() const { return UnresolvedDeclRefExprBits.IsSpecialized; }
-
   /// Retrieve the kind of function reference.
   FunctionRefKind getFunctionRefKind() const {
     return static_cast<FunctionRefKind>(
diff --git a/include/swift/AST/Initializer.h b/include/swift/AST/Initializer.h
index 3b4ca5c..754f5a6 100644
--- a/include/swift/AST/Initializer.h
+++ b/include/swift/AST/Initializer.h
@@ -70,17 +70,21 @@
 class PatternBindingInitializer : public Initializer {
   PatternBindingDecl *Binding;
 
+  // created lazily for 'self' lookup from lazy property initializer
+  ParamDecl *SelfParam;
+
   friend class ASTContext; // calls reset on unused contexts
 
   void reset(DeclContext *parent) {
     setParent(parent);
     Binding = nullptr;
+    SelfParam = nullptr;
   }
 
 public:
   explicit PatternBindingInitializer(DeclContext *parent)
     : Initializer(InitializerKind::PatternBinding, parent),
-      Binding(nullptr) {
+      Binding(nullptr), SelfParam(nullptr) {
     SpareBits = 0;
   }
  
@@ -95,6 +99,8 @@
 
   unsigned getBindingIndex() const { return SpareBits; }
 
+  ParamDecl *getImplicitSelfDecl();
+
   static bool classof(const DeclContext *DC) {
     if (auto init = dyn_cast<Initializer>(DC))
       return classof(init);
diff --git a/include/swift/AST/LazyResolver.h b/include/swift/AST/LazyResolver.h
index d5652ed..3f8f8c9 100644
--- a/include/swift/AST/LazyResolver.h
+++ b/include/swift/AST/LazyResolver.h
@@ -82,9 +82,6 @@
   /// Bind an extension to its extended type.
   virtual void bindExtension(ExtensionDecl *ext) = 0;
 
-  /// Introduce the accessors for a 'lazy' variable.
-  virtual void introduceLazyVarAccessors(VarDecl *var) = 0;
-
   /// Resolve the type of an extension.
   ///
   /// This can be called to ensure that the members of an extension can be
@@ -151,10 +148,6 @@
     Principal.bindExtension(ext);
   }
 
-  void introduceLazyVarAccessors(VarDecl *var) override {
-    Principal.introduceLazyVarAccessors(var);
-  }
-
   void resolveExtension(ExtensionDecl *ext) override {
     Principal.resolveExtension(ext);
   }
diff --git a/include/swift/Basic/Mangler.h b/include/swift/Basic/Mangler.h
index 7c97e7b..a358532 100644
--- a/include/swift/Basic/Mangler.h
+++ b/include/swift/Basic/Mangler.h
@@ -94,7 +94,10 @@
 
   Mangler() : Buffer(Storage) { }
 
-  /// Adds the mangling prefix.
+  /// Begins a new mangling but does not add the mangling prefix.
+  void beginManglingWithoutPrefix();
+
+  /// Begins a new mangling but and adds the mangling prefix.
   void beginMangling();
 
   /// Finish the mangling of the symbol and return the mangled name.
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index 21261f1..822120f 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -101,6 +101,7 @@
 NODE(LazyProtocolWitnessTableCacheVariable)
 NODE(LocalDeclName)
 CONTEXT_NODE(MaterializeForSet)
+NODE(MergedFunction)
 NODE(Metatype)
 NODE(MetatypeRepresentation)
 NODE(Metaclass)
diff --git a/include/swift/Demangling/Demangler.h b/include/swift/Demangling/Demangler.h
index 773e460..23d9d94 100644
--- a/include/swift/Demangling/Demangler.h
+++ b/include/swift/Demangling/Demangler.h
@@ -286,16 +286,11 @@
 /// It de-mangles a string and it also owns the returned node-tree. This means
 /// The nodes of the tree only live as long as the Demangler itself.
 class Demangler : public NodeFactory {
-private:
+protected:
   StringRef Text;
   size_t Pos = 0;
 
-  struct NodeWithPos {
-    NodePointer Node;
-    size_t Pos;
-  };
-
-  Vector<NodeWithPos> NodeStack;
+  Vector<NodePointer> NodeStack;
   Vector<NodePointer> Substitutions;
   Vector<unsigned> PendingSubstitutions;
 
@@ -334,18 +329,18 @@
   }
 
   void pushNode(NodePointer Nd) {
-    NodeStack.push_back({ Nd, Pos }, *this);
+    NodeStack.push_back(Nd, *this);
   }
 
   NodePointer popNode() {
-    return NodeStack.pop_back_val().Node;
+    return NodeStack.pop_back_val();
   }
 
   NodePointer popNode(Node::Kind kind) {
     if (NodeStack.empty())
       return nullptr;
 
-    Node::Kind NdKind = NodeStack.back().Node->getKind();
+    Node::Kind NdKind = NodeStack.back()->getKind();
     if (NdKind != kind)
       return nullptr;
 
@@ -356,7 +351,7 @@
     if (NodeStack.empty())
       return nullptr;
 
-    Node::Kind NdKind = NodeStack.back().Node->getKind();
+    Node::Kind NdKind = NodeStack.back()->getKind();
     if (!pred(NdKind))
       return nullptr;
     
@@ -381,7 +376,7 @@
     return createWithChild(kind, popNode(Node::Kind::Type));
   }
 
-  void parseAndPushNodes();
+  bool parseAndPushNodes();
 
   NodePointer changeKind(NodePointer Node, Node::Kind NewKind);
 
diff --git a/include/swift/Migrator/FixitFilter.h b/include/swift/Migrator/FixitFilter.h
index 161ed44..0f94fb8 100644
--- a/include/swift/Migrator/FixitFilter.h
+++ b/include/swift/Migrator/FixitFilter.h
@@ -102,7 +102,6 @@
     // Fixits from warnings/notes that should be applied.
     if (Info.ID == diag::forced_downcast_coercion.ID ||
         Info.ID == diag::forced_downcast_noop.ID ||
-        Info.ID == diag::variable_never_mutated.ID ||
         Info.ID == diag::function_type_no_parens.ID ||
         Info.ID == diag::convert_let_to_var.ID ||
         Info.ID == diag::parameter_extraneous_double_up.ID ||
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index b7c864a..9204df2 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -840,6 +840,8 @@
 
     void visitEnumElementDecl(EnumElementDecl *EED) {
       printCommon(EED, "enum_element_decl");
+      if (EED->getAttrs().hasAttribute<DowngradeExhaustivityCheckAttr>())
+        OS << "@_downgrade_exhaustivity_check";
       PrintWithColorRAII(OS, ParenthesisColor) << ')';
     }
 
@@ -1792,13 +1794,7 @@
       PrintWithColorRAII(OS, AccessibilityColor)
         << " " << getAccessSemanticsString(E->getAccessSemantics());
     PrintWithColorRAII(OS, ExprModifierColor)
-      << " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind())
-      << " specialized=" << (E->isSpecialized()? "yes" : "no");
-
-    for (auto TR : E->getGenericArgs()) {
-      OS << '\n';
-      printRec(TR);
-    }
+      << " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
     PrintWithColorRAII(OS, ParenthesisColor) << ')';
   }
   void visitSuperRefExpr(SuperRefExpr *E) {
@@ -1827,7 +1823,6 @@
     printCommon(E, "overloaded_decl_ref_expr")
       << " name=" << E->getDecls()[0]->getName()
       << " #decls=" << E->getDecls().size()
-      << " specialized=" << (E->isSpecialized()? "yes" : "no")
       << " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
 
     for (ValueDecl *D : E->getDecls()) {
@@ -1841,7 +1836,6 @@
     printCommon(E, "unresolved_decl_ref_expr");
     PrintWithColorRAII(OS, IdentifierColor) << " name=" << E->getName();
     PrintWithColorRAII(OS, ExprModifierColor)
-      << " specialized=" << (E->isSpecialized()? "yes" : "no")
       << " function_ref=" << getFunctionRefKindStr(E->getFunctionRefKind());
     PrintWithColorRAII(OS, ParenthesisColor) << ')';
   }
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index e48fd02..d09ff4d 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -386,6 +386,7 @@
 }
 
 std::string ASTMangler::mangleTypeAsContextUSR(const NominalTypeDecl *type) {
+  beginManglingWithoutPrefix();
   llvm::SaveAndRestore<bool> allowUnnamedRAII(AllowNamelessEntities, true);
   appendContext(type);
   return finalize();
@@ -393,6 +394,7 @@
 
 std::string ASTMangler::mangleDeclAsUSR(const ValueDecl *Decl,
                                         StringRef USRPrefix) {
+  beginManglingWithoutPrefix();
   llvm::SaveAndRestore<bool> allowUnnamedRAII(AllowNamelessEntities, true);
   Buffer << USRPrefix;
   bindGenericParameters(Decl->getDeclContext());
@@ -419,6 +421,7 @@
                                                   AddressorKind addressorKind,
                                                   const ValueDecl *decl,
                                                   StringRef USRPrefix) {
+  beginManglingWithoutPrefix();
   llvm::SaveAndRestore<bool> allowUnnamedRAII(AllowNamelessEntities, true);
   Buffer << USRPrefix;
   appendAccessorEntity(kind, addressorKind, decl, /*isStatic*/ false);
diff --git a/lib/AST/ASTScope.cpp b/lib/AST/ASTScope.cpp
index 2ca2f44..e40a5a1 100644
--- a/lib/AST/ASTScope.cpp
+++ b/lib/AST/ASTScope.cpp
@@ -1903,28 +1903,17 @@
     }
     break;
 
-  case ASTScopeKind::PatternInitializer:
-    // FIXME: This causes recursion that we cannot yet handle.
-#if false
+  case ASTScopeKind::PatternInitializer: {
     // 'self' is available within the pattern initializer of a 'lazy' variable.
-    if (auto singleVar = patternBinding.decl->getSingleVar()) {
-      if (singleVar->getAttrs().hasAttribute<LazyAttr>() &&
-          singleVar->getDeclContext()->isTypeContext()) {
-        // If there is no getter (yet), add them.
-        if (!singleVar->getGetter()) {
-          ASTContext &ctx = singleVar->getASTContext();
-          if (auto resolver = ctx.getLazyResolver())
-            resolver->introduceLazyVarAccessors(singleVar);
-        }
-
-        // Add the getter's 'self'.
-        if (auto getter = singleVar->getGetter())
-          if (auto self = getter->getImplicitSelfDecl())
-            result.push_back(self);
-      }
+    auto *initContext = cast_or_null<PatternBindingInitializer>(
+      patternBinding.decl->getPatternList()[0].getInitContext());
+    if (initContext) {
+      if (auto *selfParam = initContext->getImplicitSelfDecl())
+        result.push_back(selfParam);
     }
-#endif
+
     break;
+  }
 
   case ASTScopeKind::Closure:
     // Note: Parameters all at once is different from functions, but it's not
diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp
index 832492f..f17ad77 100644
--- a/lib/AST/ASTWalker.cpp
+++ b/lib/AST/ASTWalker.cpp
@@ -429,10 +429,6 @@
   }
 
   Expr *visitDeclRefExpr(DeclRefExpr *E) {
-    for (auto Ty : E->getGenericArgs()) {
-      if (doIt(Ty))
-        return nullptr;
-    }
     return E;
   }
   
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index e782469..bb065bb 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -506,6 +506,10 @@
     Printer.printAttrName("@_staticInitializeObjCMetadata");
     break;
 
+  case DAK_DowngradeExhaustivityCheck:
+    Printer.printAttrName("@_downgrade_exhaustivity_check");
+    break;
+    
   case DAK_Count:
     llvm_unreachable("exceed declaration attribute kinds");
 
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 5cf5e04..7568292 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -986,6 +986,25 @@
   return PBD;
 }
 
+ParamDecl *PatternBindingInitializer::getImplicitSelfDecl() {
+  if (SelfParam)
+    return SelfParam;
+
+  if (auto singleVar = getBinding()->getSingleVar()) {
+    auto *DC = singleVar->getDeclContext();
+    if (singleVar->getAttrs().hasAttribute<LazyAttr>() &&
+        DC->isTypeContext()) {
+      bool isInOut = !DC->getDeclaredTypeOfContext()->hasReferenceSemantics();
+      SelfParam = ParamDecl::createSelf(SourceLoc(), DC,
+                                        singleVar->isStatic(),
+                                        isInOut);
+      SelfParam->setDeclContext(this);
+    }
+  }
+
+  return SelfParam;
+}
+
 static bool patternContainsVarDeclBinding(const Pattern *P, const VarDecl *VD) {
   bool Result = false;
   P->forEachVariable([&](VarDecl *FoundVD) {
@@ -3916,9 +3935,12 @@
 }
 
 bool VarDecl::isSelfParameter() const {
-  if (isa<ParamDecl>(this))
+  if (isa<ParamDecl>(this)) {
     if (auto *AFD = dyn_cast<AbstractFunctionDecl>(getDeclContext()))
       return AFD->getImplicitSelfDecl() == this;
+    if (auto *PBI = dyn_cast<PatternBindingInitializer>(getDeclContext()))
+      return PBI->getImplicitSelfDecl() == this;
+  }
 
   return false;
 }
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index dcfc680..952bbde 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1308,25 +1308,6 @@
   llvm_unreachable("unspecified literal");
 }
 
-void DeclRefExpr::setSpecialized() {
-  if (isSpecialized())
-    return;
-
-  ConcreteDeclRef ref = getDeclRef();
-  void *Mem = ref.getDecl()->getASTContext().Allocate(sizeof(SpecializeInfo),
-                                                      alignof(SpecializeInfo));
-  auto Spec = new (Mem) SpecializeInfo;
-  Spec->D = ref;
-  DOrSpecialized = Spec;
-}
-
-void DeclRefExpr::setGenericArgs(ArrayRef<TypeRepr*> GenericArgs) {
-  ValueDecl *D = getDecl();
-  assert(D);
-  setSpecialized();
-  getSpecInfo()->GenericArgs = D->getASTContext().AllocateCopy(GenericArgs);
-}
-
 ConstructorDecl *OtherConstructorDeclRefExpr::getDecl() const {
   return cast_or_null<ConstructorDecl>(Ctor.getDecl());
 }
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index d76c708..04fc0f2 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -510,29 +510,11 @@
         // Pattern binding initializers are only interesting insofar as they
         // affect lookup in an enclosing nominal type or extension thereof.
         if (auto *bindingInit = dyn_cast<PatternBindingInitializer>(dc)) {
-          if (auto binding = bindingInit->getBinding()) {
-            // Look for 'self' for a lazy variable initializer.
-            if (auto singleVar = binding->getSingleVar())
-              // We only care about lazy variables.
-              if (singleVar->getAttrs().hasAttribute<LazyAttr>()) {
+          // Lazy variable initializer contexts have a 'self' parameter for
+          // instance member lookup.
+          if (auto *selfParam = bindingInit->getImplicitSelfDecl())
+            selfDecl = selfParam;
 
-              // 'self' will be listed in the local bindings.
-              for (auto local : localBindings) {
-                auto param = dyn_cast<ParamDecl>(local);
-                if (!param) continue;
-
-
-                // If we have a variable that's the implicit self of its enclosing
-                // context, mark it as 'self'.
-                if (auto func = dyn_cast<FuncDecl>(param->getDeclContext())) {
-                  if (param == func->getImplicitSelfDecl()) {
-                    selfDecl = param;
-                    break;
-                  }
-                }
-              }
-            }
-          }
           continue;
         }
 
@@ -646,17 +628,46 @@
         Type ExtendedType;
         bool isTypeLookup = false;
 
-        // If this declcontext is an initializer for a static property, then we're
-        // implicitly doing a static lookup into the parent declcontext.
-        if (auto *PBI = dyn_cast<PatternBindingInitializer>(DC))
-          if (!DC->getParent()->isModuleScopeContext()) {
-            if (auto *PBD = PBI->getBinding()) {
-              isTypeLookup = PBD->isStatic();
-              DC = DC->getParent();
-            }
+        if (auto *PBI = dyn_cast<PatternBindingInitializer>(DC)) {
+          auto *PBD = PBI->getBinding();
+          assert(PBD);
+
+          // Lazy variable initializer contexts have a 'self' parameter for
+          // instance member lookup.
+          if (auto *selfParam = PBI->getImplicitSelfDecl()) {
+            Consumer.foundDecl(selfParam,
+                               DeclVisibilityKind::FunctionParameter);
+            if (!Results.empty())
+              return;
+
+            DC = DC->getParent();
+
+            BaseDecl = selfParam;
+            ExtendedType = DC->getSelfTypeInContext();
+            MetaBaseDecl = DC->getAsNominalTypeOrNominalTypeExtensionContext();
+
+            isTypeLookup = PBD->isStatic();
           }
-        
-        if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
+          // Initializers for stored properties of types perform static
+          // lookup into the surrounding context.
+          else if (PBD->getDeclContext()->isTypeContext()) {
+            DC = DC->getParent();
+
+            ExtendedType = DC->getSelfTypeInContext();
+            MetaBaseDecl = DC->getAsNominalTypeOrNominalTypeExtensionContext();
+            BaseDecl = MetaBaseDecl;
+
+            isTypeLookup = PBD->isStatic(); // FIXME
+
+            isCascadingUse = DC->isCascadingContextForLookup(false);
+          }
+          // Otherwise, we have an initializer for a global or local property.
+          // There's not much to find here, we'll keep going up to a parent
+          // context.
+
+          if (!isCascadingUse.hasValue())
+            isCascadingUse = DC->isCascadingContextForLookup(false);
+        } else if (auto *AFD = dyn_cast<AbstractFunctionDecl>(DC)) {
           // Look for local variables; normally, the parser resolves these
           // for us, but it can't do the right thing inside local types.
           // FIXME: when we can parse and typecheck the function body partially
@@ -690,9 +701,12 @@
               if (FD->isStatic())
                 isTypeLookup = true;
 
-            // If we're not in the body of the function, the base declaration
+            // If we're not in the body of the function (for example, we
+            // might be type checking a default argument expression and
+            // performing name lookup from there), the base declaration
             // is the nominal type, not 'self'.
-            if (Loc.isValid() &&
+            if (!AFD->isImplicit() &&
+                Loc.isValid() &&
                 AFD->getBodySourceRange().isValid() &&
                 !SM.rangeContainsTokenLoc(AFD->getBodySourceRange(), Loc)) {
               BaseDecl = MetaBaseDecl;
diff --git a/lib/Basic/Mangler.cpp b/lib/Basic/Mangler.cpp
index da5c924..71eac3f 100644
--- a/lib/Basic/Mangler.cpp
+++ b/lib/Basic/Mangler.cpp
@@ -110,12 +110,16 @@
 #endif
 }
 
-void Mangler::beginMangling() {
+void Mangler::beginManglingWithoutPrefix() {
   Storage.clear();
   Substitutions.clear();
   StringSubstitutions.clear();
   Words.clear();
   SubstMerging.clear();
+}
+
+void Mangler::beginMangling() {
+  beginManglingWithoutPrefix();
   Buffer << MANGLING_PREFIX_STR;
 }
 
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index ff368e2..553615b 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -100,6 +100,7 @@
     case Node::Kind::VTableAttribute:
     case Node::Kind::PartialApplyForwarder:
     case Node::Kind::PartialApplyObjCForwarder:
+    case Node::Kind::MergedFunction:
       return true;
     default:
       return false;
@@ -233,15 +234,11 @@
 
   // If any other prefixes are accepted, please update Mangler::verify.
 
+  if (!parseAndPushNodes())
+    return nullptr;
+
   NodePointer topLevel = createNode(Node::Kind::Global);
 
-  parseAndPushNodes();
-
-  // Let a trailing '_' be part of the not demangled suffix.
-  popNode(Node::Kind::FirstElementMarker);
-
-  size_t EndPos = (NodeStack.empty() ? 0 : NodeStack.back().Pos);
-
   NodePointer Parent = topLevel;
   while (NodePointer FuncAttr = popNode(isFunctionAttr)) {
     Parent->addChild(FuncAttr, *this);
@@ -249,8 +246,7 @@
         FuncAttr->getKind() == Node::Kind::PartialApplyObjCForwarder)
       Parent = FuncAttr;
   }
-  for (const NodeWithPos &NWP : NodeStack) {
-    NodePointer Nd = NWP.Node;
+  for (Node *Nd : NodeStack) {
     switch (Nd->getKind()) {
       case Node::Kind::Type:
         Parent->addChild(Nd->getFirstChild(), *this);
@@ -263,10 +259,6 @@
   if (topLevel->getNumChildren() == 0)
     return nullptr;
 
-  if (EndPos < Text.size()) {
-    topLevel->addChild(createNode(Node::Kind::Suffix, Text.substr(EndPos)), *this);
-  }
-
   return topLevel;
 }
 
@@ -281,15 +273,16 @@
   return createNode(Node::Kind::Suffix, Text);
 }
 
-void Demangler::parseAndPushNodes() {
+bool Demangler::parseAndPushNodes() {
   int Idx = 0;
-  while (!Text.empty()) {
+  while (Pos < Text.size()) {
     NodePointer Node = demangleOperator();
     if (!Node)
-      break;
+      return false;
     pushNode(Node);
     Idx++;
   }
+  return true;
 }
 
 NodePointer Demangler::addChild(NodePointer Parent, NodePointer Child) {
@@ -1219,6 +1212,7 @@
     case 'd': return createNode(Node::Kind::DirectMethodReferenceAttribute);
     case 'a': return createNode(Node::Kind::PartialApplyObjCForwarder);
     case 'A': return createNode(Node::Kind::PartialApplyForwarder);
+    case 'm': return createNode(Node::Kind::MergedFunction);
     case 'V': {
       NodePointer Base = popNode(isEntity);
       NodePointer Derived = popNode(isEntity);
diff --git a/lib/Demangling/NodeDumper.cpp b/lib/Demangling/NodeDumper.cpp
index be2929d..fdcc6c8 100644
--- a/lib/Demangling/NodeDumper.cpp
+++ b/lib/Demangling/NodeDumper.cpp
@@ -62,8 +62,8 @@
 
 void Demangler::dump() {
   for (unsigned Idx = 0; Idx < NodeStack.size(); ++Idx) {
-    fprintf(stderr, "NodeStack[%u] at position %zd:\n", Idx, NodeStack[Idx].Pos);
-    NodeStack[Idx].Node->dump();
+    fprintf(stderr, "NodeStack[%u]:\n", Idx);
+    NodeStack[Idx]->dump();
     fprintf(stderr, "\n");
   }
   fprintf(stderr, "Position = %zd:\n%.*s\n%*s\n", Pos,
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index 7c57e44..fe322e6 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -347,6 +347,7 @@
     case Node::Kind::LocalDeclName:
     case Node::Kind::PrivateDeclName:
     case Node::Kind::MaterializeForSet:
+    case Node::Kind::MergedFunction:
     case Node::Kind::Metaclass:
     case Node::Kind::NativeOwningAddressor:
     case Node::Kind::NativeOwningMutableAddressor:
@@ -1238,6 +1239,11 @@
     print(Node->getChild(Node->getNumChildren() - 1));
     return nullptr;
   }
+  case Node::Kind::MergedFunction:
+    if (!Options.ShortenThunk) {
+      Printer << "merged ";
+    }
+    return nullptr;
   case Node::Kind::GenericTypeMetadataPattern:
     Printer << "generic type metadata pattern for ";
     print(Node->getChild(0));
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index 8089ebe..e933875 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -653,6 +653,10 @@
   mangleSingleChildNode(node); // global
 }
 
+void Remangler::mangleMergedFunction(Node *node) {
+  Out << "Tm";
+}
+
 void Remangler::mangleDirectness(Node *node) {
   auto getChar = [](Directness d) -> char {
     switch (d) {
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 7abeb0d..afa2671 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -1063,6 +1063,7 @@
       case Node::Kind::DynamicAttribute:
       case Node::Kind::VTableAttribute:
       case Node::Kind::DirectMethodReferenceAttribute:
+      case Node::Kind::MergedFunction:
         mangleInReverseOrder = true;
         break;
       default:
@@ -1368,6 +1369,10 @@
   Buffer << "Ta";
 }
 
+void Remangler::mangleMergedFunction(Node *node) {
+  Buffer << "Tm";
+}
+
 void Remangler::manglePostfixOperator(Node *node) {
   mangleIdentifierImpl(node, /*isOperator*/ true);
   Buffer << "oP";
diff --git a/lib/LLVMPasses/LLVMMergeFunctions.cpp b/lib/LLVMPasses/LLVMMergeFunctions.cpp
index 55ad969..5185bc3 100644
--- a/lib/LLVMPasses/LLVMMergeFunctions.cpp
+++ b/lib/LLVMPasses/LLVMMergeFunctions.cpp
@@ -861,7 +861,7 @@
   // a name which can be demangled in a meaningful way.
   Function *NewFunction = Function::Create(funcType,
                                            FirstF->getLinkage(),
-                                           FirstF->getName() + "_merged");
+                                           FirstF->getName() + "Tm");
   NewFunction->copyAttributesFrom(FirstF);
   // NOTE: this function is not externally available, do ensure that we reset
   // the DLL storage
diff --git a/lib/Migrator/TupleSplatMigratorPass.cpp b/lib/Migrator/TupleSplatMigratorPass.cpp
index 2aedb1e..b058a5a 100644
--- a/lib/Migrator/TupleSplatMigratorPass.cpp
+++ b/lib/Migrator/TupleSplatMigratorPass.cpp
@@ -58,15 +58,15 @@
     if (!Expr->hasAnonymousClosureVars())
       return;
     References.clear();
-    for(auto *Param: *Expr->getParameters()) {
+    for (auto *Param: *Expr->getParameters()) {
       References[Param] = {};
     }
     Expr->walk(*this);
   }
 
   void forEachReference(llvm::function_ref<void(Expr*, ParamDecl*)> Callback) {
-    for(auto Entry: References) {
-      for(auto *Expr : Entry.getSecond()) {
+    for (auto Entry: References) {
+      for (auto *Expr : Entry.getSecond()) {
         Callback(Expr, Entry.getFirst());
       }
     }
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index c6a0b44..ea4b2d9 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -2063,15 +2063,11 @@
       return parseExprEditorPlaceholder(IdentTok, name.getBaseName());
 
     auto refKind = DeclRefKind::Ordinary;
-    auto unresolved = new (Context) UnresolvedDeclRefExpr(name, refKind, loc);
-    unresolved->setSpecialized(hasGenericArgumentList);
-    E = unresolved;
+    E = new (Context) UnresolvedDeclRefExpr(name, refKind, loc);
   } else if (auto TD = dyn_cast<TypeDecl>(D)) {
     E = TypeExpr::createForDecl(loc.getBaseNameLoc(), TD, /*implicit*/false);
   } else {
-    auto declRef = new (Context) DeclRefExpr(D, loc, /*Implicit=*/false);
-    declRef->setGenericArgs(args);
-    E = declRef;
+    E = new (Context) DeclRefExpr(D, loc, /*Implicit=*/false);
   }
   
   if (hasGenericArgumentList) {
diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp
index 626cb05..2bf4152 100644
--- a/lib/SIL/DynamicCasts.cpp
+++ b/lib/SIL/DynamicCasts.cpp
@@ -89,15 +89,24 @@
   if (source == target)
     return DynamicCastFeasibility::WillSucceed;
 
-  auto *SourceNominalTy = source.getAnyNominal();
-
-  if (!SourceNominalTy)
-    return DynamicCastFeasibility::MaySucceed;
-
   auto *TargetProtocol = target.getAnyNominal();
   if (!TargetProtocol)
     return DynamicCastFeasibility::MaySucceed;
 
+  auto *SourceNominalTy = source.getAnyNominal();
+
+  if (!SourceNominalTy) {
+    if (auto Archetype = dyn_cast<ArchetypeType>(source)) {
+      auto SourceProtocols = Archetype->getConformsTo();
+      // Check all protocols implemented by the archetype.
+      for (auto *Protocol : SourceProtocols) {
+        if (Protocol == TargetProtocol)
+          return DynamicCastFeasibility::WillSucceed;
+      }
+    }
+    return DynamicCastFeasibility::MaySucceed;
+  }
+
   auto SourceProtocols = SourceNominalTy->getAllProtocols();
 
   // Check all protocols implemented by the type.
@@ -330,11 +339,8 @@
   if (source->hasArchetype() || source.isExistentialType() ||
       target->hasArchetype() || target.isExistentialType()) {
 
-    auto *SourceNominalTy = source.getAnyNominal();
-
     // Check conversions from non-protocol types into protocol types.
     if (!source.isExistentialType() &&
-        SourceNominalTy &&
         target.isExistentialType())
       return classifyDynamicCastToProtocol(source, target, isWholeModuleOpts);
 
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 5941a3d..b5132b1 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -859,7 +859,7 @@
   if (auto *dre1 = dyn_cast<DeclRefExpr>(e1)) {
     auto *dre2 = cast<DeclRefExpr>(e2);
     return dre1->getDecl() == dre2->getDecl() &&
-           dre1->getGenericArgs() == dre2->getGenericArgs();
+           dre1->getType()->isEqual(dre2->getType());
   }
 
   // Compare a variety of literals.
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
index 3afefba..f3301a6 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp
@@ -541,13 +541,17 @@
     }
   }
 
+  auto *Scope = NoReturnCall->getDebugScope();
   recursivelyDeleteTriviallyDeadInstructions(ToBeDeleted, true);
   NumInstructionsRemoved += ToBeDeleted.size();
 
   // Add an unreachable terminator. The terminator has an invalid source
   // location to signal to the DataflowDiagnostic pass that this code does
   // not correspond to user code.
+  // Share the scope with the preceding BB. This causes the debug info to be
+  // much smaller and easier to read, but otherwise has no effect.
   SILBuilder B(&BB);
+  B.setCurrentDebugScope(Scope);
   B.createUnreachable(ArtificialUnreachableLocation());
 
   return true;
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index e4c9d7d..638a3e5 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -2458,6 +2458,104 @@
   }
 }
 
+/// TODO: Move to emitSuccessfulIndirectUnconditionalCast?
+///
+/// Peephole to avoid runtime calls:
+/// unconditional_checked_cast_addr T in %0 : $*T to P in %1 : $*P
+/// ->
+/// %addr = init_existential_addr %1 : $*P, T
+/// copy_addr %0 to %addr
+///
+/// where T is a type statically known to conform to P.
+///
+/// In caase P is a class existential type, it generates:
+/// %val = load %0 : $*T
+/// %existential = init_existential_ref %val : $T, $T, P
+/// store %existential to %1 : $*P
+///
+/// Returns true if the optimization was possible and false otherwise.
+static bool optimizeStaticallyKnownProtocolConformance(
+    UnconditionalCheckedCastAddrInst *Inst) {
+  auto Loc = Inst->getLoc();
+  auto Src = Inst->getSrc();
+  auto Dest = Inst->getDest();
+  auto SourceType = Inst->getSourceType();
+  auto TargetType = Inst->getTargetType();
+  auto &Mod = Inst->getModule();
+
+  if (TargetType->isAnyExistentialType() &&
+      !SourceType->isAnyExistentialType()) {
+    auto &Ctx = Mod.getASTContext();
+    auto *SM = Mod.getSwiftModule();
+
+    auto Proto = dyn_cast<ProtocolDecl>(TargetType->getAnyNominal());
+    if (Proto) {
+      auto Conformance = SM->lookupConformance(SourceType, Proto, nullptr);
+      if (Conformance.hasValue()) {
+        // SourceType is a non-existential type conforming to a
+        // protocol represented by the TargetType.
+        SILBuilder B(Inst);
+        SmallVector<ProtocolConformanceRef, 1> NewConformances;
+        NewConformances.push_back(Conformance.getValue());
+        ArrayRef<ProtocolConformanceRef> Conformances =
+            Ctx.AllocateCopy(NewConformances);
+
+        auto ExistentialRepr =
+            Dest->getType().getPreferredExistentialRepresentation(Mod,
+                                                                  SourceType);
+
+        switch (ExistentialRepr) {
+        default:
+          return false;
+        case ExistentialRepresentation::Opaque: {
+          auto ExistentialAddr = B.createInitExistentialAddr(
+              Loc, Dest, SourceType, Src->getType().getObjectType(),
+              Conformances);
+          B.createCopyAddr(
+              Loc, Src, ExistentialAddr,
+              (Inst->getConsumptionKind() != CastConsumptionKind::CopyOnSuccess)
+                  ? IsTake_t::IsTake
+                  : IsTake_t::IsNotTake,
+              IsInitialization_t::IsInitialization);
+          break;
+        }
+        case ExistentialRepresentation::Class: {
+          auto Value = B.createLoad(Loc, Src,
+                                    swift::LoadOwnershipQualifier::Unqualified);
+          if (Inst->getConsumptionKind() == CastConsumptionKind::CopyOnSuccess)
+            B.createRetainValue(Loc, Value, B.getDefaultAtomicity());
+          auto Existential =
+              B.createInitExistentialRef(Loc, Dest->getType().getObjectType(),
+                                         SourceType, Value, Conformances);
+          B.createStore(Loc, Existential, Dest,
+                        swift::StoreOwnershipQualifier::Unqualified);
+          break;
+        }
+        case ExistentialRepresentation::Boxed: {
+          auto AllocBox = B.createAllocExistentialBox(Loc, Dest->getType(),
+                                                      SourceType, Conformances);
+          auto Projection =
+              B.createProjectExistentialBox(Loc, Src->getType(), AllocBox);
+          auto Value = B.createLoad(Loc, Src,
+                                    swift::LoadOwnershipQualifier::Unqualified);
+          if (Inst->getConsumptionKind() == CastConsumptionKind::CopyOnSuccess)
+            B.createRetainValue(Loc, Value, B.getDefaultAtomicity());
+          B.createStore(Loc, Value, Projection,
+                        swift::StoreOwnershipQualifier::Unqualified);
+          B.createStore(Loc, AllocBox, Dest,
+                        swift::StoreOwnershipQualifier::Unqualified);
+          break;
+        }
+        };
+
+        Inst->replaceAllUsesWithUndef();
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 SILInstruction *
 CastOptimizer::
 optimizeUnconditionalCheckedCastAddrInst(UnconditionalCheckedCastAddrInst *Inst) {
@@ -2512,18 +2610,24 @@
   if (Feasibility == DynamicCastFeasibility::WillSucceed ||
       Feasibility == DynamicCastFeasibility::MaySucceed) {
 
+    // Check if a result of a cast is unused. If this is the case, the cast can
+    // be removed even if the cast may fail at runtime.
+    // Swift optimizer does not claim to be crash-preserving.
     bool ResultNotUsed = isa<AllocStackInst>(Dest);
     DestroyAddrInst *DestroyDestInst = nullptr;
-    for (auto Use : Dest->getUses()) {
-      auto *User = Use->getUser();
-      if (isa<DeallocStackInst>(User) || User == Inst)
-        continue;
-      if (isa<DestroyAddrInst>(User) && !DestroyDestInst) {
-        DestroyDestInst = cast<DestroyAddrInst>(User);
-        continue;
+    if (ResultNotUsed) {
+      for (auto Use : Dest->getUses()) {
+        auto *User = Use->getUser();
+        if (isa<DeallocStackInst>(User) || User == Inst)
+          continue;
+        if (isa<DestroyAddrInst>(User) && !DestroyDestInst) {
+          DestroyDestInst = cast<DestroyAddrInst>(User);
+          continue;
+        }
+        ResultNotUsed = false;
+        DestroyDestInst = nullptr;
+        break;
       }
-      ResultNotUsed = false;
-      break;
     }
 
     if (ResultNotUsed) {
@@ -2544,23 +2648,33 @@
       return nullptr;
     }
 
-    // Try to apply the bridged casts optimizations
+    // Try to apply the bridged casts optimizations.
     auto NewI = optimizeBridgedCasts(Inst, Inst->getConsumptionKind(),
                                      false, Src, Dest, SourceType,
                                      TargetType, nullptr, nullptr);
     if (NewI) {
-        WillSucceedAction();
-        return nullptr;
+      WillSucceedAction();
+      return nullptr;
+    }
+
+    if (Feasibility == DynamicCastFeasibility::MaySucceed)
+      return nullptr;
+
+    assert(Feasibility == DynamicCastFeasibility::WillSucceed);
+
+    if (optimizeStaticallyKnownProtocolConformance(Inst)) {
+      EraseInstAction(Inst);
+      WillSucceedAction();
+      return nullptr;
     }
 
     if (isBridgingCast(SourceType, TargetType))
       return nullptr;
 
     SILBuilderWithScope Builder(Inst);
-    if (!emitSuccessfulIndirectUnconditionalCast(Builder, Mod.getSwiftModule(),
-                                            Loc, Inst->getConsumptionKind(),
-                                            Src, SourceType,
-                                            Dest, TargetType, Inst)) {
+    if (!emitSuccessfulIndirectUnconditionalCast(
+            Builder, Mod.getSwiftModule(), Loc, Inst->getConsumptionKind(), Src,
+            SourceType, Dest, TargetType, Inst)) {
       // No optimization was possible.
       return nullptr;
     }
diff --git a/lib/SILOptimizer/Utils/SpecializationMangler.cpp b/lib/SILOptimizer/Utils/SpecializationMangler.cpp
index d133c81..7134e4b 100644
--- a/lib/SILOptimizer/Utils/SpecializationMangler.cpp
+++ b/lib/SILOptimizer/Utils/SpecializationMangler.cpp
@@ -19,16 +19,37 @@
 using namespace Mangle;
 
 void SpecializationMangler::beginMangling() {
-  ASTMangler::beginMangling();
+  ASTMangler::beginManglingWithoutPrefix();
   if (Serialized)
     ArgOpBuffer << 'q';
   ArgOpBuffer << char(uint8_t(Pass) + '0');
 }
 
+namespace {
+
+/// Utility class for demangling specialization attributes.
+class AttributeDemangler : public Demangle::Demangler {
+public:
+  void demangleAndAddAsChildren(StringRef MangledSpecialization,
+                                NodePointer Parent) {
+    init(MangledSpecialization);
+    if (!parseAndPushNodes()) {
+      llvm::errs() << "Can't demangle: " << MangledSpecialization << '\n';
+      abort();
+    }
+    for (Node *Nd : NodeStack) {
+      addChild(Parent, Nd);
+    }
+  }
+};
+
+} // namespace
+
 std::string SpecializationMangler::finalize() {
   StringRef MangledSpecialization(Storage.data(), Storage.size());
-  Demangle::Demangler D;
-  NodePointer TopLevel = D.demangleSymbol(MangledSpecialization);
+  AttributeDemangler D;
+  NodePointer TopLevel = D.createNode(Node::Kind::Global);
+  D.demangleAndAddAsChildren(MangledSpecialization, TopLevel);
 
   StringRef FuncName = Function->getName();
   NodePointer FuncTopLevel = nullptr;
@@ -41,8 +62,6 @@
     FuncTopLevel->addChild(D.createNode(Node::Kind::Identifier, FuncName), D);
   }
   for (NodePointer FuncChild : *FuncTopLevel) {
-    assert(FuncChild->getKind() != Node::Kind::Suffix ||
-           FuncChild->getText() == "merged");
     TopLevel->addChild(FuncChild, D);
   }
   std::string mangledName = Demangle::mangleNode(TopLevel);
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 5ef9dd0..05dc57b 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -72,10 +72,8 @@
     return;
 
   TypeSubstitutionMap subs;
-  for (const auto &opened : openedTypes->second) {
-    subs[opened.first->castTo<GenericTypeParamType>()] =
-      getFixedType(opened.second);
-  }
+  for (const auto &opened : openedTypes->second)
+    subs[opened.first] = getFixedType(opened.second);
 
   auto &tc = getConstraintSystem().getTypeChecker();
 
@@ -441,8 +439,7 @@
   public:
     /// \brief Build a reference to the given declaration.
     Expr *buildDeclRef(ValueDecl *decl, DeclNameLoc loc, Type openedType,
-                       ConstraintLocatorBuilder locator,
-                       bool specialized, bool implicit,
+                       ConstraintLocatorBuilder locator, bool implicit,
                        FunctionRefKind functionRefKind,
                        AccessSemantics semantics) {
       // Determine the declaration selected for this overloaded reference.
@@ -2373,7 +2370,7 @@
       // FIXME: Cannibalize the existing DeclRefExpr rather than allocating a
       // new one?
       return buildDeclRef(decl, expr->getNameLoc(), selected->openedFullType,
-                          locator, expr->isSpecialized(),
+                          locator,
                           expr->isImplicit(),
                           expr->getFunctionRefKind(),
                           expr->getAccessSemantics());
@@ -2393,7 +2390,6 @@
     }
 
     Expr *visitOtherConstructorDeclRefExpr(OtherConstructorDeclRefExpr *expr) {
-      assert(!expr->getDeclRef().isSpecialized());
       cs.setType(expr, expr->getDecl()->getInitializerInterfaceType());
       return expr;
     }
@@ -2410,7 +2406,7 @@
       auto decl = choice.getDecl();
 
       return buildDeclRef(decl, expr->getNameLoc(), selected.openedFullType,
-                          locator, expr->isSpecialized(), expr->isImplicit(),
+                          locator, expr->isImplicit(),
                           choice.getFunctionRefKind(),
                           AccessSemantics::Ordinary);
     }
@@ -2423,16 +2419,6 @@
 
     Expr *visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *expr) {
       // Our specializations should have resolved the subexpr to the right type.
-      if (auto DRE = dyn_cast<DeclRefExpr>(expr->getSubExpr())) {
-        assert(DRE->getGenericArgs().empty() ||
-            DRE->getGenericArgs().size() == expr->getUnresolvedParams().size());
-        if (DRE->getGenericArgs().empty()) {
-          SmallVector<TypeRepr *, 8> GenArgs;
-          for (auto TL : expr->getUnresolvedParams())
-            GenArgs.push_back(TL.getTypeRepr());
-          DRE->setGenericArgs(GenArgs);
-        }
-      }
       return expr->getSubExpr();
     }
 
@@ -7612,12 +7598,11 @@
 Expr *Solution::coerceToType(Expr *expr, Type toType,
                              ConstraintLocator *locator,
                              bool ignoreTopLevelInjection,
-                             bool skipClosures,
                              Optional<Pattern*> typeFromPattern) const {
   auto &cs = getConstraintSystem();
   ExprRewriter rewriter(cs, *this,
                         /*suppressDiagnostics=*/false,
-                        /*skipClosures=*/skipClosures);
+                        /*skipClosures=*/false);
   Expr *result = rewriter.coerceToType(expr, toType, locator, typeFromPattern);
   if (!result)
     return nullptr;
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 03dc2ef..0477ee6 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -4737,7 +4737,7 @@
         continue;
 
       OverloadChoice choice(base ? base->getInterfaceType() : nullptr,
-                            candidate, false, UDE->getFunctionRefKind());
+                            candidate, UDE->getFunctionRefKind());
 
       if (base) { // Let's group all of the candidates have a common base.
         candidates[base].push_back(choice);
@@ -5694,7 +5694,6 @@
   SmallVector<OverloadChoice, 2> choices;
   for (auto &unviable : results.UnviableCandidates)
     choices.push_back(OverloadChoice(baseType, unviable.first,
-                                     /*isSpecialized=*/false,
                                      UDE->getFunctionRefKind()));
 
   CalleeCandidateInfo unviableCandidates(baseType, choices, hasTrailingClosure,
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 98fb72c..e80325c 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -1019,8 +1019,7 @@
         CS.getConstraintLocator(expr, ConstraintLocator::Member);
       auto tv = CS.createTypeVariable(memberLocator, TVO_CanBindToLValue);
 
-      OverloadChoice choice(CS.getType(base), decl, /*isSpecialized=*/false,
-                            functionRefKind);
+      OverloadChoice choice(CS.getType(base), decl, functionRefKind);
       auto locator = CS.getConstraintLocator(expr, ConstraintLocator::Member);
       CS.addBindOverloadConstraint(tv, choice, locator, CurDC);
       return tv;
@@ -1121,8 +1120,7 @@
       // a known subscript here. This might be cleaner if we split off a new
       // UnresolvedSubscriptExpr from SubscriptExpr.
       if (auto decl = declOrNull) {
-        OverloadChoice choice(baseTy, decl, /*isSpecialized=*/false,
-                              FunctionRefKind::DoubleApply);
+        OverloadChoice choice(baseTy, decl, FunctionRefKind::DoubleApply);
         CS.addBindOverloadConstraint(fnTy, choice, memberLocator,
                                      CurDC);
       } else {
@@ -1314,7 +1312,6 @@
       auto tv = CS.createTypeVariable(locator, TVO_CanBindToLValue);
       CS.resolveOverload(locator, tv,
                          OverloadChoice(Type(), E->getDecl(),
-                                        E->isSpecialized(),
                                         E->getFunctionRefKind()),
                          CurDC);
       
@@ -1391,7 +1388,6 @@
           continue;
 
         choices.push_back(OverloadChoice(Type(), decls[i],
-                                         expr->isSpecialized(),
                                          expr->getFunctionRefKind()));
       }
 
@@ -3342,8 +3338,15 @@
         createMemberConstraint(Req, ConstraintKind::ConformsTo);
         break;
       case RequirementKind::Layout:
-        // FIXME FIXME FIXME
-        createMemberConstraint(Req, ConstraintKind::ConformsTo);
+        if (Req.getLayoutConstraint()->isClass()) {
+          auto First = resolveType(Req.getFirstType());
+          CS.addConstraint(ConstraintKind::ConformsTo, First,
+                           CS.getASTContext().getAnyObjectType(),
+                           Loc);
+        }
+
+        // Nothing else can appear outside of @_specialize yet, and Sema
+        // doesn't know how to check.
         break;
       case RequirementKind::Superclass:
         createMemberConstraint(Req, ConstraintKind::Subtype);
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 33868bb..a4bff05 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -2999,8 +2999,7 @@
         }
       }
       
-      result.addViable(OverloadChoice(baseTy, ctor, /*isSpecialized=*/false,
-                                      functionRefKind));
+      result.addViable(OverloadChoice(baseTy, ctor, functionRefKind));
     }
 
 
@@ -3160,9 +3159,7 @@
         OverloadChoice::getDeclViaUnwrappedOptional(ovlBaseTy, cand,
                                                     functionRefKind));
     } else {
-      result.addViable(OverloadChoice(ovlBaseTy, cand,
-                                      /*isSpecialized=*/false,
-                                      functionRefKind));
+      result.addViable(OverloadChoice(ovlBaseTy, cand, functionRefKind));
     }
   };
 
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index db5ae5d..c2428f5 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -22,6 +22,7 @@
 #include "swift/AST/Availability.h"
 #include "swift/AST/Expr.h"
 #include "swift/AST/GenericEnvironment.h"
+#include "swift/AST/Initializer.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/ProtocolConformance.h"
 #include "swift/Basic/Defer.h"
@@ -89,13 +90,14 @@
 }
 
 static Type getTypeOfStorage(AbstractStorageDecl *storage,
-                             TypeChecker &TC,
                              bool wantInterfaceType) {
-  if (auto var = dyn_cast<VarDecl>(storage))
-    return TC.getTypeOfRValue(var, wantInterfaceType);
+  if (auto var = dyn_cast<VarDecl>(storage)) {
+    auto type = (wantInterfaceType
+                 ? var->getInterfaceType()
+                 : var->getType());
+    return type->getReferenceStorageReferent();
+  }
 
-  // None of the transformations done by getTypeOfRValue are
-  // necessary for subscripts.
   auto subscript = cast<SubscriptDecl>(storage);
   auto type = subscript->getElementInterfaceType();
   if (!wantInterfaceType)
@@ -142,10 +144,25 @@
   SmallVector<ParameterList*, 2> getterParams;
 
   // The implicit 'self' argument if in a type context.
-  if (storage->getDeclContext()->isTypeContext())
-    getterParams.push_back(ParameterList::createSelf(loc,
-                                                     storage->getDeclContext(),
-                                                     /*isStatic*/false));
+  if (storage->getDeclContext()->isTypeContext()) {
+    ParamDecl *selfDecl;
+
+    // For lazy properties, steal the 'self' from the initializer context.
+    if (storage->getAttrs().hasAttribute<LazyAttr>()) {
+      auto *varDecl = cast<VarDecl>(storage);
+      auto *bindingDecl = varDecl->getParentPatternBinding();
+      auto *bindingInit = cast<PatternBindingInitializer>(
+        bindingDecl->getPatternEntryForVarDecl(varDecl).getInitContext());
+
+      selfDecl = bindingInit->getImplicitSelfDecl();
+    } else {
+      selfDecl = ParamDecl::createSelf(loc,
+                                       storage->getDeclContext(),
+                                       /*isStatic*/false);
+    }
+
+    getterParams.push_back(ParameterList::create(TC.Context, selfDecl));
+  }
     
   // Add an index-forwarding clause.
   getterParams.push_back(buildIndexForwardingParamList(storage, {}));
@@ -156,7 +173,7 @@
       staticLoc = var->getLoc();
   }
 
-  auto storageInterfaceType = getTypeOfStorage(storage, TC, true);
+  auto storageInterfaceType = getTypeOfStorage(storage, true);
 
   auto getter = FuncDecl::create(
       TC.Context, staticLoc, StaticSpellingKind::None, loc, Identifier(), loc,
@@ -199,8 +216,8 @@
   }
   
   // Add a "(value : T, indices...)" argument list.
-  auto storageType = getTypeOfStorage(storage, TC, false);
-  auto storageInterfaceType = getTypeOfStorage(storage, TC, true);
+  auto storageType = getTypeOfStorage(storage, false);
+  auto storageInterfaceType = getTypeOfStorage(storage, true);
   valueDecl = buildLetArgument(storage->getLoc(),
                                storage->getDeclContext(), "value",
                                storageType,
@@ -615,7 +632,7 @@
 
   // We support @NSCopying on class types (which conform to NSCopying),
   // protocols which conform, and option types thereof.
-  Type UnderlyingType = TC.getTypeOfRValue(VD, /*want interface type*/false);
+  Type UnderlyingType = VD->getType()->getReferenceStorageReferent();
 
   bool isOptional = false;
   if (Type optionalEltTy = UnderlyingType->getAnyOptionalObjectType()) {
@@ -1145,7 +1162,6 @@
   // realize that they are in the getter function.
   InitValue->walk(RecontextualizeClosures(Get));
 
-
   Pattern *Tmp2PBDPattern = new (Ctx) NamedPattern(Tmp2VD, /*implicit*/true);
   Tmp2PBDPattern = new (Ctx) TypedPattern(Tmp2PBDPattern,
                                           TypeLoc::withoutLoc(VD->getType()),
@@ -1672,10 +1688,6 @@
   addMaterializeForSet(storage, TC);
 }
 
-void TypeChecker::introduceLazyVarAccessors(VarDecl *var) {
-  maybeAddAccessorsToVariable(var, *this);
-}
-
 void swift::maybeAddAccessorsToVariable(VarDecl *var, TypeChecker &TC) {
   if (var->getGetter())
     return;
@@ -1930,8 +1942,10 @@
       
       accessLevel = std::min(accessLevel, var->getFormalAccess());
 
-      auto varType = tc.getTypeOfRValue(var, false);
-      auto varInterfaceType = tc.getTypeOfRValue(var, true);
+      auto varType = var->getType()
+        ->getReferenceStorageReferent();
+      auto varInterfaceType = var->getInterfaceType()
+        ->getReferenceStorageReferent();
 
       // If var is a lazy property, its value is provided for the underlying
       // storage.  We thus take an optional of the properties type.  We only
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 8a07b816..4a07f2e 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -499,14 +499,12 @@
     auto resultTy = openType(genericFn->getResult(), replacements);
 
     // Build the resulting (non-generic) function type.
-    type = FunctionType::get(inputTy, resultTy,
-                             FunctionType::ExtInfo().
-                               withThrows(genericFn->throws()));
-  } else {
-    type = openType(funcType, replacements);
+    funcType = FunctionType::get(inputTy, resultTy,
+                                 FunctionType::ExtInfo().
+                                   withThrows(genericFn->throws()));
   }
 
-  return removeArgumentLabels(type, numArgumentLabelsToRemove);
+  return removeArgumentLabels(funcType, numArgumentLabelsToRemove);
 }
 
 Optional<Type> ConstraintSystem::isArrayType(Type type) {
@@ -603,6 +601,80 @@
   return type;
 }
 
+/// Does a var or subscript produce an l-value?
+///
+/// \param baseType - the type of the base on which this object
+///   is being accessed; must be null if and only if this is not
+///   a type member
+static bool doesStorageProduceLValue(TypeChecker &TC,
+                                     AbstractStorageDecl *storage,
+                                     Type baseType, DeclContext *useDC,
+                                     const DeclRefExpr *base = nullptr) {
+  // Unsettable storage decls always produce rvalues.
+  if (!storage->isSettable(useDC, base))
+    return false;
+  
+  if (TC.Context.LangOpts.EnableAccessControl &&
+      !storage->isSetterAccessibleFrom(useDC))
+    return false;
+
+  // If there is no base, or if the base isn't being used, it is settable.
+  // This is only possible for vars.
+  if (auto var = dyn_cast<VarDecl>(storage)) {
+    if (!baseType || var->isStatic())
+      return true;
+  }
+
+  // If the base is an lvalue, then a reference produces an lvalue.
+  if (baseType->is<LValueType>())
+    return true;
+
+  // Stored properties of reference types produce lvalues.
+  if (baseType->hasReferenceSemantics() && storage->hasStorage())
+    return true;
+
+  // So the base is an rvalue type. The only way an accessor can
+  // produce an lvalue is if we have a property where both the
+  // getter and setter are nonmutating.
+  return !storage->hasStorage() &&
+      !storage->isGetterMutating() &&
+      storage->isSetterNonMutating();
+}
+
+Type TypeChecker::getUnopenedTypeOfReference(VarDecl *value, Type baseType,
+                                             DeclContext *UseDC,
+                                             const DeclRefExpr *base,
+                                             bool wantInterfaceType) {
+  validateDecl(value);
+  if (value->isInvalid())
+    return ErrorType::get(Context);
+
+  Type requestedType = (wantInterfaceType
+                        ? value->getInterfaceType()
+                        : value->getType());
+
+  requestedType = requestedType->getLValueOrInOutObjectType()
+    ->getReferenceStorageReferent();
+
+  // If we're dealing with contextual types, and we referenced this type from
+  // a different context, map the type.
+  if (!wantInterfaceType && requestedType->hasArchetype()) {
+    auto valueDC = value->getDeclContext();
+    if (valueDC != UseDC) {
+      Type mapped = valueDC->mapTypeOutOfContext(requestedType);
+      requestedType = UseDC->mapTypeIntoContext(mapped);
+    }
+  }
+
+  // Qualify storage declarations with an lvalue when appropriate.
+  // Otherwise, they yield rvalues (and the access must be a load).
+  if (doesStorageProduceLValue(*this, value, baseType, UseDC, base)) {
+    return LValueType::get(requestedType);
+  }
+
+  return requestedType;
+}
+
 void ConstraintSystem::recordOpenedTypes(
        ConstraintLocatorBuilder locator,
        const OpenedTypeMap &replacements) {
@@ -675,7 +747,6 @@
 
 std::pair<Type, Type>
 ConstraintSystem::getTypeOfReference(ValueDecl *value,
-                                     bool isSpecialized,
                                      FunctionRefKind functionRefKind,
                                      ConstraintLocatorBuilder locator,
                                      const DeclRefExpr *base) {
@@ -717,12 +788,34 @@
     return { openedType, openedFnType->getResult() };
   }
 
-  // If we have a type declaration, resolve it within the current context.
+  // Unqualified reference to a local or global function.
+  if (auto funcDecl = dyn_cast<AbstractFunctionDecl>(value)) {
+    OpenedTypeMap replacements;
+
+    auto funcType = funcDecl->getInterfaceType()->castTo<AnyFunctionType>();
+    auto openedType =
+      openFunctionType(
+        funcType,
+        getNumRemovedArgumentLabels(TC.Context, funcDecl,
+                                    /*isCurriedInstanceReference=*/false,
+                                    functionRefKind),
+        locator, replacements,
+        funcDecl->getInnermostDeclContext(),
+        funcDecl->getDeclContext(),
+        /*skipProtocolSelfConstraint=*/false);
+
+    // If we opened up any type variables, record the replacements.
+    recordOpenedTypes(locator, replacements);
+
+    return { openedType, openedType };
+  }
+
+  // Unqualified reference to a type.
   if (auto typeDecl = dyn_cast<TypeDecl>(value)) {
     // Resolve the reference to this type declaration in our current context.
-    auto type = getTypeChecker().resolveTypeInContext(typeDecl, DC,
-                                                      TR_InExpression,
-                                                      isSpecialized);
+    auto type = TC.resolveTypeInContext(typeDecl, DC,
+                                        TR_InExpression,
+                                        /*isSpecialized=*/false);
 
     // Open the type.
     type = openUnboundGenericType(type, locator);
@@ -736,18 +829,22 @@
     return { type, type };
   }
 
+  // Only remaining case: unqualified reference to a property.
+  auto *varDecl = cast<VarDecl>(value);
+
   // Determine the type of the value, opening up that type if necessary.
-  bool wantInterfaceType = true;
-  if (isa<VarDecl>(value))
-    wantInterfaceType = !value->getDeclContext()->isLocalContext();
-  Type valueType = TC.getUnopenedTypeOfReference(value, Type(), DC, base,
+  bool wantInterfaceType = !varDecl->getDeclContext()->isLocalContext();
+  Type valueType = TC.getUnopenedTypeOfReference(varDecl, Type(), DC, base,
                                                  wantInterfaceType);
 
+  assert(!valueType->hasUnboundGenericType() &&
+         !valueType->hasTypeParameter());
+
   // If this is a let-param whose type is a type variable, this is an untyped
   // closure param that may be bound to an inout type later. References to the
   // param should have lvalue type instead. Express the relationship with a new
   // constraint.
-  if (auto *param = dyn_cast<ParamDecl>(value)) {
+  if (auto *param = dyn_cast<ParamDecl>(varDecl)) {
     if (param->isLet() && valueType->is<TypeVariableType>()) {
       Type paramType = valueType;
       valueType = createTypeVariable(getConstraintLocator(locator),
@@ -757,28 +854,6 @@
     }
   }
 
-  // Adjust the type of the reference.
-  if (auto funcType = valueType->getAs<AnyFunctionType>()) {
-    OpenedTypeMap replacements;
-
-    valueType =
-      openFunctionType(
-          funcType,
-          getNumRemovedArgumentLabels(TC.Context, value,
-                                      /*isCurriedInstanceReference=*/false,
-                                      functionRefKind),
-          locator, replacements,
-          value->getInnermostDeclContext(),
-          value->getDeclContext(),
-          /*skipProtocolSelfConstraint=*/false);
-
-    // If we opened up any type variables, record the replacements.
-    recordOpenedTypes(locator, replacements);
-  } else {
-    assert(!valueType->hasUnboundGenericType() &&
-           !valueType->hasTypeParameter());
-  }
-
   return { valueType, valueType };
 }
 
@@ -996,8 +1071,7 @@
 
   // If the base is a module type, just use the type of the decl.
   if (baseObjTy->is<ModuleType>()) {
-    return getTypeOfReference(value, /*isSpecialized=*/false,
-                              functionRefKind, locator, base);
+    return getTypeOfReference(value, functionRefKind, locator, base);
   }
 
   // Don't open existentials when accessing typealias members of
@@ -1005,17 +1079,24 @@
   if (auto *alias = dyn_cast<TypeAliasDecl>(value)) {
     if (baseObjTy->isExistentialType()) {
       auto memberTy = alias->getDeclaredInterfaceType();
+      // If we end up with a protocol typealias here, it's underlying
+      // type must be fully concrete.
+      assert(!memberTy->hasTypeParameter());
       auto openedType = FunctionType::get(baseObjTy, memberTy);
       return { openedType, memberTy };
     }
   }
 
-  // Handle associated type lookup as a special case, horribly.
-  // FIXME: This is an awful hack.
-  if (isa<AssociatedTypeDecl>(value)) {
-    // Refer to a member of the archetype directly.
-    auto archetype = baseObjTy->castTo<ArchetypeType>();
-    Type memberTy = archetype->getNestedType(value->getName());
+  if (auto *typeDecl = dyn_cast<TypeDecl>(value)) {
+    assert(!isa<ModuleDecl>(typeDecl) && "Nested module?");
+
+    auto memberTy = TC.substMemberTypeWithBase(DC->getParentModule(),
+                                               typeDecl, baseObjTy);
+
+    // Open the type if it was a reference to a generic type.
+    memberTy = openUnboundGenericType(memberTy, locator);
+
+    // Wrap it in a metatype.
     memberTy = MetatypeType::get(memberTy);
 
     auto openedType = FunctionType::get(baseObjTy, memberTy);
@@ -1035,48 +1116,68 @@
     getNumRemovedArgumentLabels(TC.Context, value, isCurriedInstanceReference,
                                 functionRefKind);
 
+  AnyFunctionType *funcType;
+
   if (isa<AbstractFunctionDecl>(value) ||
       isa<EnumElementDecl>(value)) {
     // This is the easy case.
-    auto funcType = value->getInterfaceType()->getAs<AnyFunctionType>();
-
-    openedType = openFunctionType(funcType, numRemovedArgumentLabels,
-                                  locator, replacements, innerDC, outerDC,
-                                  /*skipProtocolSelfConstraint=*/true);
+    funcType = value->getInterfaceType()->castTo<AnyFunctionType>();
   } else {
-    // If we're not coming from something function-like, prepend the type
-    // for 'self' to the type.
-    assert(isa<AbstractStorageDecl>(value) ||
-           isa<TypeDecl>(value));
+    // For a property, build a type (Self) -> PropType.
+    // For a subscript, build a type (Self) -> (Indices...) -> ElementType.
+    //
+    // If the access is mutating, wrap the storage type in an lvalue type.
+    Type refType;
+    if (auto *subscript = dyn_cast<SubscriptDecl>(value)) {
+      auto elementTy = subscript->getElementInterfaceType();
 
-    openedType = TC.getUnopenedTypeOfReference(value, baseTy, useDC, base,
-                                               /*wantInterfaceType=*/true);
+      if (doesStorageProduceLValue(TC, subscript, baseTy, useDC, base))
+        elementTy = LValueType::get(elementTy);
 
-    // Remove argument labels, if needed.
-    openedType = removeArgumentLabels(openedType, numRemovedArgumentLabels);
+      // See ConstraintSystem::resolveOverload() -- optional and dynamic
+      // subscripts are a special case, because the optionality is
+      // applied to the result type and not the type of the reference.
+      if (!isRequirementOrWitness(locator)) {
+        if (subscript->getAttrs().hasAttribute<OptionalAttr>())
+          elementTy = OptionalType::get(elementTy->getRValueType());
+        else if (isDynamicResult) {
+          elementTy = ImplicitlyUnwrappedOptionalType::get(
+            elementTy->getRValueType());
+        }
+      }
 
-    // Open up the generic parameter list for the container.
-    openGeneric(innerDC, outerDC, innerDC->getGenericSignatureOfContext(),
-                /*skipProtocolSelfConstraint=*/true,
-                locator, replacements);
+      auto indicesTy = subscript->getIndicesInterfaceType();
+      refType = FunctionType::get(indicesTy, elementTy,
+                                  AnyFunctionType::ExtInfo());
+    } else {
+      refType = TC.getUnopenedTypeOfReference(cast<VarDecl>(value),
+                                              baseTy, useDC, base,
+                                              /*wantInterfaceType=*/true);
+    }
 
-    // Open up the type of the member.
-    openedType = openType(openedType, replacements);
+    auto selfTy = outerDC->getSelfInterfaceType();
 
-    // Determine the object type of 'self'.
-    auto selfTy = openType(outerDC->getSelfInterfaceType(),
-                           replacements);
-
-    // If self is a struct, properly qualify it based on our base
-    // qualification.  If we have an lvalue coming in, we expect an inout.
+    // If self is a value type and the base type is an lvalue, wrap it in an
+    // inout type.
     if (!outerDC->getDeclaredTypeOfContext()->hasReferenceSemantics() &&
         baseTy->is<LValueType>() &&
         !selfTy->hasError())
       selfTy = InOutType::get(selfTy);
 
-    openedType = FunctionType::get(selfTy, openedType);
+    // If the storage is generic, add a generic signature.
+    if (auto *sig = innerDC->getGenericSignatureOfContext()) {
+      funcType = GenericFunctionType::get(sig, selfTy, refType,
+                                          AnyFunctionType::ExtInfo());
+    } else {
+      funcType = FunctionType::get(selfTy, refType,
+                                   AnyFunctionType::ExtInfo());
+    }
   }
 
+  openedType = openFunctionType(funcType, numRemovedArgumentLabels,
+                                locator, replacements, innerDC, outerDC,
+                                /*skipProtocolSelfConstraint=*/true);
+
   if (!outerDC->getAsProtocolOrProtocolExtensionContext()) {
     // Class methods returning Self as well as constructors get the
     // result replaced with the base object type.
@@ -1122,27 +1223,9 @@
 
   // Compute the type of the reference.
   Type type;
-  if (auto subscript = dyn_cast<SubscriptDecl>(value)) {
-    // For a subscript, turn the element type into an (@unchecked)
-    // optional or lvalue, depending on whether the result type is
-    // optional/dynamic, is settable, or is not.
-    auto fnType = openedFnType->getResult()->castTo<FunctionType>();
-    auto elementTy = fnType->getResult();
-    if (!isRequirementOrWitness(locator)) {
-      if (subscript->getAttrs().hasAttribute<OptionalAttr>())
-        elementTy = OptionalType::get(elementTy->getRValueType());
-      else if (isDynamicResult) {
-        elementTy = ImplicitlyUnwrappedOptionalType::get(
-                      elementTy->getRValueType());
-      }
-    }
-
-    type = FunctionType::get(fnType->getInput(), elementTy);
-  } else if (!value->isInstanceMember() || isInstance) {
-    // For a constructor, enum element, static method, static property,
-    // or an instance method referenced through an instance, we've consumed the
-    // curried 'self' already. For a type, strip off the 'self' we artificially
-    // added.
+  if (!value->isInstanceMember() || isInstance) {
+    // For a static member referenced through a metatype or an instance
+    // member referenced through an instance, strip off the 'self'.
     type = openedFnType->getResult();
   } else if (isDynamicResult && isa<AbstractFunctionDecl>(value)) {
     // For a dynamic result referring to an instance function through
@@ -1380,7 +1463,6 @@
     } else {
       std::tie(openedFullType, refType)
         = getTypeOfReference(choice.getDecl(),
-                             choice.isSpecialized(),
                              choice.getFunctionRefKind(), locator);
     }
 
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index eefaf33..26adfc0 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -575,9 +575,6 @@
   /// on a suspicious top-level optional injection (because the caller already
   /// diagnosed it).
   ///
-  /// \param skipClosures Whether to skip bodies of non-single expression
-  /// closures.
-  ///
   /// \param typeFromPattern Optionally, the caller can specify the pattern
   /// from where the toType is derived, so that we can deliver better fixit.
   ///
@@ -585,7 +582,6 @@
   Expr *coerceToType(Expr *expr, Type toType,
                      ConstraintLocator *locator,
                      bool ignoreTopLevelInjection = false,
-                     bool skipClosures = false,
                      Optional<Pattern*> typeFromPattern = None) const;
 
   /// \brief Convert the given expression to a logic value.
@@ -1959,13 +1955,10 @@
   ///
   /// \param decl The declarations whose type is being computed.
   ///
-  /// \param isSpecialized Whether this declaration is immediately specialized.
-  ///
   /// \returns a pair containing the full opened type (if applicable) and
   /// opened type of a reference to declaration.
   std::pair<Type, Type> getTypeOfReference(
                           ValueDecl *decl,
-                          bool isSpecialized,
                           FunctionRefKind functionRefKind,
                           ConstraintLocatorBuilder locator,
                           const DeclRefExpr *base = nullptr);
diff --git a/lib/Sema/OverloadChoice.h b/lib/Sema/OverloadChoice.h
index 635715a..ee9f0a2 100644
--- a/lib/Sema/OverloadChoice.h
+++ b/lib/Sema/OverloadChoice.h
@@ -65,8 +65,6 @@
 /// 
 class OverloadChoice {
   enum : unsigned {
-    /// Indicates whether this overload was immediately specialized.
-    IsSpecializedBit = 0x01,
     /// Indicates whether this declaration was bridged, turning a
     /// "Decl" kind into "DeclViaBridge" kind.
     IsBridgedBit = 0x02,
@@ -81,9 +79,7 @@
   };
 
   /// \brief The base type to be used when referencing the declaration
-  /// along with two bits: the low bit indicates whether this overload
-  /// was immediately specialized and the second lowest bit indicates
-  /// whether the declaration was bridged.
+  /// along with the two bits above.
   llvm::PointerIntPair<Type, 3, unsigned> BaseAndBits;
 
   /// \brief Either the declaration pointer (if the low bit is clear) or the
@@ -99,9 +95,9 @@
     : BaseAndBits(nullptr, 0), DeclOrKind(0),
       TheFunctionRefKind(FunctionRefKind::Unapplied) {}
 
-  OverloadChoice(Type base, ValueDecl *value, bool isSpecialized,
+  OverloadChoice(Type base, ValueDecl *value,
                  FunctionRefKind functionRefKind)
-    : BaseAndBits(base, isSpecialized ? IsSpecializedBit : 0),
+    : BaseAndBits(base, 0),
       TheFunctionRefKind(functionRefKind) {
     assert(!base || !base->hasTypeParameter());
     assert((reinterpret_cast<uintptr_t>(value) & (uintptr_t)0x03) == 0 &&
@@ -178,14 +174,6 @@
 
   /// \brief Retrieve the base type used to refer to the declaration.
   Type getBaseType() const { return BaseAndBits.getPointer(); }
-
-  /// \brief Determine whether the referenced declaration was immediately
-  /// specialized with <...>.
-  ///
-  /// This value only has meaning when there is no base type.
-  bool isSpecialized() const { 
-    return BaseAndBits.getInt() & IsSpecializedBit;
-  }
   
   /// \brief Determines the kind of overload choice this is.
   OverloadChoiceKind getKind() const {
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index 6c657b3..a43c95e 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -107,6 +107,7 @@
   IGNORED_ATTR(NSKeyedArchiverClassName)
   IGNORED_ATTR(StaticInitializeObjCMetadata)
   IGNORED_ATTR(NSKeyedArchiverEncodeNonGenericSubclassesOnly)
+  IGNORED_ATTR(DowngradeExhaustivityCheck)
 #undef IGNORED_ATTR
 
   // @noreturn has been replaced with a 'Never' return type.
@@ -784,6 +785,7 @@
     IGNORED_ATTR(ObjCMembers)
     IGNORED_ATTR(StaticInitializeObjCMetadata)
     IGNORED_ATTR(NSKeyedArchiverEncodeNonGenericSubclassesOnly)
+    IGNORED_ATTR(DowngradeExhaustivityCheck)
 #undef IGNORED_ATTR
 
   void visitAvailableAttr(AvailableAttr *attr);
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index d974bcb..1035ea5 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -581,8 +581,7 @@
     }
 
     return buildRefExpr(ResultValues, DC, UDRE->getNameLoc(),
-                        UDRE->isImplicit(), UDRE->isSpecialized(),
-                        UDRE->getFunctionRefKind());
+                        UDRE->isImplicit(), UDRE->getFunctionRefKind());
   }
 
   ResultValues.clear();
@@ -1631,6 +1630,10 @@
   return false;
 }
 
+Expr *ExprTypeCheckListener::foundSolution(Solution &solution, Expr *expr) {
+  return expr;
+}
+
 Expr *ExprTypeCheckListener::appliedSolution(Solution &solution, Expr *expr) {
   return expr;
 }
@@ -1864,14 +1867,24 @@
     expr->setType(ErrorType::get(Context));
     return false;
   }
-  
-  // Apply the solution to the expression.
+
+  auto result = expr;
   auto &solution = viable[0];
+  if (listener) {
+    result = listener->foundSolution(solution, result);
+    if (!result)
+      return true;
+  }
+
+  if (options.contains(TypeCheckExprFlags::SkipApplyingSolution))
+    return false;
+
+  // Apply the solution to the expression.
   bool isDiscarded = options.contains(TypeCheckExprFlags::IsDiscarded);
   bool skipClosures = options.contains(TypeCheckExprFlags::SkipMultiStmtClosures);
-  auto result = cs.applySolution(solution, expr, convertType.getType(),
-                                 isDiscarded, suppressDiagnostics,
-                                 skipClosures);
+  result = cs.applySolution(solution, result, convertType.getType(),
+                            isDiscarded, suppressDiagnostics,
+                            skipClosures);
   if (!result) {
     // Failure already diagnosed, above, as part of applying the solution.
     return true;
@@ -2111,26 +2124,25 @@
 }
 
 bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
-                                   DeclContext *DC, bool skipClosures) {
+                                   DeclContext *DC, bool skipApplyingSolution) {
 
   /// Type checking listener for pattern binding initializers.
   class BindingListener : public ExprTypeCheckListener {
     Pattern *&pattern;
     Expr *&initializer;
-    DeclContext *DC;
-    bool skipClosures;
 
     /// The locator we're using.
     ConstraintLocator *Locator;
 
     /// The type of the initializer.
     Type InitType;
-    
+
   public:
-    explicit BindingListener(Pattern *&pattern, Expr *&initializer,
-                             DeclContext *DC, bool skipClosures)
-      : pattern(pattern), initializer(initializer), DC(DC),
-        skipClosures(skipClosures) { }
+    explicit BindingListener(Pattern *&pattern, Expr *&initializer)
+      : pattern(pattern), initializer(initializer),
+        Locator(nullptr) { }
+
+    Type getInitType() const { return InitType; }
 
     bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
       // Save the locator we're using for the expression.
@@ -2150,44 +2162,32 @@
       return false;
     }
 
-    Expr *appliedSolution(Solution &solution, Expr *expr) override {
+    Expr *foundSolution(Solution &solution, Expr *expr) override {
       // Figure out what type the constraints decided on.
-      auto &cs = solution.getConstraintSystem();
-      auto &tc = cs.getTypeChecker();
       InitType = solution.simplifyType(InitType);
 
+      // Just keep going.
+      return expr;
+    }
+
+    Expr *appliedSolution(Solution &solution, Expr *expr) override {
       // Convert the initializer to the type of the pattern.
       // ignoreTopLevelInjection = Binding->isConditional()
       expr = solution.coerceToType(expr, InitType, Locator,
-                                   false /* ignoreTopLevelInjection */,
-                                   skipClosures);
+                                   false /* ignoreTopLevelInjection */);
       if (!expr) {
         return nullptr;
       }
 
-      // Force the initializer to be materializable.
-      // FIXME: work this into the constraint system
-      expr = tc.coerceToMaterializable(expr);
+      assert(expr->getType()->isEqual(InitType));
 
-      // Apply the solution to the pattern as well.
-      Type patternType = expr->getType();
-
-      TypeResolutionOptions options;
-      options |= TR_OverrideType;
-      options |= TR_InExpression;
-      if (isa<EditorPlaceholderExpr>(expr->getSemanticsProvidingExpr())) {
-        options |= TR_EditorPlaceholder;
-      }
-      if (tc.coercePatternToType(pattern, DC, patternType, options)) {
-        return nullptr;
-      }
       initializer = expr;
       return expr;
     }
   };
 
   assert(initializer && "type-checking an uninitialized binding?");
-  BindingListener listener(pattern, initializer, DC, skipClosures);
+  BindingListener listener(pattern, initializer);
 
   TypeLoc contextualType;
   auto contextualPurpose = CTP_Unused;
@@ -2209,18 +2209,34 @@
     
   // Type-check the initializer.
   TypeCheckExprOptions flags = TypeCheckExprFlags::ConvertTypeIsOnlyAHint;
-  if (skipClosures)
-    flags |= TypeCheckExprFlags::SkipMultiStmtClosures;
+  if (skipApplyingSolution)
+    flags |= TypeCheckExprFlags::SkipApplyingSolution;
 
   bool hadError = typeCheckExpression(initializer, DC, contextualType,
                                      contextualPurpose,
                                      flags,
                                      &listener);
-  
-  if (hadError && !initializer->getType()) {
-    initializer->setType(ErrorType::get(Context));
+
+  if (!hadError) {
+    TypeResolutionOptions options;
+    options |= TR_OverrideType;
+    options |= TR_InExpression;
+    if (isa<EditorPlaceholderExpr>(initializer->getSemanticsProvidingExpr())) {
+      options |= TR_EditorPlaceholder;
+    }
+
+    // Apply the solution to the pattern as well.
+    if (coercePatternToType(pattern, DC, listener.getInitType(), options)) {
+      return true;
+    }
   }
 
+  if (hadError && !initializer->getType())
+    initializer->setType(ErrorType::get(Context));
+
+  // If the type of the pattern is inferred, assign error types to the pattern
+  // and its variables, to prevent it from being referenced by the constraint
+  // system.
   if (hadError &&
       (!pattern->hasType() ||
        pattern->getType()->hasUnboundGenericType())) {
@@ -2242,7 +2258,7 @@
 
 bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
                                           unsigned patternNumber,
-                                          bool skipClosures) {
+                                          bool skipApplyingSolution) {
 
   Pattern *pattern = PBD->getPattern(patternNumber);
   Expr *init = PBD->getInit(patternNumber);
@@ -2262,11 +2278,10 @@
       DC = initContext;
   }
 
-  bool hadError = typeCheckBinding(pattern, init, DC, skipClosures);
+  bool hadError = typeCheckBinding(pattern, init, DC, skipApplyingSolution);
   PBD->setPattern(patternNumber, pattern, initContext);
   PBD->setInit(patternNumber, init);
 
-
   // If we entered an initializer context, contextualize any
   // auto-closures we might have created.
   if (initContext) {
@@ -2600,7 +2615,8 @@
     // If the pattern didn't get a type, it's because we ran into some
     // unknown types along the way. We'll need to check the initializer.
     auto init = elt.getInitializer();
-    hadError |= typeCheckBinding(pattern, init, dc, /*skipClosures*/false);
+    hadError |= typeCheckBinding(pattern, init, dc,
+                                 /*skipApplyingSolution*/false);
     elt.setPattern(pattern);
     elt.setInitializer(init);
     hadAnyFalsable |= pattern->isRefutablePattern();
@@ -2657,8 +2673,7 @@
   // Build the 'expr ~= var' expression.
   // FIXME: Compound name locations.
   auto *matchOp = buildRefExpr(choices, DC, DeclNameLoc(EP->getLoc()),
-                               /*Implicit=*/true, /*isSpecialized=*/false,
-                               FunctionRefKind::Compound);
+                               /*Implicit=*/true, FunctionRefKind::Compound);
   auto *matchVarRef = new (Context) DeclRefExpr(matchVar,
                                                 DeclNameLoc(EP->getLoc()),
                                                 /*Implicit=*/true);
@@ -2917,7 +2932,6 @@
   Expr *result = solution.coerceToType(expr, type,
                                        cs.getConstraintLocator(expr),
                                        /*ignoreTopLevelInjection*/false,
-                                       /*skipClosures*/false,
                                        typeFromPattern);
   if (!result) {
     return true;
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 7ce273b..6994a3d 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -1198,11 +1198,11 @@
   // If the pattern didn't get a type or if it contains an unbound generic type,
   // we'll need to check the initializer.
   if (!pattern->hasType() || pattern->getType()->hasUnboundGenericType()) {
-    bool skipClosures = false;
+    bool skipApplyingSolution = false;
     if (auto var = binding->getSingleVar())
-      skipClosures = var->getAttrs().hasAttribute<LazyAttr>();
+      skipApplyingSolution = var->getAttrs().hasAttribute<LazyAttr>();
 
-    if (tc.typeCheckPatternBinding(binding, entryNumber, skipClosures))
+    if (tc.typeCheckPatternBinding(binding, entryNumber, skipApplyingSolution))
       return;
   }
 
@@ -4047,7 +4047,7 @@
     if (!IsFirstPass) {
       for (unsigned i = 0, e = PBD->getNumPatternEntries(); i != e; ++i) {
         if (!PBD->isInitializerChecked(i) && PBD->getInit(i))
-          TC.typeCheckPatternBinding(PBD, i, /*skipClosures*/false);
+          TC.typeCheckPatternBinding(PBD, i, /*skipApplyingSolution*/false);
       }
     }
 
@@ -4078,7 +4078,7 @@
             // If we got a default initializer, install it and re-type-check it
             // to make sure it is properly coerced to the pattern type.
             PBD->setInit(i, defaultInit);
-            TC.typeCheckPatternBinding(PBD, i, /*skipClosures*/false);
+            TC.typeCheckPatternBinding(PBD, i, /*skipApplyingSolution*/false);
           }
         }
       }
@@ -6142,6 +6142,7 @@
     UNINTERESTING_ATTR(NSKeyedArchiverClassName)
     UNINTERESTING_ATTR(StaticInitializeObjCMetadata)
     UNINTERESTING_ATTR(NSKeyedArchiverEncodeNonGenericSubclassesOnly)
+    UNINTERESTING_ATTR(DowngradeExhaustivityCheck)
 #undef UNINTERESTING_ATTR
 
     void visitAvailableAttr(AvailableAttr *attr) {
diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp
index 20eff06..3005be9 100644
--- a/lib/Sema/TypeCheckExpr.cpp
+++ b/lib/Sema/TypeCheckExpr.cpp
@@ -492,23 +492,6 @@
   return makeBinOp(TC, op1.op, LHS, RHS, op1.precedence, S.empty());
 }
 
-Type TypeChecker::getTypeOfRValue(ValueDecl *value, bool wantInterfaceType) {
-
-  Type type;
-  if (wantInterfaceType) {
-    if (!value->hasInterfaceType())
-      validateDecl(value);
-    type = value->getInterfaceType();
-  } else {
-    auto *var = cast<VarDecl>(value);
-    if (!var->hasType())
-      validateDecl(var);
-    type = var->getType();
-  }
-
-  return type->getLValueOrInOutObjectType()->getReferenceStorageReferent();
-}
-
 bool TypeChecker::requireOptionalIntrinsics(SourceLoc loc) {
   if (Context.hasOptionalIntrinsics(this)) return false;
 
@@ -530,94 +513,6 @@
   return true;
 }
 
-/// Does a var or subscript produce an l-value?
-///
-/// \param baseType - the type of the base on which this object
-///   is being accessed; must be null if and only if this is not
-///   a type member
-static bool doesStorageProduceLValue(TypeChecker &TC,
-                                     AbstractStorageDecl *storage,
-                                     Type baseType, DeclContext *useDC,
-                                     const DeclRefExpr *base = nullptr) {
-  // Unsettable storage decls always produce rvalues.
-  if (!storage->isSettable(useDC, base))
-    return false;
-  
-  if (TC.Context.LangOpts.EnableAccessControl &&
-      !storage->isSetterAccessibleFrom(useDC))
-    return false;
-
-  // If there is no base, or if the base isn't being used, it is settable.
-  // This is only possible for vars.
-  if (auto var = dyn_cast<VarDecl>(storage)) {
-    if (!baseType || var->isStatic())
-      return true;
-  }
-
-  // If the base is an lvalue, then a reference produces an lvalue.
-  if (baseType->is<LValueType>())
-    return true;
-
-  // Stored properties of reference types produce lvalues.
-  if (baseType->hasReferenceSemantics() && storage->hasStorage())
-    return true;
-
-  // So the base is an rvalue type. The only way an accessor can
-  // produce an lvalue is if we have a property where both the
-  // getter and setter are nonmutating.
-  return !storage->hasStorage() &&
-      !storage->isGetterMutating() &&
-      storage->isSetterNonMutating();
-}
-
-Type TypeChecker::getUnopenedTypeOfReference(ValueDecl *value, Type baseType,
-                                             DeclContext *UseDC,
-                                             const DeclRefExpr *base,
-                                             bool wantInterfaceType) {
-  validateDecl(value);
-  if (value->isInvalid())
-    return ErrorType::get(Context);
-
-  Type requestedType = getTypeOfRValue(value, wantInterfaceType);
-
-  // If we're dealing with contextual types, and we referenced this type from
-  // a different context, map the type.
-  if (!wantInterfaceType && requestedType->hasArchetype()) {
-    auto valueDC = value->getDeclContext();
-    if (valueDC != UseDC) {
-      Type mapped = valueDC->mapTypeOutOfContext(requestedType);
-      requestedType = UseDC->mapTypeIntoContext(mapped);
-    }
-  }
-
-  // Qualify storage declarations with an lvalue when appropriate.
-  // Otherwise, they yield rvalues (and the access must be a load).
-  if (auto *storage = dyn_cast<AbstractStorageDecl>(value)) {
-    if (doesStorageProduceLValue(*this, storage, baseType, UseDC, base)) {
-      // Vars are simply lvalues of their rvalue type.
-      if (isa<VarDecl>(storage))
-        return LValueType::get(requestedType);
-
-      // Subscript decls have function type.  For the purposes of later type
-      // checker consumption, model this as returning an lvalue.
-      assert(isa<SubscriptDecl>(storage));
-      auto *RFT = requestedType->castTo<AnyFunctionType>();
-      return FunctionType::get(RFT->getInput(),
-                               LValueType::get(RFT->getResult()),
-                               RFT->getExtInfo());
-    }
-
-    // FIXME: Fix downstream callers.
-    if (auto *genericFn = requestedType->getAs<GenericFunctionType>()) {
-      return FunctionType::get(genericFn->getInput(),
-                               genericFn->getResult(),
-                               genericFn->getExtInfo());
-    }
-  }
-
-  return requestedType;
-}
-
 Expr *TypeChecker::buildCheckedRefExpr(VarDecl *value, DeclContext *UseDC,
                                        DeclNameLoc loc, bool Implicit) {
   auto type = getUnopenedTypeOfReference(value, Type(), UseDC);
@@ -627,22 +522,16 @@
 
 Expr *TypeChecker::buildRefExpr(ArrayRef<ValueDecl *> Decls,
                                 DeclContext *UseDC, DeclNameLoc NameLoc,
-                                bool Implicit, bool isSpecialized,
-                                FunctionRefKind functionRefKind) {
+                                bool Implicit, FunctionRefKind functionRefKind) {
   assert(!Decls.empty() && "Must have at least one declaration");
 
   if (Decls.size() == 1 && !isa<ProtocolDecl>(Decls[0]->getDeclContext())) {
     AccessSemantics semantics = Decls[0]->getAccessSemanticsFromContext(UseDC);
-    auto result = new (Context) DeclRefExpr(Decls[0], NameLoc, Implicit,
-                                            semantics);
-    if (isSpecialized)
-      result->setSpecialized();
-    return result;
+    return new (Context) DeclRefExpr(Decls[0], NameLoc, Implicit, semantics);
   }
 
   Decls = Context.AllocateCopy(Decls);
   auto result = new (Context) OverloadedDeclRefExpr(Decls, NameLoc, 
-                                                    isSpecialized,
                                                     functionRefKind,
                                                     Implicit);
   return result;
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 6b224dd..0c2eb88 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -1108,7 +1108,7 @@
       NP->getDecl()->setLet(false);
     }
     if (var->getAttrs().hasAttribute<OwnershipAttr>())
-      type = getTypeOfRValue(var, false);
+      type = var->getType()->getReferenceStorageReferent();
     else if (!var->isInvalid())
       type = var->getType();
     P->setType(type);
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 02ffb2d..49dd244 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -1193,19 +1193,16 @@
     witnessLocator = cs->getConstraintLocator(
                        static_cast<Expr *>(nullptr),
                        LocatorPathElt(ConstraintLocator::Witness, witness));
-    OpenedTypeMap witnessReplacements;
     if (witness->getDeclContext()->isTypeContext()) {
       std::tie(openedFullWitnessType, openWitnessType) 
         = cs->getTypeOfMemberReference(selfTy, witness, dc,
                                        /*isDynamicResult=*/false,
                                        FunctionRefKind::DoubleApply,
                                        witnessLocator,
-                                       /*base=*/nullptr,
-                                       &witnessReplacements);
+                                       /*base=*/nullptr);
     } else {
       std::tie(openedFullWitnessType, openWitnessType) 
         = cs->getTypeOfReference(witness,
-                                 /*isSpecialized=*/false,
                                  FunctionRefKind::DoubleApply,
                                  witnessLocator,
                                  /*base=*/nullptr);
@@ -6017,7 +6014,7 @@
 /// Infer the attribute tostatic-initialize the Objective-C metadata for the
 /// given class, if needed.
 static void inferStaticInitializeObjCMetadata(ClassDecl *classDecl,
-                                               bool requiresNSCodingAttr) {
+                                              bool requiresNSCodingAttr) {
   // If we already have the attribute, there's nothing to do.
   if (classDecl->getAttrs().hasAttribute<StaticInitializeObjCMetadataAttr>())
     return;
diff --git a/lib/Sema/TypeCheckREPL.cpp b/lib/Sema/TypeCheckREPL.cpp
index 532d82a..abd1711 100644
--- a/lib/Sema/TypeCheckREPL.cpp
+++ b/lib/Sema/TypeCheckREPL.cpp
@@ -97,15 +97,13 @@
   Expr *buildPrintRefExpr(SourceLoc loc) {
     assert(!C.PrintDecls.empty());
     return TC.buildRefExpr(C.PrintDecls, DC, DeclNameLoc(loc),
-                           /*Implicit=*/true, /*isSpecialized=*/false,
-                           FunctionRefKind::Compound);
+                           /*Implicit=*/true, FunctionRefKind::Compound);
   }
 
   Expr *buildDebugPrintlnRefExpr(SourceLoc loc) {
     assert(!C.DebugPrintlnDecls.empty());
     return TC.buildRefExpr(C.DebugPrintlnDecls, DC, DeclNameLoc(loc),
-                           /*Implicit=*/true, /*isSpecialized=*/false,
-                           FunctionRefKind::Compound);
+                           /*Implicit=*/true, FunctionRefKind::Compound);
   }
 };
 } // unnamed namespace
@@ -119,7 +117,6 @@
 void StmtBuilder::printReplExpr(VarDecl *Arg, SourceLoc Loc) {
   Expr *DebugPrintlnFn = buildDebugPrintlnRefExpr(Loc);
   Expr *ArgRef = TC.buildRefExpr(Arg, DC, DeclNameLoc(Loc), /*Implicit=*/true,
-                                 /*isSpecialized=*/false,
                                  FunctionRefKind::Compound);
   addToBody(CallExpr::createImplicit(Context, DebugPrintlnFn, { ArgRef }, { }));
 }
diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp
index 252891e..93cfaf6 100644
--- a/lib/Sema/TypeCheckSwitchStmt.cpp
+++ b/lib/Sema/TypeCheckSwitchStmt.cpp
@@ -83,8 +83,8 @@
       explicit Space(Type T)
         : Kind(SpaceKind::Type), TypeAndVal(T, false), Head(Identifier()),
           Spaces({}){}
-      explicit Space(Type T, Identifier H, SmallVectorImpl<Space> &SP)
-        : Kind(SpaceKind::Constructor), TypeAndVal(T, false), Head(H),
+      explicit Space(Type T, Identifier H, bool downgrade, SmallVectorImpl<Space> &SP)
+        : Kind(SpaceKind::Constructor), TypeAndVal(T, downgrade), Head(H),
           Spaces(SP.begin(), SP.end()) {}
       explicit Space(SmallVectorImpl<Space> &SP)
         : Kind(SpaceKind::Disjunct), TypeAndVal(Type(), false),
@@ -101,6 +101,12 @@
       void dump() const LLVM_ATTRIBUTE_USED;
 
       bool isEmpty() const { return getKind() == SpaceKind::Empty; }
+      
+      bool canDowngrade() const {
+        assert(getKind() == SpaceKind::Constructor
+               && "Wrong kind of space tried to access downgrade");
+        return TypeAndVal.getInt();
+      }
 
       Type getType() const {
         assert((getKind() == SpaceKind::Type
@@ -585,7 +591,8 @@
             SmallVector<Space, 4> copyParams(this->getSpaces().begin(),
                                              this->getSpaces().end());
             copyParams[idx] = s1.minus(s2, TC);
-            Space CS(this->getType(), this->Head, copyParams);
+            Space CS(this->getType(), this->getHead(), this->canDowngrade(),
+                     copyParams);
             constrSpaces.push_back(CS);
           }
 
@@ -721,7 +728,7 @@
               return Space();
             }
           }
-          return Space(getType(), Head, simplifiedSpaces);
+          return Space(getType(), Head, canDowngrade(), simplifiedSpaces);
         }
         case SpaceKind::Type: {
           // If the decomposition of a space is empty, the space is empty.
@@ -813,7 +820,10 @@
                 constElemSpaces.push_back(Space(TTy->getUnderlyingType()));
               }
             }
-            return Space(tp, eed->getName(), constElemSpaces);
+            return Space(tp, eed->getName(),
+                         eed->getAttrs()
+                          .getAttribute<DowngradeExhaustivityCheckAttr>(),
+                         constElemSpaces);
           });
         } else if (auto *TTy = tp->castTo<TupleType>()) {
           // Decompose each of the elements into its component type space.
@@ -824,7 +834,8 @@
             return Space(ty.getType());
           });
           // Create an empty constructor head for the tuple space.
-          arr.push_back(Space(tp, Identifier(), constElemSpaces));
+          arr.push_back(Space(tp, Identifier(), /*canDowngrade*/false,
+                              constElemSpaces));
         } else {
           llvm_unreachable("Can't decompose type?");
         }
@@ -851,6 +862,7 @@
         return;
       }
 
+      bool sawDowngradablePattern = false;
       SmallVector<Space, 4> spaces;
       for (unsigned i = 0, e = Switch->getCases().size(); i < e; ++i) {
         auto *caseBlock = Switch->getCases()[i];
@@ -864,7 +876,8 @@
           if (caseItem.isDefault())
             return;
 
-          auto projection = projectPattern(TC, caseItem.getPattern());
+          auto projection = projectPattern(TC, caseItem.getPattern(),
+                                           sawDowngradablePattern);
           if (projection.isUseful()
                 && projection.isSubspace(Space(spaces), TC)) {
             TC.diagnose(caseItem.getStartLoc(),
@@ -874,7 +887,7 @@
           spaces.push_back(projection);
         }
       }
-
+      
       Space totalSpace(Switch->getSubjectExpr()->getType());
       Space coveredSpace(spaces);
       auto uncovered = totalSpace.minus(coveredSpace, TC).simplify(TC);
@@ -904,43 +917,81 @@
         uncovered = Space(spaces);
       }
 
-      diagnoseMissingCases(TC, Switch, /*justNeedsDefault*/ false, uncovered);
+      diagnoseMissingCases(TC, Switch, /*justNeedsDefault*/ false, uncovered,
+                           sawDowngradablePattern);
+    }
+    
+    // HACK: Search the space for any remaining cases that were labelled
+    // @_downgrade_exhaustivity_check.
+    static bool shouldDowngradeToWarning(const Space &masterSpace) {
+      switch (masterSpace.getKind()) {
+        case SpaceKind::Type:
+        case SpaceKind::BooleanConstant:
+        case SpaceKind::Empty:
+          return false;
+        // Traverse the constructor and its subspaces.
+        case SpaceKind::Constructor:
+          return masterSpace.canDowngrade()
+              || std::accumulate(masterSpace.getSpaces().begin(),
+                                 masterSpace.getSpaces().end(),
+                                false,
+                                [](bool acc, const Space &space) {
+            return acc || shouldDowngradeToWarning(space);
+          });
+        case SpaceKind::Disjunct:
+          // Traverse the disjunct's subspaces.
+          return std::accumulate(masterSpace.getSpaces().begin(),
+                                 masterSpace.getSpaces().end(),
+                                 false,
+                                 [](bool acc, const Space &space) {
+                                   return acc || shouldDowngradeToWarning(space);
+                                 });
+      }
     }
 
-    static void diagnoseMissingCases(TypeChecker &TC, const SwitchStmt *Switch,
-                                     bool JustNeedsDefault,
-                                     SpaceEngine::Space uncovered) {
-      bool Empty = Switch->getCases().empty();
-      SourceLoc StartLoc = Switch->getStartLoc();
-      SourceLoc EndLoc = Switch->getEndLoc();
-      StringRef Placeholder = getCodePlaceholder();
-      llvm::SmallString<128> Buffer;
-      llvm::raw_svector_ostream OS(Buffer);
+    static void diagnoseMissingCases(TypeChecker &TC, const SwitchStmt *SS,
+                                     bool justNeedsDefault,
+                                     Space uncovered,
+                                     bool sawDowngradablePattern = false) {
+      SourceLoc startLoc = SS->getStartLoc();
+      SourceLoc endLoc = SS->getEndLoc();
+      StringRef placeholder = getCodePlaceholder();
+      llvm::SmallString<128> buffer;
+      llvm::raw_svector_ostream OS(buffer);
 
       bool InEditor = TC.Context.LangOpts.DiagnosticsEditorMode;
 
-      if (JustNeedsDefault) {
-        OS << tok::kw_default << ":\n" << Placeholder << "\n";
-        if (Empty) {
-          TC.Context.Diags.diagnose(StartLoc, diag::empty_switch_stmt)
-             .fixItInsert(EndLoc, Buffer.str());
+      if (justNeedsDefault) {
+        OS << tok::kw_default << ":\n" << placeholder << "\n";
+        if (SS->getCases().empty()) {
+          TC.Context.Diags.diagnose(startLoc, diag::empty_switch_stmt)
+             .fixItInsert(endLoc, buffer.str());
         } else {
-          TC.Context.Diags.diagnose(StartLoc, diag::non_exhaustive_switch);
-          TC.Context.Diags.diagnose(StartLoc, diag::missing_several_cases,
-                                    uncovered.isEmpty()).fixItInsert(EndLoc,
-                                                              Buffer.str());
+          TC.Context.Diags.diagnose(startLoc, diag::non_exhaustive_switch);
+          TC.Context.Diags.diagnose(startLoc, diag::missing_several_cases,
+                                    uncovered.isEmpty()).fixItInsert(endLoc,
+                                                              buffer.str());
         }
         return;
       }
 
       // If there's nothing else to diagnose, bail.
       if (uncovered.isEmpty()) return;
-
+      
+      auto mainDiagType = diag::non_exhaustive_switch;
+      if (TC.Context.isSwiftVersion3()) {
+        if (!sawDowngradablePattern && shouldDowngradeToWarning(uncovered)) {
+          mainDiagType = diag::non_exhaustive_switch_warn_swift3;
+        }
+      }
+      
       // If editing is enabled, emit a formatted error of the form:
       //
       // switch must be exhaustive, do you want to add missing cases?
-      //     case (.none, .some(_)): <#code#>
-      //     case (.some(_), .none): <#code#>
+      //     case (.none, .some(_)):
+      //       <#code#>
+      //     case (.some(_), .none):
+      //       <#code#>
       //
       // else:
       //
@@ -949,31 +1000,45 @@
       // missing case '(.none, .some(_))'
       // missing case '(.some(_), .none)'
       if (InEditor) {
-        Buffer.clear();
+        buffer.clear();
+        SmallVector<Space, 8> emittedSpaces;
         for (auto &uncoveredSpace : uncovered.getSpaces()) {
           SmallVector<Space, 4> flats;
           flatten(uncoveredSpace, flats);
           for (auto &flat : flats) {
+            if (flat.isSubspace(Space(emittedSpaces), TC)) {
+              continue;
+            }
+            
             OS << tok::kw_case << " ";
             flat.show(OS);
-            OS << ":\n" << Placeholder << "\n";
+            OS << ":\n" << placeholder << "\n";
+            
+            emittedSpaces.push_back(flat);
           }
         }
 
-        TC.Context.Diags.diagnose(StartLoc, diag::non_exhaustive_switch);
-        TC.Context.Diags.diagnose(StartLoc, diag::missing_several_cases, false)
-          .fixItInsert(EndLoc, Buffer.str());
-      } else {
-        TC.Context.Diags.diagnose(StartLoc, diag::non_exhaustive_switch);
+        TC.diagnose(startLoc, diag::non_exhaustive_switch);
+        TC.diagnose(startLoc, diag::missing_several_cases, false)
+          .fixItInsert(endLoc, buffer.str());
 
+      } else {
+        TC.Context.Diags.diagnose(startLoc, mainDiagType);
+
+        SmallVector<Space, 8> emittedSpaces;
         for (auto &uncoveredSpace : uncovered.getSpaces()) {
           SmallVector<Space, 4> flats;
           flatten(uncoveredSpace, flats);
           for (auto &flat : flats) {
-            Buffer.clear();
+            if (flat.isSubspace(Space(emittedSpaces), TC)) {
+              continue;
+            }
+            
+            buffer.clear();
             flat.show(OS);
-            TC.Context.Diags.diagnose(StartLoc, diag::missing_particular_case,
-                               Buffer.str());
+            TC.diagnose(startLoc, diag::missing_particular_case, buffer.str());
+            
+            emittedSpaces.push_back(flat);
           }
         }
       }
@@ -993,7 +1058,7 @@
           flats.push_back(space);
           return;
         }
-
+        
         // To recursively recover a pattern matrix from a bunch of disjuncts:
         // 1) Unpack the arguments to the constructor under scrutiny.
         // 2) Traverse each argument in turn.
@@ -1009,17 +1074,13 @@
           SmallVector<Space, 4> columnVect;
           flatten(subspace, columnVect);
 
-          // Pattern matrices grow quasi-factorially in the size of the
-          // input space.
-          multiplier *= columnVect.size();
-
           size_t startSize = matrix.size();
           if (!matrix.empty() && columnVect.size() > 1) {
             size_t oldCount = matrix.size();
-            matrix.reserve(multiplier * oldCount);
+            matrix.reserve(oldCount * columnVect.size());
             // Indexing starts at 1, we already have 'startSize'-many elements
             // in the matrix; multiplies by 1 are no-ops.
-            for (size_t i = 1; i < multiplier; ++i) {
+            for (size_t i = 1; i < columnVect.size(); ++i) {
               std::copy_n(matrix.begin(), oldCount, std::back_inserter(matrix));
             }
           }
@@ -1054,11 +1115,16 @@
               matrix[rowIdx].push_back(columnVect[colIdx]);
             }
           }
+          
+          // Pattern matrices grow quasi-factorially in the size of the
+          // input space.
+          multiplier *= columnVect.size();
         }
 
         // Wrap the matrix rows into this constructor.
         for (auto &row : matrix) {
-          flats.push_back(Space(space.getType(), space.getHead(), row));
+          flats.push_back(Space(space.getType(), space.getHead(),
+                                space.canDowngrade(), row));
         }
       }
         break;
@@ -1077,7 +1143,8 @@
     }
 
     // Recursively project a pattern into a Space.
-    static Space projectPattern(TypeChecker &TC, const Pattern *item) {
+    static Space projectPattern(TypeChecker &TC, const Pattern *item,
+                                bool &sawDowngradablePattern) {
       switch (item->getKind()) {
       case PatternKind::Any:
       case PatternKind::Named:
@@ -1109,28 +1176,39 @@
         return Space();
       case PatternKind::Var: {
         auto *VP = cast<VarPattern>(item);
-        return projectPattern(TC, VP->getSubPattern());
+        return projectPattern(TC, VP->getSubPattern(), sawDowngradablePattern);
       }
       case PatternKind::Paren: {
         auto *PP = cast<ParenPattern>(item);
-        return projectPattern(TC, PP->getSubPattern());
+        return projectPattern(TC, PP->getSubPattern(), sawDowngradablePattern);
       }
       case PatternKind::OptionalSome: {
         auto *OSP = cast<OptionalSomePattern>(item);
         SmallVector<Space, 1> payload = {
-          projectPattern(TC, OSP->getSubPattern())
+          projectPattern(TC, OSP->getSubPattern(), sawDowngradablePattern)
         };
-        return Space(item->getType(), TC.Context.getIdentifier("some"), payload);
+        return Space(item->getType(), TC.Context.getIdentifier("some"), /*canDowngrade*/false,
+                     payload);
       }
       case PatternKind::EnumElement: {
         auto *VP = cast<EnumElementPattern>(item);
         TC.validateDecl(item->getType()->getEnumOrBoundGenericEnum());
+        
+        bool canDowngrade = false;
+        if (auto *eed = VP->getElementDecl()) {
+          if (eed->getAttrs().getAttribute<DowngradeExhaustivityCheckAttr>()) {
+            canDowngrade |= true;
+            sawDowngradablePattern |= true;
+          }
+        }
+        
         SmallVector<Space, 4> conArgSpace;
         auto *SP = VP->getSubPattern();
         if (!SP) {
           // If there's no sub-pattern then there's no further recursive
           // structure here.  Yield the constructor space.
-          return Space(item->getType(), VP->getName(), conArgSpace);
+          return Space(item->getType(), VP->getName(), canDowngrade,
+                       conArgSpace);
         }
 
         switch (SP->getKind()) {
@@ -1139,9 +1217,11 @@
           std::transform(TP->getElements().begin(), TP->getElements().end(),
                          std::back_inserter(conArgSpace),
                          [&](TuplePatternElt pate) {
-                           return projectPattern(TC, pate.getPattern());
+                           return projectPattern(TC, pate.getPattern(),
+                                                 sawDowngradablePattern);
                          });
-          return Space(item->getType(), VP->getName(), conArgSpace);
+          return Space(item->getType(), VP->getName(), /*canDowngrade*/false,
+                       conArgSpace);
         }
         case PatternKind::Paren: {
           auto *PP = dyn_cast<ParenPattern>(SP);
@@ -1158,15 +1238,21 @@
                 conArgSpace.push_back(Space(ty.getType()));
               }
             } else {
-              conArgSpace.push_back(projectPattern(TC, SP));
+              conArgSpace.push_back(projectPattern(TC, SP,
+                                                   sawDowngradablePattern));
             }
           } else {
-            conArgSpace.push_back(projectPattern(TC, SP));
+            conArgSpace.push_back(projectPattern(TC, SP,
+                                                 sawDowngradablePattern));
           }
-          return Space(item->getType(), VP->getName(), conArgSpace);
+          // FIXME: This isn't *technically* correct, but we only use the
+          // downgradability of the master space, not the projected space,
+          // when reconstructing the missing pattern matrix.
+          return Space(item->getType(), VP->getName(), /*canDowngrade*/false,
+                       conArgSpace);
         }
         default:
-          return projectPattern(TC, SP);
+          return projectPattern(TC, SP, sawDowngradablePattern);
         }
       }
       case PatternKind::Tuple: {
@@ -1175,9 +1261,10 @@
         std::transform(TP->getElements().begin(), TP->getElements().end(),
                        std::back_inserter(conArgSpace),
                        [&](TuplePatternElt pate) {
-          return projectPattern(TC, pate.getPattern());
+          return projectPattern(TC, pate.getPattern(), sawDowngradablePattern);
         });
-        return Space(item->getType(), Identifier(), conArgSpace);
+        return Space(item->getType(), Identifier(), /*canDowngrade*/false,
+                     conArgSpace);
       }
       }
     }
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 79b3881..3e80f5d 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -224,6 +224,9 @@
   /// Set if the client prefers fixits to be in the form of force unwrapping
   /// or optional chaining to return an optional.
   PreferForceUnwrapToOptional = 0x80,
+
+  /// If set, don't apply a solution.
+  SkipApplyingSolution = 0x100,
 };
 
 typedef OptionSet<TypeCheckExprFlags> TypeCheckExprOptions;
@@ -325,6 +328,13 @@
   /// constraint system, or false otherwise.
   virtual bool builtConstraints(constraints::ConstraintSystem &cs, Expr *expr);
 
+  /// Callback invoked once a solution has been found.
+  ///
+  /// The callback may further alter the expression, returning either a
+  /// new expression (to replace the result) or a null pointer to indicate
+  /// failure.
+  virtual Expr *foundSolution(constraints::Solution &solution, Expr *expr);
+
   /// Callback invokes once the chosen solution has been applied to the
   /// expression.
   ///
@@ -987,7 +997,7 @@
   ///
   /// \param typeDecl The type declaration found by name lookup.
   /// \param fromDC The declaration context in which the name lookup occurred.
-  /// \param isSpecialized Whether this type is immediately specialized.
+  /// \param isSpecialized Whether the type will have generic arguments applied.
   /// \param resolver The resolver for generic types.
   ///
   /// \returns the resolved type.
@@ -1219,9 +1229,6 @@
     handleExternalDecl(nominal);
   }
 
-  /// Introduce the accessors for a 'lazy' variable.
-  void introduceLazyVarAccessors(VarDecl *var) override;
-
   /// Infer default value witnesses for all requirements in the given protocol.
   void inferDefaultWitnesses(ProtocolDecl *proto);
 
@@ -1667,9 +1674,9 @@
   
   /// Type-check an initialized variable pattern declaration.
   bool typeCheckBinding(Pattern *&P, Expr *&Init, DeclContext *DC,
-                        bool skipClosures);
+                        bool skipApplyingSolution);
   bool typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned patternNumber,
-                               bool skipClosures);
+                               bool skipApplyingSolution);
 
   /// Type-check a for-each loop's pattern binding and sequence together.
   bool typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt);
@@ -1689,8 +1696,7 @@
   static void contextualizeTopLevelCode(TopLevelContext &TLC,
                                         ArrayRef<Decl*> topLevelDecls);
 
-  /// Return the type-of-reference of the given value.  This does not
-  /// open values of polymorphic function type.
+  /// Return the type-of-reference of the given value.
   ///
   /// \param baseType if non-null, return the type of a member reference to
   ///   this value when the base has the given type
@@ -1701,14 +1707,11 @@
   /// \param base The optional base expression of this value reference
   ///
   /// \param wantInterfaceType Whether we want the interface type, if available.
-  Type getUnopenedTypeOfReference(ValueDecl *value, Type baseType,
+  Type getUnopenedTypeOfReference(VarDecl *value, Type baseType,
                                   DeclContext *UseDC,
                                   const DeclRefExpr *base = nullptr,
                                   bool wantInterfaceType = false);
 
-  /// Return the non-lvalue type-of-reference of the given value.
-  Type getTypeOfRValue(ValueDecl *value, bool wantInterfaceType = false);
-
   /// \brief Retrieve the default type for the given protocol.
   ///
   /// Some protocols, particularly those that correspond to literals, have
@@ -2044,7 +2047,6 @@
   /// the given set of declarations.
   Expr *buildRefExpr(ArrayRef<ValueDecl *> Decls, DeclContext *UseDC,
                      DeclNameLoc NameLoc, bool Implicit,
-                     bool isSpecialized,
                      FunctionRefKind functionRefKind);
   /// @}
 
diff --git a/stdlib/public/SDK/Foundation/NSStringAPI.swift b/stdlib/public/SDK/Foundation/NSStringAPI.swift
index 6464b71..585b6e2 100644
--- a/stdlib/public/SDK/Foundation/NSStringAPI.swift
+++ b/stdlib/public/SDK/Foundation/NSStringAPI.swift
@@ -1778,7 +1778,7 @@
     fatalError("unavailable function can't be called")
   }
 
-  @available(*, unavailable, renamed: "componentsSeparated(by:)")
+  @available(*, unavailable, renamed: "components(separatedBy:)")
   public func componentsSeparatedBy(_ separator: String) -> [String] {
     fatalError("unavailable function can't be called")
   }
diff --git a/stdlib/public/SwiftShims/LibcShims.h b/stdlib/public/SwiftShims/LibcShims.h
index 636c587..e631905 100644
--- a/stdlib/public/SwiftShims/LibcShims.h
+++ b/stdlib/public/SwiftShims/LibcShims.h
@@ -33,7 +33,7 @@
 
 // This declaration is not universally correct.  We verify its correctness for
 // the current platform in the runtime code.
-#if defined(__linux__) && defined (__arm__) && !defined(__android__)
+#if defined(__linux__) && defined (__arm__) && !defined(__ANDROID__)
 typedef           int __swift_ssize_t;
 #elif defined(_WIN32)
 #if defined(_M_ARM) || defined(_M_IX86)
@@ -113,7 +113,9 @@
 
 // TLS - thread local storage
 
-#if defined(__linux__)
+#if defined(__ANDROID__)
+typedef int __swift_pthread_key_t;
+#elif defined(__linux__)
 typedef unsigned int __swift_pthread_key_t;
 #else
 typedef unsigned long __swift_pthread_key_t;
diff --git a/stdlib/public/SwiftShims/NSCharacterSetShims.h b/stdlib/public/SwiftShims/NSCharacterSetShims.h
index d7735d7..f38fbcc 100644
--- a/stdlib/public/SwiftShims/NSCharacterSetShims.h
+++ b/stdlib/public/SwiftShims/NSCharacterSetShims.h
@@ -15,27 +15,27 @@
 NS_BEGIN_DECLS
 
 NS_INLINE NS_RETURNS_RETAINED NS_NON_BRIDGED(NSCharacterSet *) _NSURLComponentsGetURLUserAllowedCharacterSet(void) {
-	return NSCharacterSet.URLUserAllowedCharacterSet;
+    return NSCharacterSet.URLUserAllowedCharacterSet;
 }
 
 NS_INLINE NS_RETURNS_RETAINED NS_NON_BRIDGED(NSCharacterSet *) _NSURLComponentsGetURLPasswordAllowedCharacterSet(void) {
-	return NSCharacterSet.URLPasswordAllowedCharacterSet;
+    return NSCharacterSet.URLPasswordAllowedCharacterSet;
 }
 
 NS_INLINE NS_RETURNS_RETAINED NS_NON_BRIDGED(NSCharacterSet *) _NSURLComponentsGetURLHostAllowedCharacterSet(void) {
-	return NSCharacterSet.URLHostAllowedCharacterSet;
+    return NSCharacterSet.URLHostAllowedCharacterSet;
 }
 
 NS_INLINE NS_RETURNS_RETAINED NS_NON_BRIDGED(NSCharacterSet *) _NSURLComponentsGetURLPathAllowedCharacterSet(void) {
-	return NSCharacterSet.URLPathAllowedCharacterSet;
+    return NSCharacterSet.URLPathAllowedCharacterSet;
 }
 
 NS_INLINE NS_RETURNS_RETAINED NS_NON_BRIDGED(NSCharacterSet *) _NSURLComponentsGetURLQueryAllowedCharacterSet(void) {
-	return NSCharacterSet.URLQueryAllowedCharacterSet;
+    return NSCharacterSet.URLQueryAllowedCharacterSet;
 }
 
 NS_INLINE NS_RETURNS_RETAINED NS_NON_BRIDGED(NSCharacterSet *) _NSURLComponentsGetURLFragmentAllowedCharacterSet(void) {
-	return NSCharacterSet.URLFragmentAllowedCharacterSet;
+    return NSCharacterSet.URLFragmentAllowedCharacterSet;
 }
 
 NS_END_DECLS
diff --git a/stdlib/public/core/Sequence.swift b/stdlib/public/core/Sequence.swift
index da84ba0..aa2de70 100644
--- a/stdlib/public/core/Sequence.swift
+++ b/stdlib/public/core/Sequence.swift
@@ -693,7 +693,7 @@
 /// A sequence that only consumes up to `n` elements from an underlying
 /// `Base` iterator.
 ///
-/// The underlying iterator's sequence may be infinite
+/// The underlying iterator's sequence may be infinite.
 @_fixed_layout
 @_versioned
 internal struct _PrefixSequence<Base : IteratorProtocol>
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index d8d37d7..9052997 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -693,27 +693,18 @@
   /// 
   /// - Parameter newElements: A sequence of characters.
   public mutating func append<S : Sequence>(contentsOf newElements: S)
-    where S.Element == Character {
-    reserveCapacity(_core.count + newElements.underestimatedCount)
-    for c in newElements {
-      self.append(c)
-    }
-  }
-
-  /// Creates a new character view containing the characters in the given
-  /// sequence.
-  ///
-  /// - Parameter characters: A sequence of characters.
-  public init<S : Sequence>(_ characters: S)
   where S.Element == Character {
-    let v0 = characters as? _SwiftStringView
-    if _fastPath(v0 != nil), let v = v0 {
-      self = v._persistentContent.characters
+    if _fastPath(newElements is _SwiftStringView) {
+      let v = newElements as! _SwiftStringView
+      if _fastPath(_core.count == 0) {
+        _core = v._persistentContent._core
+        return
+      }
+      _core.append(v._ephemeralContent._core)
+      return
     }
-    else {
-      self = String.CharacterView()
-      self.append(contentsOf: characters)
-    }
+    reserveCapacity(_core.count + newElements.underestimatedCount)
+    for c in newElements { self.append(c) }
   }
 }
 
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
index 10126fc..f489634 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
@@ -36,16 +36,17 @@
     self.init(repeating: String(repeatedValue), count: count)
   }
 
-  // FIXME(strings): doc comment
   // This initializer disambiguates between the following intitializers, now
   // that String conforms to Collection:
   // - init<T>(_ value: T) where T : LosslessStringConvertible
   // - init<S>(_ characters: S) where S : Sequence, S.Element == Character
-  public init<T : StringProtocol>(_ other: T) {
-    self.init(other.characters)
+  public init<S : Sequence & LosslessStringConvertible>(_ other: S)
+  where S.Element == Character {
+    self._core = CharacterView(other)._core
   }
-
+  
   // This initializer satisfies the LosslessStringConvertible conformance
+  @available(swift, obsoleted: 4, message: "String.init(_:String) is no longer failable")
   public init?(_ other: String) {
     self.init(other._core)
   }
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index ea02eb4..c0ccbe5 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -88,6 +88,10 @@
     _slice = RangeReplaceableBidirectionalSlice()
   }
 
+  internal init(_slice: RangeReplaceableBidirectionalSlice<String>) {
+    self._slice = _slice
+  }
+  
   /// Creates a substring with the specified bounds within the given string.
   ///
   /// - Parameters:
@@ -455,53 +459,21 @@
   }
 }
 
-// The purpose of this protocol is backward compatibility with Swift 3 code,
-// where String subscripts returned String.
-// Since the Substring returning subscripts are introduced by the protocol
-// extension, they will be less specific than the String-returning ones
-// declared on the String type itself, thus avoiding ambiguity.
-public protocol _RangeSubscriptableString {
-  associatedtype Index : Comparable
-  func _subscript(_ bounds: Range<Index>) -> Substring
-  func _subscript(_ bounds: ClosedRange<Index>) -> Substring
-}
-
-// Without the `where` subscripts will be ambiguous
-extension _RangeSubscriptableString where Self : RangeReplaceableCollection {
-% for Range in ['Range', 'ClosedRange']:
-  public subscript(bounds: ${Range}<Index>) -> Substring {
-    return _subscript(bounds)
-  }
-% end
-}
-
-extension String : _RangeSubscriptableString {
-% for Range in ['Range', 'ClosedRange']:
-  /// Accesses the text in the given range.
-  ///
-  /// - Complexity: O(*n*) if the underlying string is bridged from
-  ///   Objective-C, where *n* is the length of the string; otherwise, O(1).
-  public func _subscript(_ bounds: ${Range}<Index>) -> Substring {
-    return Substring(_base: String(self._core), bounds)
-  }
-% end
-}
-
-extension Substring : _RangeSubscriptableString {
-% for Range in ['Range', 'ClosedRange']:
-  public func _subscript(_ bounds: ${Range}<Index>) -> Substring {
-    let subSlice = _slice[bounds]
-    let bounds = (lower: subSlice.startIndex, upper: subSlice.endIndex)
-%   if Range == 'ClosedRange':
-    // Creating Substring using the half-open range, since subSlice already
-    // handled the ClosedRange case.
-%   end
-    return Substring(_base: _slice._base, Range(uncheckedBounds: bounds))
-  }
-% end
-}
-
+//===--- String/Substring Slicing Support ---------------------------------===//
+/// In Swift 3.2, in the absence of type context,
+///
+///     someString[someString.startIndex..<someString.endIndex]
+///
+/// was deduced to be of type `String`.  Therefore have a more-specific
+/// Swift-3-only `subscript` overload on `String` (and `Substring`) that
+/// continues to produce `String`.
 extension String {
+  @available(swift, introduced: 4)
+  public subscript(r: Range<Index>) -> Substring {
+    return Substring(
+      _slice: RangeReplaceableBidirectionalSlice(base: self, bounds: r))
+  }
+
   @available(swift, obsoleted: 4)
   public subscript(bounds: Range<Index>) -> String {
     return String(characters[bounds])
@@ -514,6 +486,11 @@
 }
 
 extension Substring {
+  @available(swift, introduced: 4)
+  public subscript(r: Range<Index>) -> Substring {
+    return Substring(_slice: _slice[r])
+  }
+
   @available(swift, obsoleted: 4)
   public subscript(bounds: Range<Index>) -> String {
     return String(characters[bounds])
@@ -524,3 +501,4 @@
     return String(characters[bounds])
   }
 }
+//===----------------------------------------------------------------------===//
diff --git a/stdlib/public/core/ThreadLocalStorage.swift b/stdlib/public/core/ThreadLocalStorage.swift
index 32278da..cb213d5 100644
--- a/stdlib/public/core/ThreadLocalStorage.swift
+++ b/stdlib/public/core/ThreadLocalStorage.swift
@@ -1,3 +1,15 @@
+//===--- ThreadLocalStorage.swift -----------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
 import SwiftShims
 
 // For testing purposes, a thread-safe counter to guarantee that destructors get
diff --git a/test/Constraints/array_literal.swift b/test/Constraints/array_literal.swift
index 4761468..91c624b 100644
--- a/test/Constraints/array_literal.swift
+++ b/test/Constraints/array_literal.swift
@@ -129,7 +129,7 @@
 
   let a2: Array = [1, "a", 3.5]
   // expected-error@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}}
-  let _: Int = a2  // expected-error{{value of type '[Any]'}}
+  let _: Int = a2  // expected-error{{value of type 'Array<Any>'}}
   
   let a3 = [1, "a", nil, 3.5]
   // expected-error@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}}
@@ -137,7 +137,7 @@
   
   let a4: Array = [1, "a", nil, 3.5]
   // expected-error@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}}
-  let _: Int = a4 // expected-error{{value of type '[Any?]'}}
+  let _: Int = a4 // expected-error{{value of type 'Array<Any?>'}}
 
   let a5 = []
   // expected-error@-1{{empty collection literal requires an explicit type}}
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index ce5d0fd..600ac53 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -258,4 +258,5 @@
 _T0Tk ---> _T0Tk
 _T0A8 ---> _T0A8
 _T0s30ReversedRandomAccessCollectionVyxGTfq3nnpf_nTfq1cn_nTfq4x_n ---> _T0s30ReversedRandomAccessCollectionVyxGTfq3nnpf_nTfq1cn_nTfq4x_n
+_T03abc6testitySiFTm ---> merged abc.testit(Swift.Int) -> ()
 
diff --git a/test/Demangle/Inputs/simplified-manglings.txt b/test/Demangle/Inputs/simplified-manglings.txt
index e537834..98399f6 100644
--- a/test/Demangle/Inputs/simplified-manglings.txt
+++ b/test/Demangle/Inputs/simplified-manglings.txt
@@ -203,3 +203,5 @@
 _TTRXFo_oCSo13SKPhysicsBodydVSC7CGPointdVSC8CGVectordGSpV10ObjectiveC8ObjCBool___XFdCb_dS_dS0_dS1_dGSpS3____ ---> thunk for @callee_owned (@owned SKPhysicsBody, @unowned CGPoint, @unowned CGVector, @unowned UnsafeMutablePointer<ObjCBool>) -> ()
 _T0So13SKPhysicsBodyCSC7CGPointVSC8CGVectorVSpy10ObjectiveC8ObjCBoolVGIxxyyy_AbdFSpyAIGIyByyyy_TR ---> thunk for @callee_owned (@owned SKPhysicsBody, @unowned CGPoint, @unowned CGVector, @unowned UnsafeMutablePointer<ObjCBool>) -> ()
 _T04main1_yyF ---> _()
+_T03abc6testitySiFTm ---> testit(_:)
+
diff --git a/test/IDE/print_types.swift b/test/IDE/print_types.swift
index dba1c03..9b61ea5 100644
--- a/test/IDE/print_types.swift
+++ b/test/IDE/print_types.swift
@@ -57,14 +57,14 @@
   _ = typealias1 ; typealias1 = 1
 
   var optional1 = Optional<Int>.none
-// CHECK: VarDecl '''optional1''' Optional<Int>{{$}}
-// FULL:  VarDecl '''optional1''' Swift.Optional<Swift.Int>{{$}}
+// CHECK: VarDecl '''optional1''' Int?{{$}}
+// FULL:  VarDecl '''optional1''' Swift.Int?{{$}}
   _ = optional1 ; optional1 = nil
 
   var optional2 = Optional<[Int]>.none
   _ = optional2 ; optional2 = nil
-// CHECK: VarDecl '''optional2''' Optional<[Int]>{{$}}
-// FULL:  VarDecl '''optional2''' Swift.Optional<[Swift.Int]>{{$}}
+// CHECK: VarDecl '''optional2''' [Int]?{{$}}
+// FULL:  VarDecl '''optional2''' [Swift.Int]?{{$}}
 }
 
 func testFuncType1() {}
diff --git a/test/Interpreter/repl.swift b/test/Interpreter/repl.swift
index 6f82de3..77654f0 100644
--- a/test/Interpreter/repl.swift
+++ b/test/Interpreter/repl.swift
@@ -148,7 +148,7 @@
 // CHECK-NEXT: r
 
 var vec = Array<String>()
-// CHECK: vec : Array<String> = []
+// CHECK: vec : [String] = []
 
 // Error recovery
 var a : [int]
diff --git a/test/LLVMPasses/merge_func.ll b/test/LLVMPasses/merge_func.ll
index 64f4485..7a9be33 100644
--- a/test/LLVMPasses/merge_func.ll
+++ b/test/LLVMPasses/merge_func.ll
@@ -9,7 +9,7 @@
 ; Test the most trivial example.
 
 ; CHECK-LABEL: define i32 @simple_func1(i32 %x, i32 %y)
-; CHECK: %1 = tail call i32 @simple_func1_merged(i32 %x, i32 %y, i32* @g1)
+; CHECK: %1 = tail call i32 @simple_func1Tm(i32 %x, i32 %y, i32* @g1)
 ; CHECK: ret i32 %1
 define i32 @simple_func1(i32 %x, i32 %y) {
   %sum = add i32 %x, %y
@@ -20,7 +20,7 @@
 }
 
 ; CHECK-LABEL: define i32 @simple_func2(i32 %x, i32 %y)
-; CHECK: %1 = tail call i32 @simple_func1_merged(i32 %x, i32 %y, i32* @g2)
+; CHECK: %1 = tail call i32 @simple_func1Tm(i32 %x, i32 %y, i32* @g2)
 ; CHECK: ret i32 %1
 define i32 @simple_func2(i32 %x, i32 %y) {
   %sum = add i32 %x, %y
@@ -30,7 +30,7 @@
   ret i32 %sum3
 }
 
-; CHECK-LABEL: define internal i32 @simple_func1_merged(i32, i32, i32*)
+; CHECK-LABEL: define internal i32 @simple_func1Tm(i32, i32, i32*)
 ; CHECK: %l = load i32, i32* %2
 ; CHECK: ret
 
@@ -38,7 +38,7 @@
 ; Merge 3 functions with 3 types of differing instructions: load, store and call.
 
 ; CHECK-LABEL: define i32 @func1_of_3(i32 %x)
-; CHECK: %1 = tail call i32 @func1_of_3_merged(i32 %x, i32* @g1, i32* @g1, void (i32)* @callee1)
+; CHECK: %1 = tail call i32 @func1_of_3Tm(i32 %x, i32* @g1, i32* @g1, void (i32)* @callee1)
 ; CHECK: ret i32 %1
 define i32 @func1_of_3(i32 %x) {
   %l1 = load i32, i32* @g1, align 4
@@ -52,7 +52,7 @@
 }
 
 ; CHECK-LABEL: define i32 @func2_of_3(i32 %x)
-; CHECK: %1 = tail call i32 @func1_of_3_merged(i32 %x, i32* @g2, i32* @g2, void (i32)* @callee2)
+; CHECK: %1 = tail call i32 @func1_of_3Tm(i32 %x, i32* @g2, i32* @g2, void (i32)* @callee2)
 ; CHECK: ret i32 %1
 define i32 @func2_of_3(i32 %x) {
   %l1 = load i32, i32* @g2, align 4
@@ -66,7 +66,7 @@
 }
 
 ; CHECK-LABEL: define i32 @func3_of_3(i32 %x)
-; CHECK: %1 = tail call i32 @func1_of_3_merged(i32 %x, i32* @g3, i32* @g1, void (i32)* @callee3)
+; CHECK: %1 = tail call i32 @func1_of_3Tm(i32 %x, i32* @g3, i32* @g1, void (i32)* @callee3)
 ; CHECK: ret i32 %1
 define i32 @func3_of_3(i32 %x) {
   %l1 = load i32, i32* @g3, align 4
@@ -79,7 +79,7 @@
   ret i32 %sum3
 }
 
-; CHECK-LABEL: define internal i32 @func1_of_3_merged(i32, i32*, i32*, void (i32)*)
+; CHECK-LABEL: define internal i32 @func1_of_3Tm(i32, i32*, i32*, void (i32)*)
 ; CHECK: %l1 = load i32, i32* %1
 ; CHECK: %l2 = load i32, i32* %2
 ; CHECK: store i32 %sum2, i32* %1
@@ -93,7 +93,7 @@
 ; Preserve attributes
 
 ; CHECK-LABEL: define void @sret_func1(i32* sret %p, i32 %x, i32 %y)
-; CHECK: tail call void @sret_func1_merged(i32* sret %p, i32 %x, i32 %y, i32* @g1)
+; CHECK: tail call void @sret_func1Tm(i32* sret %p, i32 %x, i32 %y, i32* @g1)
 ; CHECK: ret void
 define void @sret_func1(i32* sret %p, i32 %x, i32 %y) {
   %sum = add i32 %x, %y
@@ -104,7 +104,7 @@
 }
 
 ; CHECK-LABEL: define void @sret_func2(i32* sret %p, i32 %x, i32 %y)
-; CHECK: tail call void @sret_func1_merged(i32* sret %p, i32 %x, i32 %y, i32* @g2)
+; CHECK: tail call void @sret_func1Tm(i32* sret %p, i32 %x, i32 %y, i32* @g2)
 ; CHECK: ret void
 define void @sret_func2(i32* sret %p, i32 %x, i32 %y) {
   %sum = add i32 %x, %y
@@ -114,7 +114,7 @@
   ret void
 }
 
-; CHECK-LABEL: define internal void @sret_func1_merged(i32* sret, i32, i32, i32*)
+; CHECK-LABEL: define internal void @sret_func1Tm(i32* sret, i32, i32, i32*)
 ; CHECK: %l = load i32, i32* %3, align 4
 ; CHECK: store i32 %sum2, i32* %0
 ; CHECK: ret
@@ -124,7 +124,7 @@
 ; Instead merge those functions which match best.
 
 ; CHECK-LABEL: define i32 @func1_merged_with3(i32 %x)
-; CHECK: %1 = tail call i32 @func1_merged_with3_merged(i32 %x, i32* @g1)
+; CHECK: %1 = tail call i32 @func1_merged_with3Tm(i32 %x, i32* @g1)
 ; CHECK: ret i32 %1
 define i32 @func1_merged_with3(i32 %x) {
   %l1 = load i32, i32* @g1, align 4
@@ -141,7 +141,7 @@
 }
 
 ; CHECK-LABEL: define i32 @func2_merged_with4(i32 %x)
-; CHECK: %1 = tail call i32 @func2_merged_with4_merged(i32 %x, i32* @g2)
+; CHECK: %1 = tail call i32 @func2_merged_with4Tm(i32 %x, i32* @g2)
 ; CHECK: ret i32 %1
 define i32 @func2_merged_with4(i32 %x) {
   %l1 = load i32, i32* @g2, align 4
@@ -158,7 +158,7 @@
 }
 
 ; CHECK-LABEL: define i32 @func3_merged_with1(i32 %x)
-; CHECK: %1 = tail call i32 @func1_merged_with3_merged(i32 %x, i32* @g2)
+; CHECK: %1 = tail call i32 @func1_merged_with3Tm(i32 %x, i32* @g2)
 ; CHECK: ret i32 %1
 define i32 @func3_merged_with1(i32 %x) {
   %l1 = load i32, i32* @g2, align 4
@@ -174,7 +174,7 @@
   ret i32 %sum5
 }
 
-; CHECK-LABEL: define internal i32 @func1_merged_with3_merged(i32, i32*)
+; CHECK-LABEL: define internal i32 @func1_merged_with3Tm(i32, i32*)
 ; CHECK: load i32, i32* %1, align 4
 ; CHECK: load i32, i32* @g2, align 4
 ; CHECK: load i32, i32* @g3, align 4
@@ -183,7 +183,7 @@
 ; CHECK: ret i32
 
 ; CHECK-LABEL: define i32 @func4_merged_with2(i32 %x) {
-; CHECK: %1 = tail call i32 @func2_merged_with4_merged(i32 %x, i32* @g1)
+; CHECK: %1 = tail call i32 @func2_merged_with4Tm(i32 %x, i32* @g1)
 ; CHECK: ret i32 %1
 define i32 @func4_merged_with2(i32 %x) {
   %l1 = load i32, i32* @g1, align 4
@@ -205,7 +205,7 @@
 ; Also check that the calling convention is preserved.
 
 ; CHECK-LABEL: define fastcc i32 @callee1_a(i32 %x, i32 %y)
-; CHECK: %1 = tail call fastcc i32 @callee1_a_merged(i32 %x, i32 %y, i32* @g1)
+; CHECK: %1 = tail call fastcc i32 @callee1_aTm(i32 %x, i32 %y, i32* @g1)
 ; CHECK: ret i32 %1
 define fastcc i32 @callee1_a(i32 %x, i32 %y) {
   %sum = add i32 %x, %y
@@ -216,7 +216,7 @@
 }
 
 ; CHECK-LABEL: define fastcc i32 @callee1_b(i32 %x, i32 %y)
-; CHECK: %1 = tail call fastcc i32 @callee1_a_merged(i32 %x, i32 %y, i32* @g2)
+; CHECK: %1 = tail call fastcc i32 @callee1_aTm(i32 %x, i32 %y, i32* @g2)
 ; CHECK: ret i32 %1
 define fastcc i32 @callee1_b(i32 %x, i32 %y) {
   %sum = add i32 %x, %y
@@ -226,8 +226,8 @@
   ret i32 %sum3
 }
 
-; CHECK-LABEL: define internal fastcc i32 @callee1_a_merged(i32, i32, i32*)
-; CHECK: call i32 @callee2_a_merged(i32 %sum2, i32 %1, i32* %2)
+; CHECK-LABEL: define internal fastcc i32 @callee1_aTm(i32, i32, i32*)
+; CHECK: call i32 @callee2_aTm(i32 %sum2, i32 %1, i32* %2)
 ; CHECK: ret
 
 ; CHECK-NOT: @callee2_a(
@@ -249,7 +249,7 @@
 }
 
 ; CHECK-LABEL: define i32 @caller_a(i32 %x, i32 %y)
-; CHECK: %1 = tail call i32 @caller_a_merged(i32 %x, i32 %y, i32* @g1)
+; CHECK: %1 = tail call i32 @caller_aTm(i32 %x, i32 %y, i32* @g1)
 ; CHECK: ret i32 %1
 define i32 @caller_a(i32 %x, i32 %y) {
   %sum = add i32 %x, %y
@@ -260,7 +260,7 @@
 }
 
 ; CHECK-LABEL: define i32 @caller_b(i32 %x, i32 %y)
-; CHECK: %1 = tail call i32 @caller_a_merged(i32 %x, i32 %y, i32* @g2)
+; CHECK: %1 = tail call i32 @caller_aTm(i32 %x, i32 %y, i32* @g2)
 ; CHECK: ret i32 %1
 define i32 @caller_b(i32 %x, i32 %y) {
   %sum = add i32 %x, %y
@@ -270,8 +270,8 @@
   ret i32 %sum3
 }
 
-; CHECK-LABEL: define internal i32 @caller_a_merged(i32, i32, i32*)
-; CHECK: call fastcc i32 @callee1_a_merged(i32 %sum2, i32 %1, i32* %2)
+; CHECK-LABEL: define internal i32 @caller_aTm(i32, i32, i32*)
+; CHECK: call fastcc i32 @callee1_aTm(i32 %sum2, i32 %1, i32* %2)
 ; CHECK: ret
 
 
@@ -327,7 +327,7 @@
 ; Check self recursive functions
 
 ; CHECK-LABEL: define internal void @recursive1(i32 %x, i32 %y)
-; CHECK: tail call void @recursive1_merged(i32 %x, i32 %y, i32* @g1, void (i32, i32)* @recursive1)
+; CHECK: tail call void @recursive1Tm(i32 %x, i32 %y, i32* @g1, void (i32, i32)* @recursive1)
 ; CHECK: ret void
 define internal void @recursive1(i32 %x, i32 %y) {
   br i1 undef, label %bb1, label %bb2
@@ -342,7 +342,7 @@
 }
 
 ; CHECK-LABEL: define internal void @recursive2(i32 %x, i32 %y)
-; CHECK: tail call void @recursive1_merged(i32 %x, i32 %y, i32* @g2, void (i32, i32)* @recursive2)
+; CHECK: tail call void @recursive1Tm(i32 %x, i32 %y, i32* @g2, void (i32, i32)* @recursive2)
 ; CHECK: ret void
 define internal void @recursive2(i32 %x, i32 %y) {
   br i1 undef, label %bb1, label %bb2
@@ -355,14 +355,14 @@
 bb2:
   ret void
 }
-; CHECK-LABEL: define internal void @recursive1_merged(i32, i32, i32*, void (i32, i32)*)
+; CHECK-LABEL: define internal void @recursive1Tm(i32, i32, i32*, void (i32, i32)*)
 ; CHECK: load i32, i32* %2
 ; CHECK: call void %3(i32 %0, i32 %1)
 ; CHECK: ret void
 
 
 ; CHECK-LABEL: define internal void @another_recursive_func(i32 %x)
-; CHECK: tail call void @another_recursive_func_merged(i32 %x, i32* @g1, void (i32)* @another_recursive_func)
+; CHECK: tail call void @another_recursive_funcTm(i32 %x, i32* @g1, void (i32)* @another_recursive_func)
 ; CHECK: ret void
 define internal void @another_recursive_func(i32 %x) {
   br i1 undef, label %bb1, label %bb2
@@ -377,7 +377,7 @@
 }
 ; CHECK-NOT: @not_really_recursive(
 
-; CHECK-LABEL: define internal void @another_recursive_func_merged(i32, i32*, void (i32)*)
+; CHECK-LABEL: define internal void @another_recursive_funcTm(i32, i32*, void (i32)*)
 ; CHECK: store i32 %0, i32* %1
 ; CHECK: call void %2(i32 %0)
 ; CHECK: ret void
@@ -398,7 +398,7 @@
 ; CHECK: call void @recursive1(i32 %x, i32 %x)
 ; CHECK: call void @recursive2(i32 %x, i32 %x)
 ; CHECK: call void @another_recursive_func(i32 %x)
-; CHECK: call void @another_recursive_func_merged(i32 %x, i32* @g2, void (i32)* @callee1)
+; CHECK: call void @another_recursive_funcTm(i32 %x, i32* @g2, void (i32)* @callee1)
 ; CHECK: ret void
 define void @call_recursive_funcs(i32 %x) {
   call void @recursive1(i32 %x, i32 %x)
diff --git a/test/LLVMPasses/merge_func_coff.ll b/test/LLVMPasses/merge_func_coff.ll
index df8f60d..67c12f5 100644
--- a/test/LLVMPasses/merge_func_coff.ll
+++ b/test/LLVMPasses/merge_func_coff.ll
@@ -18,6 +18,6 @@
   ret i32 %sum3
 }
 
-; CHECK-NOT: define internal dllexport i32 @f_merged(i32, i32)
-; CHECK-LABEL: define internal i32 @f_merged(i32, i32)
+; CHECK-NOT: define internal dllexport i32 @fTm(i32, i32)
+; CHECK-LABEL: define internal i32 @fTm(i32, i32)
 
diff --git a/test/Migrator/no_var_to_let.swift b/test/Migrator/no_var_to_let.swift
new file mode 100644
index 0000000..796702f
--- /dev/null
+++ b/test/Migrator/no_var_to_let.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend -typecheck %s -swift-version 3
+// RUN: rm -rf %t && mkdir -p %t && %target-swift-frontend -c -update-code -primary-file %s -emit-migrated-file-path %t/no_var_to_let.swift.result -swift-version 3 -o /dev/null
+// RUN: diff -u %s %t/no_var_to_let.swift.result
+// RUN: %target-swift-frontend -typecheck %s -swift-version 4
+
+// Note that the diff run line indicates that there should be no change.
+
+// The compiler should not suggest `let` instead of `var` here because
+// it is a compile error to say `for let ...`.
+// rdar://problem/32390726
+
+for var i in 0..<10 {
+  _ = i + 1
+}
diff --git a/test/NameBinding/name_lookup.swift b/test/NameBinding/name_lookup.swift
index 416ca70..b8b0aef 100644
--- a/test/NameBinding/name_lookup.swift
+++ b/test/NameBinding/name_lookup.swift
@@ -528,7 +528,7 @@
 // <rdar://problem/16954496> lazy properties must use "self." in their body, and can weirdly refer to class variables directly
 class r16954496 {
   func bar() {}
-  lazy var x: Array<(r16954496) -> () -> Void> = [bar]
+  lazy var x: Array<() -> Void> = [bar]
 }
 
 
diff --git a/test/NameBinding/scope_map.swift b/test/NameBinding/scope_map.swift
index 4067a15..ba3fc5c 100644
--- a/test/NameBinding/scope_map.swift
+++ b/test/NameBinding/scope_map.swift
@@ -460,8 +460,7 @@
 // CHECK-SEARCHES-NEXT:     ClassDecl name=LazyProperties
 // CHECK-SEARCHES-NEXT:       Initializer PatternBinding {{.*}} #0
 
-// FIXME: Re-enable the binding below
-// CHECK-SEARCHES-NOT: Local bindings: self
+// CHECK-SEARCHES-NEXT: Local bindings: self
 
 // CHECK-SEARCHES-LABEL: ***Complete scope map***
 // CHECK-SEARCHES-NEXT: SourceFile {{.*}} '{{.*}}scope_map.swift' [1:1 - [[EOF:[0-9]+:[0-9]+]]] unexpanded
diff --git a/test/SILGen/downgrade_exhaustivity_swift3.swift b/test/SILGen/downgrade_exhaustivity_swift3.swift
new file mode 100644
index 0000000..f0be6c1
--- /dev/null
+++ b/test/SILGen/downgrade_exhaustivity_swift3.swift
@@ -0,0 +1,48 @@
+// RUN: %target-swift-frontend -swift-version 3 -emit-silgen %s | %FileCheck %s
+
+enum Downgradable {
+  case spoon
+  case hat
+  @_downgrade_exhaustivity_check
+  case fork
+}
+
+// CHECK-LABEL: sil hidden @_T029downgrade_exhaustivity_swift343testDowngradableOmittedPatternIsUnreachableyAA0E0OSg3pat_tF
+func testDowngradableOmittedPatternIsUnreachable(pat : Downgradable?) {
+  // CHECK: switch_enum {{%.*}} : $Downgradable, case #Downgradable.spoon!enumelt: [[CASE1:bb[0-9]+]], case #Downgradable.hat!enumelt: [[CASE2:bb[0-9]+]], default [[DEFAULT_CASE:bb[0-9]+]]
+  switch pat! {
+  // CHECK: [[CASE1]]:
+  case .spoon:
+    break
+  // CHECK: [[CASE2]]:
+  case .hat:
+    break
+  // CHECK: [[DEFAULT_CASE]]:
+  // CHECK-NEXT:   unreachable
+  }
+  
+  // CHECK: switch_enum {{%[0-9]+}} : $Downgradable, case #Downgradable.spoon!enumelt: {{bb[0-9]+}}, case #Downgradable.hat!enumelt: {{bb[0-9]+}}, default [[TUPLE_DEFAULT_CASE_1:bb[0-9]+]]
+  // CHECK: switch_enum [[Y:%[0-9]+]] : $Downgradable, case #Downgradable.spoon!enumelt: {{bb[0-9]+}}, case #Downgradable.hat!enumelt: {{bb[0-9]+}}, default [[TUPLE_DEFAULT_CASE_2:bb[0-9]+]]
+  switch (pat!, pat!) {
+  case (.spoon, .spoon):
+    break
+  case (.spoon, .hat):
+    break
+  case (.hat, .spoon):
+    break
+  case (.hat, .hat):
+    break
+  // CHECK: [[TUPLE_DEFAULT_CASE_2]]:
+  // CHECK-NEXT:   unreachable
+    
+  // CHECK: switch_enum [[Y]] : $Downgradable, case #Downgradable.spoon!enumelt: {{bb[0-9]+}}, case #Downgradable.hat!enumelt: {{bb[0-9]+}}, default [[TUPLE_DEFAULT_CASE_3:bb[0-9]+]]
+    
+  // CHECK: [[TUPLE_DEFAULT_CASE_3]]:
+  // CHECK-NEXT:   unreachable
+    
+  // CHECK: [[TUPLE_DEFAULT_CASE_1]]:
+  // CHECK-NEXT:   unreachable
+  }
+  
+}
+
diff --git a/test/SILOptimizer/constant_propagation.sil b/test/SILOptimizer/constant_propagation.sil
index 90d483a..48e9e17 100644
--- a/test/SILOptimizer/constant_propagation.sil
+++ b/test/SILOptimizer/constant_propagation.sil
@@ -1,6 +1,7 @@
 // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -diagnostic-constant-propagation | %FileCheck %s
 // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -performance-constant-propagation | %FileCheck %s
 
+import Swift
 import Builtin
 
 struct UInt {
@@ -692,3 +693,254 @@
   dealloc_stack %31 : $*AnObject
   br bb1
 }
+
+public protocol P {
+}
+
+public protocol PP {
+}
+
+struct X : P {
+}
+
+struct Y<T>: P {
+  var x : T
+}
+
+class Z: P {
+  init()
+}
+
+// Do not optimize casts to unrelated protocols.
+// CHECK-LABEL: sil @dont_replace_unconditional_check_cast_addr_for_type_to_unrelated_existential
+// CHECK: unconditional_checked_cast_addr
+// CHECK: end sil function 'dont_replace_unconditional_check_cast_addr_for_type_to_unrelated_existential'
+sil @dont_replace_unconditional_check_cast_addr_for_type_to_unrelated_existential : $@convention(thin) (@in X) -> (@out PP) {
+bb0(%0 : $*PP, %1 : $*X):
+  unconditional_checked_cast_addr take_always X in %1 : $*X to PP in %0 : $*PP
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// Do not optimize casts between existentials.
+// CHECK-LABEL: sil @dont_replace_unconditional_check_cast_addr_for_existential_to_existential
+// CHECK: unconditional_checked_cast_addr
+// CHECK: end sil function 'dont_replace_unconditional_check_cast_addr_for_existential_to_existential'
+sil @dont_replace_unconditional_check_cast_addr_for_existential_to_existential : $@convention(thin) (@in PP) -> (@out P) {
+bb0(%0 : $*P, %1 : $*PP):
+  unconditional_checked_cast_addr take_always PP in %1 : $*PP to P in %0 : $*P
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// Check that an unconditional_checked_cast_addr from a non-existential loadable type to a protocol
+// can be replaced by a more efficient code sequence if it is statitcally known that this
+// type conforms to this protocol.
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_existential
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: init_existential
+// CHECK-NOT: store
+// CHECK: copy_addr
+// CHECK-NOT: destroy_addr
+// CHECK-NOT: unconditional_checked_cast_addr
+sil @replace_unconditional_check_cast_addr_for_type_to_existential : $@convention(thin) (@in X) -> (@out P) {
+bb0(%0 : $*P, %1 : $*X):
+  unconditional_checked_cast_addr take_always X in %1 : $*X to P in %0 : $*P
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_class_to_existential
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
+// CHECK-NOT: unconditional_checked_cast_addr
+sil @replace_unconditional_check_cast_addr_for_class_to_existential : $@convention(thin) (@in Z) -> (@out P) {
+bb0(%0 : $*P, %1 : $*Z):
+  unconditional_checked_cast_addr take_always Z in %1 : $*Z to P in %0 : $*P
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_archetype_to_existential
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
+// CHECK-NOT: unconditional_checked_cast_addr
+sil @replace_unconditional_check_cast_addr_for_archetype_to_existential : $@convention(thin) <X:P> (@in X) -> (@out P) {
+bb0(%0 : $*P, %1 : $*X):
+  unconditional_checked_cast_addr take_always X in %1 : $*X to P in %0 : $*P
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_generic_type_to_existential
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
+// CHECK-NOT: unconditional_checked_cast_addr
+sil @replace_unconditional_check_cast_addr_for_generic_type_to_existential : $@convention(thin) <X:P> (@in Y<X>) -> (@out P) {
+bb0(%0 : $*P, %1 : $*Y<X>):
+  unconditional_checked_cast_addr take_always Y<X> in %1 : $*Y<X> to P in %0 : $*P
+  %2 = tuple ()
+  return %2 : $()
+}
+
+protocol Q : class {
+}
+
+class V : Q {
+  init()
+}
+
+class W<T>: Q {
+  var x : T
+  init()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_class_existential
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK-NOT: retain_value
+// CHECK: init_existential_ref
+// CHECK-NOT: retain_value
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_for_type_to_class_existential : $@convention(thin) (@in V) -> (@out Q) {
+bb0(%0 : $*Q, %1 : $*V):
+  unconditional_checked_cast_addr take_always V in %1 : $*V to Q in %0 : $*Q
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_class_existential_copy_on_success
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: retain_value
+// CHECK: init_existential_ref
+// CHECK-NOT: retain_value
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_for_type_to_class_existential_copy_on_success : $@convention(thin) (@in V) -> (@out Q) {
+bb0(%0 : $*Q, %1 : $*V):
+  unconditional_checked_cast_addr copy_on_success V in %1 : $*V to Q in %0 : $*Q
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_archetype_to_class_existential
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK-NOT: retain_value
+// CHECK: init_existential_ref
+// CHECK-NOT: retain_value
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_for_archetype_to_class_existential : $@convention(thin) <X:Q> (@in X) -> (@out Q) {
+bb0(%0 : $*Q, %1 : $*X):
+  unconditional_checked_cast_addr take_always X in %1 : $*X to Q in %0 : $*Q
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_to_class_existential
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK-NOT: retain_value
+// CHECK: init_existential_ref
+// CHECK-NOT: retain_value
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_to_class_existential : $@convention(thin) <X:Q> (@in W<X>) -> (@out Q) {
+bb0(%0 : $*Q, %1 : $*W<X>):
+  unconditional_checked_cast_addr take_always W<X> in %1 : $*W<X> to Q in %0 : $*Q
+  %2 = tuple ()
+  return %2 : $()
+}
+
+public protocol MyError : Error {
+}
+
+public class E1 : MyError {
+  init()
+}
+
+public class E2<T> : MyError {
+  init()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_myerror_existential 
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_for_type_to_myerror_existential : $@convention(thin) (@in E1) -> (@out MyError) {
+bb0(%0 : $*MyError, %1 : $*E1):
+  unconditional_checked_cast_addr take_always E1 in %1 : $*E1 to MyError in %0 : $*MyError
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_myerror_existential_copy_on_success
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
+// There should be no [take] in copy_addr! 
+// CHECK: copy_addr %{{.}} to [initialization]
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_for_type_to_myerror_existential_copy_on_success : $@convention(thin) (@in E1) -> (@out MyError) {
+bb0(%0 : $*MyError, %1 : $*E1):
+  unconditional_checked_cast_addr copy_on_success E1 in %1 : $*E1 to MyError in %0 : $*MyError
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_archetype_to_myerror_existentia
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_for_archetype_to_myerror_existential : $@convention(thin) <X:MyError> (@in X) -> (@out MyError) {
+bb0(%0 : $*MyError, %1 : $*X):
+  unconditional_checked_cast_addr take_always X in %1 : $*X to MyError in %0 : $*MyError
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_to_myerror_existential 
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_to_myerror_existential : $@convention(thin) <X:MyError> (@in E2<X>) -> (@out MyError) {
+bb0(%0 : $*MyError, %1 : $*E2<X>):
+  unconditional_checked_cast_addr take_always E2<X> in %1 : $*E2<X> to MyError in %0 : $*MyError
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// Check casts to Error.
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_error_existential 
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: [[ALLOC_BOX:%.*]] = alloc_existential_box $Error, $E1
+// CHECK: [[PROJ:%.*]] = project_existential_box $E1 in [[ALLOC_BOX]] : $Error
+// CHECK: [[VAL:%.*]] = load %1 : $*E1
+// CHECK: store [[VAL]] to [[PROJ]]
+// CHECK: store [[ALLOC_BOX]] to %0 : $*Error
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_for_type_to_error_existential : $@convention(thin) (@in E1) -> (@out Error) {
+bb0(%0 : $*Error, %1 : $*E1):
+  unconditional_checked_cast_addr take_always E1 in %1 : $*E1 to Error in %0 : $*Error
+  %2 = tuple ()
+  return %2 : $()
+}
+
+// Check casts to Error.
+// CHECK-LABEL: sil @replace_unconditional_check_cast_addr_for_type_to_error_existential_copy_on_success 
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: [[ALLOC_BOX:%.*]] = alloc_existential_box $Error, $E1
+// CHECK: [[PROJ:%.*]] = project_existential_box $E1 in [[ALLOC_BOX]] : $Error
+// CHECK: [[VAL:%.*]] = load %1 : $*E1
+// CHECK: retain_value [[VAL]]
+// CHECK: store [[VAL]] to [[PROJ]]
+// CHECK: store [[ALLOC_BOX]] to %0 : $*Error
+// CHECK: return
+sil @replace_unconditional_check_cast_addr_for_type_to_error_existential_copy_on_success : $@convention(thin) (@in E1) -> (@out Error) {
+bb0(%0 : $*Error, %1 : $*E1):
+  unconditional_checked_cast_addr copy_on_success E1 in %1 : $*E1 to Error in %0 : $*Error
+  %2 = tuple ()
+  return %2 : $()
+}
diff --git a/test/SILOptimizer/diagnose_unreachable.sil b/test/SILOptimizer/diagnose_unreachable.sil
index 8876a41..8bb789d 100644
--- a/test/SILOptimizer/diagnose_unreachable.sil
+++ b/test/SILOptimizer/diagnose_unreachable.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -diagnose-unreachable | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -diagnose-unreachable -sil-print-debuginfo | %FileCheck %s
 
 import Builtin
 import Swift
@@ -387,19 +387,24 @@
   throw %3 : $Error
 }
 
+sil_scope 0 { loc "f.swift":1:1 parent @try_apply_2 : $@convention(thin) (Builtin.Int1) -> @error Error }
+// CHECK: sil_scope [[F:[0-9]+]] { loc "f.swift":1:1 parent @try_apply_2
+sil_scope 1 { loc "f.swift":2:1 parent 0 }
+// CHECK: sil_scope [[S:[0-9]+]] { loc "f.swift":2:1 parent [[F]] }
 // CHECK-LABEL:sil @try_apply_2
-// CHECK:    bb3(
-// CHECK-NEXT: {{ unreachable}}
+// CHECK:    bb3({{.*}}$Never):
+// CHECK-NEXT: {{ unreachable }}, scope [[S]]
 // CHECK:    bb4(
 // CHECK-NEXT: throw
+
 sil @try_apply_2 : $@convention(thin) (Builtin.Int1) -> @error Error {
 bb0(%0 : $Builtin.Int1):
   %1 = function_ref @throwing_noreturn : $@convention(thin) () -> (Never, @error Error)
   cond_br %0, bb1, bb2
 bb1:
-  try_apply %1() : $@convention(thin) () -> (Never, @error Error), normal bb3, error bb4
+  try_apply %1() : $@convention(thin) () -> (Never, @error Error), normal bb3, error bb4, scope 0
 bb2:
-  try_apply %1() : $@convention(thin) () -> (Never, @error Error), normal bb3, error bb4
+  try_apply %1() : $@convention(thin) () -> (Never, @error Error), normal bb3, error bb4, scope 1
 bb3(%2 : $Never):
   %3 = tuple ()
   return %3 : $()
diff --git a/test/SILOptimizer/sil_combine_enum_addr.sil b/test/SILOptimizer/sil_combine_enum_addr.sil
index 8493ee9..a525fbf 100644
--- a/test/SILOptimizer/sil_combine_enum_addr.sil
+++ b/test/SILOptimizer/sil_combine_enum_addr.sil
@@ -6,7 +6,7 @@
 import Swift
 
 // CHECK-LABEL: sil  @convert_inject_enum_addr_select_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
-// CHECK: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
 // CHECK: inject_enum_addr
 // CHECK-NOT: select_enum_addr
 // CHECK-NOT: bb1
@@ -42,7 +42,7 @@
 
 
 // CHECK-LABEL: sil  @convert_inject_enum_addr_switch_enum_addr_into_cond_br : $@convention(thin) (@in Int, @inout _Stdout) -> ()
-// CHECK: unconditional_checked_cast_addr
+// CHECK: init_existential_addr
 // CHECK: inject_enum_addr
 // CHECK-NOT: switch_enum_addr
 // CHECK-NOT: bb1
diff --git a/test/Sema/exhaustive_switch.swift b/test/Sema/exhaustive_switch.swift
index 944db82..0ea73f2 100644
--- a/test/Sema/exhaustive_switch.swift
+++ b/test/Sema/exhaustive_switch.swift
@@ -309,3 +309,37 @@
   case .two: break
   }
 }
+
+enum Runcible {
+  case spoon
+  case hat
+  case fork
+}
+
+func checkDiagnosticMinimality(x: Runcible?) {
+  switch (x!, x!) { // expected-error {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '(.fork, _)'}}
+  // expected-note@-2 {{add missing case: '(.hat, .hat)'}}
+  // expected-note@-3 {{add missing case: '(.hat, .fork)'}}
+  // expected-note@-4 {{add missing case: '(_, .fork)'}}
+  case (.spoon, .spoon):
+    break
+  case (.spoon, .hat):
+    break
+  case (.hat, .spoon):
+    break
+  }
+  
+  switch (x!, x!) { // expected-error {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '(.fork, _)'}}
+  // expected-note@-2 {{add missing case: '(.hat, .spoon)'}}
+  // expected-note@-3 {{add missing case: '(.hat, .fork)'}}
+  // expected-note@-4 {{add missing case: '(.spoon, .hat)'}}
+  // expected-note@-5 {{add missing case: '(.spoon, .fork)'}}
+  // expected-note@-6 {{add missing case: '(_, .fork)'}}
+  case (.spoon, .spoon):
+    break
+  case (.hat, .hat):
+    break
+  }
+}
diff --git a/test/attr/attr_downgrade_exhaustivity.swift b/test/attr/attr_downgrade_exhaustivity.swift
new file mode 100644
index 0000000..c357209
--- /dev/null
+++ b/test/attr/attr_downgrade_exhaustivity.swift
@@ -0,0 +1,150 @@
+// RUN: %target-typecheck-verify-swift -swift-version 3 %s
+
+enum Runcible {
+  case spoon
+  case hat
+  @_downgrade_exhaustivity_check
+  case fork
+}
+
+enum Trioptional {
+  case some(Runcible)
+  case just(Runcible)
+  case none
+}
+
+enum Fungible {
+  case cash
+  case giftCard
+}
+
+func missingCases(x: Runcible?, y: Runcible?, z: Trioptional) {
+  // Should warn in S3 mode that `fork` isn't used
+  switch x! { // expected-warning {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '.fork'}}
+  case .spoon:
+    break
+  case .hat:
+    break
+  }
+
+  // Should warn in S3 mode that `fork` isn't used
+  switch (x!, y!) { // expected-warning {{switch must be exhaustive}}
+  // expected-note@-1 3 {{add missing case:}}
+  case (.spoon, .spoon):
+    break
+  case (.spoon, .hat):
+    break
+  case (.hat, .spoon):
+    break
+  case (.hat, .hat):
+    break
+  }
+  
+  // Should error, since `fork` is used but not totally covered
+  switch (x!, y!) { // expected-error {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '(.fork, .hat)'}}
+  // expected-note@-2 {{add missing case: '(.fork, .fork)'}}
+  // expected-note@-3 {{add missing case: '(.hat, .fork)'}}
+  // expected-note@-4 {{add missing case: '(_, .fork)'}}
+  case (.spoon, .spoon):
+    break
+  case (.spoon, .hat):
+    break
+  case (.hat, .spoon):
+    break
+  case (.hat, .hat):
+    break
+  case (.fork, .spoon):
+    break
+  }
+  
+  // Should error, since `fork` is used but not totally covered
+  switch (x!, y!) { // expected-error {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '(.fork, _)'}}
+  // expected-note@-2 {{add missing case: '(.spoon, .fork)'}}
+  case (.spoon, .spoon):
+    break
+  case (.spoon, .hat):
+    break
+  case (.hat, .spoon):
+    break
+  case (.hat, .hat):
+    break
+  case (.hat, .fork):
+    break
+  }
+  
+  // Should warn in S3 mode that `fork` isn't used
+  switch x { // expected-warning {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '.some(.fork)'}}
+  case .some(.spoon):
+    break
+  case .some(.hat):
+    break
+  case .none:
+    break
+  }
+  
+  // Should warn in S3 mode that `fork` isn't used
+  switch (x, y!) { // expected-warning {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '(.some(.fork), _)'}}
+  // expected-note@-2 {{add missing case: '(.none, .fork)'}}
+  // expected-note@-3 {{add missing case: '(.some(.hat), .fork)'}}
+  // expected-note@-4 {{add missing case: '(_, .fork)'}}
+  case (.some(.spoon), .spoon):
+    break
+  case (.some(.spoon), .hat):
+    break
+  case (.some(.hat), .spoon):
+    break
+  case (.some(.hat), .hat):
+    break
+  case (.none, .spoon):
+    break
+  case (.none, .hat):
+    break
+  }
+
+  // Should warn in S3 mode that `fork` isn't used
+  switch (x, y) { // expected-warning {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '(.some(.fork), _)'}}
+  // expected-note@-2 {{add missing case: '(_, .some(.fork))'}}
+  // expected-note@-3 {{add missing case: '(.some(.hat), .some(.fork))'}}
+  // expected-note@-4 {{add missing case: '(.none, _)'}}
+  case (.some(.spoon), .some(.spoon)):
+    break
+  case (.some(.spoon), .some(.hat)):
+    break
+  case (.some(.spoon), .none):
+    break
+  case (.some(.hat), .some(.spoon)):
+    break
+  case (.some(.hat), .some(.hat)):
+    break
+  case (.some(.hat), .none):
+    break
+  case (.some(.hat), .some(.spoon)): // expected-warning {{case is already handled by previous patterns; consider removing it}}
+    break
+  case (.some(.hat), .some(.hat)): // expected-warning {{case is already handled by previous patterns; consider removing it}}
+    break
+  case (.some(.hat), .none): // expected-warning {{case is already handled by previous patterns; consider removing it}}
+    break
+  }
+  
+  // Should warn in S3 mode that `fork` isn't used
+  switch z { // expected-warning {{switch must be exhaustive}}
+  // expected-note@-1 {{add missing case: '.some(.fork)'}}
+  // expected-note@-2 {{add missing case: '.just(.fork)'}}
+  case .some(.spoon):
+    break
+  case .some(.hat):
+    break
+  case .just(.spoon):
+    break
+  case .just(.hat):
+    break
+  case .none:
+    break
+  }
+}
diff --git a/test/decl/var/lazy_properties.swift b/test/decl/var/lazy_properties.swift
index 1f6dba9..ab76c10 100644
--- a/test/decl/var/lazy_properties.swift
+++ b/test/decl/var/lazy_properties.swift
@@ -1,4 +1,5 @@
-// RUN: %target-typecheck-verify-swift -parse-as-library
+// RUN: %target-typecheck-verify-swift -parse-as-library -swift-version 3
+// RUN: %target-typecheck-verify-swift -parse-as-library -swift-version 4
 
 lazy func lazy_func() {} // expected-error {{'lazy' may only be used on 'var' declarations}} {{1-6=}}
 
@@ -27,22 +28,21 @@
 
   lazy var (e, f) = (1,2)  // expected-error {{'lazy' cannot destructure an initializer}} {{3-8=}}
 
-  lazy var g : Int = { 0 }()   // single-expr closure
+  lazy var g = { 0 }()   // single-expr closure
 
-  lazy var h : Int = { return 0 }()+1  // multi-stmt closure
+  lazy var h : Int = { 0 }()   // single-expr closure
 
-  lazy var i : Int = 42 {  // expected-error {{lazy properties may not have observers}} {{3-8=}}
+  lazy var i = { () -> Int in return 0 }()+1  // multi-stmt closure
+
+  lazy var j : Int = { return 0 }()+1  // multi-stmt closure
+
+  lazy var k : Int = { () -> Int in return 0 }()+1  // multi-stmt closure
+
+  lazy var l : Int = 42 {  // expected-error {{lazy properties may not have observers}} {{3-8=}}
     didSet {
     }
   }
 
-  // Lazy values can have observers, be NSCopying, etc.
-/*  lazy var d : Int = 42 {
-    didSet {
-      print("set me")
-    }
-  }*/
-
   init() {
     lazy var localvar = 42  // expected-error {{lazy is only valid for members of a struct or class}} {{5-10=}}
     localvar += 1
@@ -73,7 +73,8 @@
 
 // <rdar://problem/16889110> capture lists in lazy member properties cannot use self
 class CaptureListInLazyProperty {
-  lazy var closure: () -> Int = { [weak self] in return self!.i }
+  lazy var closure1 = { [weak self] in return self!.i }
+  lazy var closure2: () -> Int = { [weak self] in return self!.i }
   var i = 42
 }
 
@@ -91,3 +92,64 @@
     _ = ()
   }
 }
+
+protocol MyProtocol {
+  func f() -> Int
+}
+
+struct MyStruct : MyProtocol {
+  func f() -> Int { return 0 }
+}
+
+struct Outer {
+  static let p: MyProtocol = MyStruct()
+
+  struct Inner {
+    lazy var x = p.f()
+
+    lazy var y = {_ = 3}()
+    // expected-warning@-1 {{variable 'y' inferred to have type '()', which may be unexpected}}
+    // expected-note@-2 {{add an explicit type annotation to silence this warning}}
+  }
+}
+
+// https://bugs.swift.org/browse/SR-2616
+struct Construction {
+  init(x: Int, y: Int? = 42) { }
+}
+
+class Constructor {
+  lazy var myQ = Construction(x: 3)
+}
+
+
+// Problems with self references
+class BaseClass {
+  var baseInstanceProp = 42
+  static var baseStaticProp = 42
+}
+
+class ReferenceSelfInLazyProperty : BaseClass {
+  lazy var refs = (i, f())
+  lazy var trefs: (Int, Int) = (i, f())
+
+  lazy var qrefs = (self.i, self.f())
+  lazy var qtrefs: (Int, Int) = (self.i, self.f())
+
+  lazy var crefs = { (i, f()) }()
+  lazy var ctrefs: (Int, Int) = { (i, f()) }()
+
+  lazy var cqrefs = { (self.i, self.f()) }()
+  lazy var cqtrefs: (Int, Int) = { (self.i, self.f()) }()
+
+  lazy var mrefs = { () -> (Int, Int) in return (i, f()) }()
+  // expected-error@-1 {{call to method 'f' in closure requires explicit 'self.' to make capture semantics explicit}}
+  // expected-error@-2 {{reference to property 'i' in closure requires explicit 'self.' to make capture semantics explicit}}
+  lazy var mtrefs: (Int, Int) = { return (i, f()) }()
+
+  lazy var mqrefs = { () -> (Int, Int) in (self.i, self.f()) }()
+  lazy var mqtrefs: (Int, Int) = { return (self.i, self.f()) }()
+
+  var i = 42
+  func f() -> Int { return 0 }
+}
diff --git a/test/expr/cast/dictionary_bridge.swift b/test/expr/cast/dictionary_bridge.swift
index c4ab85b..8b973f6 100644
--- a/test/expr/cast/dictionary_bridge.swift
+++ b/test/expr/cast/dictionary_bridge.swift
@@ -83,12 +83,12 @@
   dictBO = dictBB as [BridgedToObjC: ObjC]
   dictOB = dictBB as [ObjC: BridgedToObjC]
 
-  dictBB = dictBO // expected-error{{cannot assign value of type 'Dictionary<BridgedToObjC, ObjC>' to type 'Dictionary<BridgedToObjC, BridgedToObjC>'}}
-  dictBB = dictOB // expected-error{{cannot assign value of type 'Dictionary<ObjC, BridgedToObjC>' to type 'Dictionary<BridgedToObjC, BridgedToObjC>'}}
+  dictBB = dictBO // expected-error{{cannot assign value of type '[BridgedToObjC : ObjC]' to type '[BridgedToObjC : BridgedToObjC]'}}
+  dictBB = dictOB // expected-error{{cannot assign value of type '[ObjC : BridgedToObjC]' to type '[BridgedToObjC : BridgedToObjC]'}}
 
-  dictDO = dictBB // expected-error{{cannot assign value of type 'Dictionary<BridgedToObjC, BridgedToObjC>' to type 'Dictionary<DerivesObjC, ObjC>'}}
-  dictOD = dictBB // expected-error{{cannot assign value of type 'Dictionary<BridgedToObjC, BridgedToObjC>' to type 'Dictionary<ObjC, DerivesObjC>'}}
-  dictDD = dictBB // expected-error{{cannot assign value of type 'Dictionary<BridgedToObjC, BridgedToObjC>' to type 'Dictionary<DerivesObjC, DerivesObjC>'}}
+  dictDO = dictBB // expected-error{{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[DerivesObjC : ObjC]'}}
+  dictOD = dictBB // expected-error{{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[ObjC : DerivesObjC]'}}
+  dictDD = dictBB // expected-error{{cannot assign value of type '[BridgedToObjC : BridgedToObjC]' to type '[DerivesObjC : DerivesObjC]'}}
   
   _ = dictDD; _ = dictDO; _ = dictOD; _ = dictOO; _ = dictOR; _ = dictOR; _ = dictRR; _ = dictRO
 }
@@ -119,7 +119,7 @@
   _ = dictOB as Dictionary<BridgedToObjC, BridgedToObjC>
 
   // We don't do mixed down/upcasts.
-  _ = dictDO as! Dictionary<BridgedToObjC, BridgedToObjC> // expected-warning{{forced cast from 'Dictionary<DerivesObjC, ObjC>' to 'Dictionary<BridgedToObjC, BridgedToObjC>' always succeeds; did you mean to use 'as'?}}
+  _ = dictDO as! Dictionary<BridgedToObjC, BridgedToObjC> // expected-warning{{forced cast from '[DerivesObjC : ObjC]' to 'Dictionary<BridgedToObjC, BridgedToObjC>' always succeeds; did you mean to use 'as'?}}
 }
 
 func testConditionalDowncastBridge() {
@@ -149,7 +149,7 @@
 
   // Mixed down/upcasts.
   if let d = dictDO as? Dictionary<BridgedToObjC, BridgedToObjC> { _ = d }
-  // expected-warning@-1{{conditional cast from 'Dictionary<DerivesObjC, ObjC>' to 'Dictionary<BridgedToObjC, BridgedToObjC>' always succeeds}}
+  // expected-warning@-1{{conditional cast from '[DerivesObjC : ObjC]' to 'Dictionary<BridgedToObjC, BridgedToObjC>' always succeeds}}
 
   _ = dictRR
   _ = dictRO
diff --git a/test/expr/cast/dictionary_coerce.swift b/test/expr/cast/dictionary_coerce.swift
index 76fa403b..de97265 100644
--- a/test/expr/cast/dictionary_coerce.swift
+++ b/test/expr/cast/dictionary_coerce.swift
@@ -24,11 +24,11 @@
 dictCC = dictDD
 
 dictCD = dictDD
-dictCD = dictCC // expected-error{{cannot assign value of type 'Dictionary<C, C>' to type 'Dictionary<C, D>'}}
+dictCD = dictCC // expected-error{{cannot assign value of type '[C : C]' to type '[C : D]'}}
 
 
 dictDC = dictDD
-dictDC = dictCD // expected-error{{cannot assign value of type 'Dictionary<C, D>' to type 'Dictionary<D, C>'}}
+dictDC = dictCD // expected-error{{cannot assign value of type '[C : D]' to type '[D : C]'}}
 
-dictDD = dictCC // expected-error{{cannot assign value of type 'Dictionary<C, C>' to type 'Dictionary<D, D>'}}
+dictDD = dictCC // expected-error{{cannot assign value of type '[C : C]' to type '[D : D]'}}
 
diff --git a/test/expr/cast/dictionary_downcast.swift b/test/expr/cast/dictionary_downcast.swift
index b5cdef3..7f818cf 100644
--- a/test/expr/cast/dictionary_downcast.swift
+++ b/test/expr/cast/dictionary_downcast.swift
@@ -34,12 +34,12 @@
 if let _ = dictCC as? Dictionary<D, D> { }
 
 // Test dictionary downcasts to unrelated types.
-dictCC as Dictionary<D, U> // expected-error{{cannot convert value of type 'Dictionary<C, C>' to type 'Dictionary<D, U>' in coercion}}
-dictCC as Dictionary<U, D> // expected-error{{cannot convert value of type 'Dictionary<C, C>' to type 'Dictionary<U, D>' in coercion}}
-dictCC as Dictionary<U, U> // expected-error{{cannot convert value of type 'Dictionary<C, C>' to type 'Dictionary<U, U>' in coercion}}
+dictCC as Dictionary<D, U> // expected-error{{cannot convert value of type '[C : C]' to type 'Dictionary<D, U>' in coercion}}
+dictCC as Dictionary<U, D> // expected-error{{cannot convert value of type '[C : C]' to type 'Dictionary<U, D>' in coercion}}
+dictCC as Dictionary<U, U> // expected-error{{cannot convert value of type '[C : C]' to type 'Dictionary<U, U>' in coercion}}
 
 // Test dictionary conditional downcasts to unrelated types
-if let _ = dictCC as? Dictionary<D, U> { } // expected-warning{{cast from 'Dictionary<C, C>' to unrelated type 'Dictionary<D, U>' always fails}}
-if let _ = dictCC as? Dictionary<U, D> { } // expected-warning{{cast from 'Dictionary<C, C>' to unrelated type 'Dictionary<U, D>' always fails}}
-if let _ = dictCC as? Dictionary<U, U> { } // expected-warning{{cast from 'Dictionary<C, C>' to unrelated type 'Dictionary<U, U>' always fails}}
+if let _ = dictCC as? Dictionary<D, U> { } // expected-warning{{cast from '[C : C]' to unrelated type 'Dictionary<D, U>' always fails}}
+if let _ = dictCC as? Dictionary<U, D> { } // expected-warning{{cast from '[C : C]' to unrelated type 'Dictionary<U, D>' always fails}}
+if let _ = dictCC as? Dictionary<U, U> { } // expected-warning{{cast from '[C : C]' to unrelated type 'Dictionary<U, U>' always fails}}
 
diff --git a/test/stdlib/StringCompatibility.swift b/test/stdlib/StringCompatibility.swift
index ba8fb14..385ef0b 100644
--- a/test/stdlib/StringCompatibility.swift
+++ b/test/stdlib/StringCompatibility.swift
@@ -4,58 +4,275 @@
 
 import StdlibUnittest
 
+//===--- MyString ---------------------------------------------------------===//
+/// A simple StringProtocol with a wacky .description that proves
+/// LosslessStringConvertible is not infecting ordinary constructions by using
+/// .description as the content of a copied string.
+struct MyString {
+  var base: String
+}
+
+extension MyString : BidirectionalCollection {
+  typealias Iterator = String.Iterator
+  typealias Index = String.Index
+  typealias IndexDistance = String.IndexDistance
+  func makeIterator() -> Iterator { return base.makeIterator() }
+  var startIndex: String.Index { return base.startIndex }
+  var endIndex: String.Index { return base.startIndex }
+  subscript(i: Index) -> Character { return base[i] }
+  func index(after i: Index) -> Index { return base.index(after: i) }
+  func index(before i: Index) -> Index { return base.index(before: i) }
+  func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+    return base.index(i, offsetBy: n)
+  }
+  func distance(from i: Index, to j: Index) -> IndexDistance {
+    return base.distance(from: i, to: j)
+  }
+}
+
+extension MyString : RangeReplaceableCollection {
+  init() { base = "" }
+  mutating func append<S: Sequence>(contentsOf s: S)
+  where S.Element == Character {
+    base.append(contentsOf: s)
+  }
+  mutating func replaceSubrange<C: Collection>(_ r: Range<Index>, with c: C)
+  where C.Element == Character {
+    base.replaceSubrange(r, with: c)
+  }
+}
+
+extension MyString : CustomStringConvertible {
+  var description: String { return "***MyString***" }
+}
+
+extension MyString : TextOutputStream {
+  public mutating func write(_ other: String) {
+    append(contentsOf: other)
+  }
+}
+
+extension MyString : TextOutputStreamable {
+  public func write<Target : TextOutputStream>(to target: inout Target) {
+    target.write(base)
+  }
+}
+
+extension MyString : ExpressibleByUnicodeScalarLiteral {
+  public init(unicodeScalarLiteral value: String) {
+    base = .init(unicodeScalarLiteral: value)
+  }
+}
+extension MyString : ExpressibleByExtendedGraphemeClusterLiteral {
+  public init(extendedGraphemeClusterLiteral value: String) {
+    base = .init(extendedGraphemeClusterLiteral: value)
+  }
+}
+
+extension MyString : ExpressibleByStringLiteral {
+  public init(stringLiteral value: String) {
+    base = .init(stringLiteral: value)
+  }
+}
+
+extension MyString : CustomReflectable {
+  public var customMirror: Mirror {
+    return base.customMirror
+  }
+}
+
+extension MyString : CustomPlaygroundQuickLookable {
+  public var customPlaygroundQuickLook: PlaygroundQuickLook {
+    return base.customPlaygroundQuickLook
+  }
+}
+
+extension MyString : CustomDebugStringConvertible {
+  public var debugDescription: String {
+    return "(***MyString***)"
+  }
+}
+
+extension MyString : Equatable {
+  public static func ==(lhs: MyString, rhs: MyString) -> Bool {
+    return lhs.base == rhs.base
+  }
+}
+
+extension MyString : Comparable {
+  public static func <(lhs: MyString, rhs: MyString) -> Bool {
+    return lhs.base < rhs.base
+  }
+}
+
+extension MyString : Hashable {
+  public var hashValue : Int {
+    return base.hashValue
+  }
+}
+
+#if _runtime(_ObjC)
+
+extension MyString {
+  public func hasPrefix(_ prefix: String) -> Bool {
+    return self.base.hasPrefix(prefix)
+  }
+
+  public func hasSuffix(_ suffix: String) -> Bool {
+    return self.base.hasSuffix(suffix)
+  }
+}
+
+#endif
+
+extension MyString : StringProtocol {
+  typealias UTF8Index = String.UTF8Index
+  typealias UTF16Index = String.UTF16Index
+  typealias UnicodeScalarIndex = String.UnicodeScalarIndex
+  var utf8: String.UTF8View { return base.utf8 }
+  var utf16: String.UTF16View { return base.utf16 }
+  var unicodeScalars: String.UnicodeScalarView { return base.unicodeScalars }
+  var characters: String.CharacterView { return base.characters }
+  func lowercased() -> String {
+    return base.lowercased()
+  }
+  func uppercased() -> String {
+    return base.uppercased()
+  }
+
+  init<C: Collection, Encoding: Unicode.Encoding>(
+    decoding codeUnits: C, as sourceEncoding: Encoding.Type
+  )
+  where C.Iterator.Element == Encoding.CodeUnit {
+    base = .init(decoding: codeUnits, as: sourceEncoding)
+  }
+
+  init(cString nullTerminatedUTF8: UnsafePointer<CChar>) {
+    base = .init(cString: nullTerminatedUTF8)
+  }
+  
+  init<Encoding: Unicode.Encoding>(
+    decodingCString nullTerminatedCodeUnits: UnsafePointer<Encoding.CodeUnit>,
+    as sourceEncoding: Encoding.Type) {
+    base = .init(decodingCString: nullTerminatedCodeUnits, as: sourceEncoding)
+  }
+  
+  func withCString<Result>(
+    _ body: (UnsafePointer<CChar>) throws -> Result) rethrows -> Result {
+    return try base.withCString(body)
+  }
+
+  func withCString<Result, Encoding: Unicode.Encoding>(
+    encodedAs targetEncoding: Encoding.Type,
+    _ body: (UnsafePointer<Encoding.CodeUnit>) throws -> Result
+  ) rethrows -> Result {
+    return try base.withCString(encodedAs: targetEncoding, body)
+  }
+}
+//===----------------------------------------------------------------------===//
+
 #if swift(>=4)
 
-public typealias ExpectedSubstring = Substring
+public typealias ExpectedConcreteSlice = Substring
+public typealias ExpectedStringFromString = String
+let swift = 4
 
 #else
 
-public typealias ExpectedSubstring = String
+public typealias ExpectedConcreteSlice = String
+public typealias ExpectedStringFromString = String?
+let swift = 3
 
 #endif
 
 var Tests = TestSuite("SubstringCompatibility")
 
-Tests.test("Range/Subscript/ExpectedType") {
+Tests.test("String/Range/Slice/ExpectedType/\(swift)") {
   var s = "hello world"
   var sub = s[s.startIndex ..< s.endIndex]
   var subsub = sub[s.startIndex ..< s.endIndex]
 
   expectType(String.self, &s)
-  expectType(ExpectedSubstring.self, &sub)
-  expectType(ExpectedSubstring.self, &subsub)
+  expectType(ExpectedConcreteSlice.self, &sub)
+  expectType(ExpectedConcreteSlice.self, &subsub)
 }
 
-Tests.test("ClosedRange/Subsript/ExpectedType") {
+Tests.test("String/ClosedRange/Slice/ExpectedType/\(swift)") {
   var s = "hello world"
   let lastIndex = s.index(before:s.endIndex)
   var sub = s[s.startIndex ... lastIndex]
   var subsub = sub[s.startIndex ... lastIndex]
 
   expectType(String.self, &s)
-  expectType(ExpectedSubstring.self, &sub)
-  expectType(ExpectedSubstring.self, &subsub)
+  expectType(ExpectedConcreteSlice.self, &sub)
+  expectType(ExpectedConcreteSlice.self, &subsub)
 }
 
-Tests.test("String.init(_:String)/default type") {
-  var s = String("")
-  expectType(String?.self, &s)
+Tests.test("Substring/Range/Slice/ExpectedType/\(swift)") {
+  let s = "hello world" as Substring
+  var sub = s[s.startIndex ..< s.endIndex]
+  var subsub = sub[s.startIndex ..< s.endIndex]
+
+  expectType(ExpectedConcreteSlice.self, &sub)
+  expectType(ExpectedConcreteSlice.self, &subsub)
 }
 
-Tests.test("LosslessStringConvertible/generic") {
+Tests.test("Substring/ClosedRange/Slice/ExpectedType/\(swift)") {
+  let s = "hello world" as Substring
+  let lastIndex = s.index(before:s.endIndex)
+  var sub = s[s.startIndex ... lastIndex]
+  var subsub = sub[s.startIndex ... lastIndex]
+
+  expectType(ExpectedConcreteSlice.self, &sub)
+  expectType(ExpectedConcreteSlice.self, &subsub)
+}
+
+Tests.test("RangeReplaceable.init/generic/\(swift)") {
+  func check<
+    T: RangeReplaceableCollection, S: Collection
+  >(_: T.Type, from source: S)
+  where T.Element : Equatable, T.Element == S.Element
+  {
+    var r = T(source)
+    expectType(T.self, &r)
+    expectEqualSequence(Array(source), Array(r))
+  }
+
+  check(String.self, from: "a" as String)
+  check(Substring.self, from: "b" as String)
+  // FIXME: Why isn't this working?
+  // check(MyString.self, from: "c" as String)
+  
+  check(String.self, from: "d" as Substring)
+  check(Substring.self, from: "e" as Substring)
+  // FIXME: Why isn't this working?
+  // check(MyString.self, from: "f" as Substring)
+
+  // FIXME: Why isn't this working?
+  // check(String.self, from: "g" as MyString)
+  // check(Substring.self, from: "h" as MyString)
+  check(MyString.self, from: "i" as MyString)
+}
+
+Tests.test("String.init(someString)/default type/\(swift)") {
+  var s = String("" as String)
+  expectType(ExpectedStringFromString.self, &s)
+}
+
+Tests.test("Substring.init(someString)/default type/\(swift)") {
+  var s = Substring("" as Substring)
+  expectType(Substring.self, &s)
+}
+
+Tests.test("LosslessStringConvertible/generic/\(swift)") {
   func f<T : LosslessStringConvertible>(_ x: T.Type) {
     _ = T("")! // unwrapping optional should work in generic context
   }
   f(String.self)
 }
 
-Tests.test("LosslessStringConvertible/concrete") {
-  _ = String("") as String?
-}
-
-#if swift(>=4)
-#else
-Tests.test("LosslessStringConvertible/force unwrap") {
+#if !swift(>=4)
+Tests.test("LosslessStringConvertible/force unwrap/\(swift)") {
   // Force unwrap should still work in Swift 3 mode
   _ = String("")!
 }
diff --git a/test/stmt/statements.swift b/test/stmt/statements.swift
index db46e81..e8dcd1a 100644
--- a/test/stmt/statements.swift
+++ b/test/stmt/statements.swift
@@ -418,6 +418,7 @@
 // condition may have contained a SequenceExpr.
 func r23684220(_ b: Any) {
   if let _ = b ?? b {} // expected-error {{initializer for conditional binding must have Optional type, not 'Any'}}
+  // expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type 'Any', so the right side is never used}}
 }
 
 
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
index f7b1d8a..d2712da 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
@@ -729,6 +729,7 @@
     // Ignore these.
     case DAK_ShowInInterface:
     case DAK_RawDocComment:
+    case DAK_DowngradeExhaustivityCheck:
       continue;
     default:
       break;
diff --git a/utils/symbolicate-linux-fatal b/utils/symbolicate-linux-fatal
index e9215d9..81d403f 100755
--- a/utils/symbolicate-linux-fatal
+++ b/utils/symbolicate-linux-fatal
@@ -25,6 +25,7 @@
 from __future__ import print_function
 
 import argparse
+import os
 import subprocess
 
 import lldb
@@ -34,8 +35,11 @@
     dyn_libs = {}
     for line in lddoutput.splitlines():
         ldd_tokens = line.split()
-        if len(ldd_tokens) >= 3:
-            dyn_libs[ldd_tokens[0]] = ldd_tokens[2]
+        if len(ldd_tokens) >= 2:
+            lib = ldd_tokens[-2]
+            dyn_libs[ldd_tokens[0]] = lib
+            real_name = os.path.basename(os.path.realpath(lib)) 
+            dyn_libs[real_name] = lib
     return dyn_libs
 
 
diff --git a/validation-test/compiler_crashers/28508-unreachable-executed-at-swift-lib-sema-csgen-cpp-2656.swift b/validation-test/compiler_crashers_fixed/28508-unreachable-executed-at-swift-lib-sema-csgen-cpp-2656.swift
similarity index 87%
rename from validation-test/compiler_crashers/28508-unreachable-executed-at-swift-lib-sema-csgen-cpp-2656.swift
rename to validation-test/compiler_crashers_fixed/28508-unreachable-executed-at-swift-lib-sema-csgen-cpp-2656.swift
index 33b37bd..19f3c69 100644
--- a/validation-test/compiler_crashers/28508-unreachable-executed-at-swift-lib-sema-csgen-cpp-2656.swift
+++ b/validation-test/compiler_crashers_fixed/28508-unreachable-executed-at-swift-lib-sema-csgen-cpp-2656.swift
@@ -5,5 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 protocol A{{}func a{}struct A{lazy var f=a
diff --git a/validation-test/compiler_crashers/28509-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift b/validation-test/compiler_crashers_fixed/28509-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
similarity index 82%
rename from validation-test/compiler_crashers/28509-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
rename to validation-test/compiler_crashers_fixed/28509-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
index b207867..fe46a52 100644
--- a/validation-test/compiler_crashers/28509-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
+++ b/validation-test/compiler_crashers_fixed/28509-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// RUN: not --crash %target-swift-frontend %s -emit-ir
-// REQUIRES: asserts
+// RUN: not %target-swift-frontend %s -emit-ir
 class d{lazy var f={_={
diff --git a/validation-test/compiler_crashers/28605-anonymous-namespace-verifier-verifychecked-swift-type-llvm-smallptrset-swift-arc.swift b/validation-test/compiler_crashers_fixed/28605-anonymous-namespace-verifier-verifychecked-swift-type-llvm-smallptrset-swift-arc.swift
similarity index 87%
rename from validation-test/compiler_crashers/28605-anonymous-namespace-verifier-verifychecked-swift-type-llvm-smallptrset-swift-arc.swift
rename to validation-test/compiler_crashers_fixed/28605-anonymous-namespace-verifier-verifychecked-swift-type-llvm-smallptrset-swift-arc.swift
index 8e6313f..caf6a1e 100644
--- a/validation-test/compiler_crashers/28605-anonymous-namespace-verifier-verifychecked-swift-type-llvm-smallptrset-swift-arc.swift
+++ b/validation-test/compiler_crashers_fixed/28605-anonymous-namespace-verifier-verifychecked-swift-type-llvm-smallptrset-swift-arc.swift
@@ -5,6 +5,6 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 protocol A:RangeReplaceableCollection
 guard let c=A.init(
diff --git a/validation-test/compiler_crashers/28755-getkind-requirementkind-layout.swift b/validation-test/compiler_crashers_fixed/28755-getkind-requirementkind-layout.swift
similarity index 82%
rename from validation-test/compiler_crashers/28755-getkind-requirementkind-layout.swift
rename to validation-test/compiler_crashers_fixed/28755-getkind-requirementkind-layout.swift
index faef36c..2e29534 100644
--- a/validation-test/compiler_crashers/28755-getkind-requirementkind-layout.swift
+++ b/validation-test/compiler_crashers_fixed/28755-getkind-requirementkind-layout.swift
@@ -5,6 +5,5 @@
 // See https://swift.org/LICENSE.txt for license information
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 Unmanaged.t