Merge pull request #17561 from jckarter/silfunctiontype-pseudogeneric-iff-generic

 SIL: Assert that SILFunctionTypes are only @pseudogeneric when they have generic arguments.
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index d36b026..fdbc7be 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -2279,7 +2279,6 @@
     StoredProperty,
     GettableProperty,
     SettableProperty,
-    External,
     OptionalChain,
     OptionalForce,
     OptionalWrap,
@@ -2298,7 +2297,6 @@
   enum PackedKind: unsigned {
     PackedStored,
     PackedComputed,
-    PackedExternal,
     Unpacked,
   };
   
@@ -2311,8 +2309,6 @@
     case Kind::GettableProperty:
     case Kind::SettableProperty:
       return PackedComputed;
-    case Kind::External:
-      return PackedExternal;
     case Kind::OptionalChain:
     case Kind::OptionalForce:
     case Kind::OptionalWrap:
@@ -2323,23 +2319,18 @@
   // Value is the VarDecl* for StoredProperty, the SILFunction* of the
   // Getter for computed properties, or the Kind for other kinds
   llvm::PointerIntPair<void *, KindPackingBits, unsigned> ValueAndKind;
-  union {
-    // Valid if Kind == GettableProperty || Kind == SettableProperty
-    struct {
-      llvm::PointerIntPair<SILFunction *, 2,
-                           ComputedPropertyId::KindType> SetterAndIdKind;
-      ComputedPropertyId::ValueType IdValue;
-    } Computed;
-    // Valid if Kind == External
-    SubstitutionMap ExternalSubstitutions;
-  };
+  llvm::PointerIntPair<SILFunction *, 2,
+                       ComputedPropertyId::KindType> SetterAndIdKind;
+  ComputedPropertyId::ValueType IdValue;
   ArrayRef<Index> Indices;
   struct {
     SILFunction *Equal;
     SILFunction *Hash;
   } IndexEquality;
   CanType ComponentType;
-  
+  AbstractStorageDecl *ExternalStorage;
+  SubstitutionMap ExternalSubstitutions;
+
   /// Constructor for stored components
   KeyPathPatternComponent(VarDecl *storedProp,
                           CanType ComponentType)
@@ -2353,26 +2344,18 @@
                           ArrayRef<Index> indices,
                           SILFunction *indicesEqual,
                           SILFunction *indicesHash,
+                          AbstractStorageDecl *externalStorage,
+                          SubstitutionMap externalSubstitutions,
                           CanType ComponentType)
     : ValueAndKind(getter, PackedComputed),
-      Computed{{setter, id.Kind}, {id.Value}},
+      SetterAndIdKind{setter, id.Kind},
+      IdValue{id.Value},
       Indices(indices),
       IndexEquality{indicesEqual, indicesHash},
-      ComponentType(ComponentType) {
-  }
-  
-  /// Constructor for external components
-  KeyPathPatternComponent(AbstractStorageDecl *externalStorage,
-                          SubstitutionMap substitutions,
-                          ArrayRef<Index> indices,
-                          SILFunction *indicesEqual,
-                          SILFunction *indicesHash,
-                          CanType componentType)
-    : ValueAndKind(externalStorage, PackedExternal),
-      ExternalSubstitutions(substitutions),
-      Indices(indices),
-      IndexEquality{indicesEqual, indicesHash},
-      ComponentType(componentType) {
+      ComponentType(ComponentType),
+      ExternalStorage(externalStorage),
+      ExternalSubstitutions(externalSubstitutions)
+  {
   }
   
   /// Constructor for optional components.
@@ -2396,10 +2379,8 @@
     case PackedStored:
       return Kind::StoredProperty;
     case PackedComputed:
-      return Computed.SetterAndIdKind.getPointer()
+      return SetterAndIdKind.getPointer()
         ? Kind::SettableProperty : Kind::GettableProperty;
-    case PackedExternal:
-      return Kind::External;
     case Unpacked:
       return (Kind)((uintptr_t)ValueAndKind.getPointer() >> KindPackingBits);
     }
@@ -2418,7 +2399,6 @@
     case Kind::OptionalChain:
     case Kind::OptionalForce:
     case Kind::OptionalWrap:
-    case Kind::External:
       llvm_unreachable("not a stored property");
     }
     llvm_unreachable("unhandled kind");
@@ -2430,12 +2410,11 @@
     case Kind::OptionalChain:
     case Kind::OptionalForce:
     case Kind::OptionalWrap:
-    case Kind::External:
       llvm_unreachable("not a computed property");
     case Kind::GettableProperty:
     case Kind::SettableProperty:
-      return ComputedPropertyId(Computed.IdValue,
-                                Computed.SetterAndIdKind.getInt());
+      return ComputedPropertyId(IdValue,
+                                SetterAndIdKind.getInt());
     }
     llvm_unreachable("unhandled kind");
   }
@@ -2446,7 +2425,6 @@
     case Kind::OptionalChain:
     case Kind::OptionalForce:
     case Kind::OptionalWrap:
-    case Kind::External:
       llvm_unreachable("not a computed property");
     case Kind::GettableProperty:
     case Kind::SettableProperty:
@@ -2462,10 +2440,9 @@
     case Kind::OptionalChain:
     case Kind::OptionalForce:
     case Kind::OptionalWrap:
-    case Kind::External:
       llvm_unreachable("not a settable computed property");
     case Kind::SettableProperty:
-      return Computed.SetterAndIdKind.getPointer();
+      return SetterAndIdKind.getPointer();
     }
     llvm_unreachable("unhandled kind");
   }
@@ -2479,7 +2456,6 @@
       return {};
     case Kind::GettableProperty:
     case Kind::SettableProperty:
-    case Kind::External:
       return Indices;
     }
   }
@@ -2491,7 +2467,6 @@
     case Kind::OptionalForce:
     case Kind::OptionalWrap:
       llvm_unreachable("not a computed property");
-    case Kind::External:
     case Kind::GettableProperty:
     case Kind::SettableProperty:
       return IndexEquality.Equal;
@@ -2504,7 +2479,6 @@
     case Kind::OptionalForce:
     case Kind::OptionalWrap:
       llvm_unreachable("not a computed property");
-    case Kind::External:
     case Kind::GettableProperty:
     case Kind::SettableProperty:
       return IndexEquality.Hash;
@@ -2519,15 +2493,29 @@
   }
   
   AbstractStorageDecl *getExternalDecl() const {
-    assert(getKind() == Kind::External
-           && "not an external property");
-    return (AbstractStorageDecl*)ValueAndKind.getPointer();
+    switch (getKind()) {
+    case Kind::StoredProperty:
+    case Kind::OptionalChain:
+    case Kind::OptionalForce:
+    case Kind::OptionalWrap:
+      llvm_unreachable("not a computed property");
+    case Kind::GettableProperty:
+    case Kind::SettableProperty:
+      return ExternalStorage;
+    }
   }
   
   SubstitutionMap getExternalSubstitutions() const {
-    assert(getKind() == Kind::External
-           && "not an external property");
-    return ExternalSubstitutions;
+    switch (getKind()) {
+    case Kind::StoredProperty:
+    case Kind::OptionalChain:
+    case Kind::OptionalForce:
+    case Kind::OptionalWrap:
+      llvm_unreachable("not a computed property");
+    case Kind::GettableProperty:
+    case Kind::SettableProperty:
+      return ExternalSubstitutions;
+    }
   }
 
   static KeyPathPatternComponent
@@ -2536,10 +2524,14 @@
                               ArrayRef<Index> indices,
                               SILFunction *indicesEquals,
                               SILFunction *indicesHash,
+                              AbstractStorageDecl *externalDecl,
+                              SubstitutionMap externalSubs,
                               CanType ty) {
     return KeyPathPatternComponent(identifier,
                                    getter, nullptr, indices,
-                                   indicesEquals, indicesHash, ty);
+                                   indicesEquals, indicesHash,
+                                   externalDecl, externalSubs,
+                                   ty);
   }
 
   static KeyPathPatternComponent
@@ -2549,10 +2541,14 @@
                               ArrayRef<Index> indices,
                               SILFunction *indicesEquals,
                               SILFunction *indicesHash,
+                              AbstractStorageDecl *externalDecl,
+                              SubstitutionMap externalSubs,
                               CanType ty) {
     return KeyPathPatternComponent(identifier,
                                    getter, setter, indices,
-                                   indicesEquals, indicesHash, ty);
+                                   indicesEquals, indicesHash,
+                                   externalDecl, externalSubs,
+                                   ty);
   }
   
   static KeyPathPatternComponent
@@ -2568,23 +2564,11 @@
     case Kind::StoredProperty:
     case Kind::GettableProperty:
     case Kind::SettableProperty:
-    case Kind::External:
       llvm_unreachable("not an optional kind");
     }
     return KeyPathPatternComponent(kind, ty);
   }
   
-  static KeyPathPatternComponent
-  forExternal(AbstractStorageDecl *externalDecl,
-              SubstitutionMap substitutions,
-              ArrayRef<Index> indices,
-              SILFunction *indicesEquals,
-              SILFunction *indicesHash,
-              CanType ty) {
-    return KeyPathPatternComponent(externalDecl, substitutions,
-                                   indices, indicesEquals, indicesHash, ty);
-  }
-  
   void incrementRefCounts() const;
   void decrementRefCounts() const;
   
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 9e194af..4b29be7 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
 /// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 425; // Last change: access impls
+const uint16_t VERSION_MINOR = 426; // SIL key path external components with local attempts
 
 using DeclIDField = BCFixed<31>;
 
diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp
index ebd675b..10913bf 100644
--- a/lib/IRGen/GenKeyPath.cpp
+++ b/lib/IRGen/GenKeyPath.cpp
@@ -623,8 +623,7 @@
     // External components don't need to store the key path environment (and
     // can't), since they need to already have enough information to function
     // independently of any context using the component.
-    if (genericEnv &&
-        component.getKind() != KeyPathPatternComponent::Kind::External) {
+    if (genericEnv) {
       auto destGenericEnv = dest;
       if (!component.getSubscriptIndices().empty()) {
         auto genericEnvAlignMask = llvm::ConstantInt::get(IGM.SizeTy,
@@ -703,28 +702,6 @@
     });
 };
 
-static llvm::Function *
-emitWitnessTableGeneratorForKeyPath(IRGenModule &IGM,
-                                    CanType type,
-                                    ProtocolConformanceRef conformance,
-                                    GenericEnvironment *genericEnv,
-                                    ArrayRef<GenericRequirement> requirements) {
-  // TODO: Use the standard conformance accessor when there are no arguments
-  // and the conformance accessor is defined.
-  return emitGeneratorForKeyPath(IGM, "keypath_get_witness_table", type,
-    IGM.WitnessTablePtrTy,
-    genericEnv, requirements,
-    [&](IRGenFunction &IGF, CanType substType) {
-      if (type->hasTypeParameter())
-        conformance = conformance.subst(type,
-          QueryInterfaceTypeSubstitutions(genericEnv),
-          LookUpConformanceInSignature(*genericEnv->getGenericSignature()));
-      auto ret = emitWitnessTableRef(IGF, substType, conformance);
-      IGF.Builder.CreateRet(ret);
-    });
-}
-
-
 static void
 emitKeyPathComponent(IRGenModule &IGM,
                      ConstantStructBuilder &fields,
@@ -745,75 +722,6 @@
   loweredBaseTy = IGM.getLoweredType(AbstractionPattern::getOpaque(),
                                      baseTy->getWithoutSpecifierType());
   switch (auto kind = component.getKind()) {
-  case KeyPathPatternComponent::Kind::External: {
-    fields.addInt32(KeyPathComponentHeader::forExternalComponent().getData());
-    // Emit accessors for all of the external declaration's necessary
-    // bindings.
-    SmallVector<llvm::Constant*, 4> descriptorArgs;
-    auto componentSig = component.getExternalDecl()->getInnermostDeclContext()
-      ->getGenericSignatureOfContext();
-    auto subs = component.getExternalSubstitutions();
-    enumerateGenericSignatureRequirements(
-      componentSig->getCanonicalSignature(),
-      [&](GenericRequirement reqt) {
-        auto substType = reqt.TypeParameter.subst(subs)
-          ->getCanonicalType();
-        if (!reqt.Protocol) {
-          // Type requirement.
-          descriptorArgs.push_back(
-            emitMetadataGeneratorForKeyPath(IGM, substType,
-                                            genericEnv, requirements));
-        } else {
-          // Protocol requirement.
-          auto conformance = subs.lookupConformance(
-                       reqt.TypeParameter->getCanonicalType(), reqt.Protocol);
-          descriptorArgs.push_back(
-            emitWitnessTableGeneratorForKeyPath(IGM, substType,
-                                                *conformance,
-                                                genericEnv, requirements));
-        }
-      });
-    // If instantiable in-place, pad out the argument count here to ensure
-    // there's room enough to instantiate a settable computed property
-    // with two captured words in-place. The runtime instantiation of the
-    // external component will ignore the padding, and this will make in-place
-    // instantiation more likely to avoid needing an allocation.
-    unsigned argSize = descriptorArgs.size();
-    if (isInstantiableInPlace) {
-      argSize = std::max(argSize, 3u);
-    }
-    
-    fields.addInt32(argSize);
-    fields.add(IGM.getAddrOfPropertyDescriptor(component.getExternalDecl()));
-    
-    // Add an initializer function that copies generic arguments out of the
-    // pattern argument buffer into the instantiated object, along with the
-    // index equality/hash operations we have from our perspective, or null
-    // if there are no arguments.
-    if (component.getSubscriptIndices().empty()) {
-      fields.addInt(IGM.IntPtrTy, 0);
-      fields.addInt(IGM.IntPtrTy, 0);
-      fields.addInt(IGM.IntPtrTy, 0);
-    } else {
-      fields.add(getInitializerForComputedComponent(IGM, component,
-                                                    operands,
-                                                    genericEnv,
-                                                    requirements));
-      fields.add(IGM.getAddrOfSILFunction(component.getSubscriptIndexEquals(),
-                                          NotForDefinition));
-      fields.add(IGM.getAddrOfSILFunction(component.getSubscriptIndexHash(),
-                                          NotForDefinition));
-    }
-    
-    // Add the generic arguments for the external context.
-    for (auto arg : descriptorArgs)
-      fields.add(arg);
-    
-    // Add padding.
-    for (unsigned i = descriptorArgs.size(); i < argSize; ++i)
-      fields.addInt(IGM.IntPtrTy, 0);
-    break;
-  }
   case KeyPathPatternComponent::Kind::StoredProperty: {
     auto property = cast<VarDecl>(component.getStoredPropertyDecl());
     
@@ -1162,7 +1070,6 @@
     switch (component.getKind()) {
     case KeyPathPatternComponent::Kind::GettableProperty:
     case KeyPathPatternComponent::Kind::SettableProperty:
-    case KeyPathPatternComponent::Kind::External:
       for (auto &index : component.getSubscriptIndices()) {
         operands[index.Operand].LoweredType = index.LoweredType;
         operands[index.Operand].LastUser = &component;
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index 1dfbe44..bbf8e21 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -1943,79 +1943,6 @@
     component =
       KeyPathPatternComponent::forStoredProperty(cast<VarDecl>(prop), ty);
     return false;
-  } else if (componentKind.str() == "external") {
-    ValueDecl *externalDecl;
-    SmallVector<ParsedSubstitution, 4> parsedSubs;
-    SmallVector<KeyPathPatternComponent::Index, 4> indexes;
-    CanType ty;
-
-    if (parseSILDottedPath(externalDecl)
-        || parseSubstitutions(parsedSubs, patternEnv))
-      return true;
-
-    if (P.consumeIf(tok::l_square)) {
-      if (parseComponentIndices(indexes))
-        return true;
-    }
-    
-    if (P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")
-        || P.parseToken(tok::sil_dollar,
-                        diag::expected_tok_in_sil_instr, "$")
-        || parseASTType(ty, patternEnv))
-      return true;
-
-    SILFunction *equals = nullptr;
-    SILFunction *hash = nullptr;
-
-    while (P.consumeIf(tok::comma)) {
-      Identifier subKind;
-      SourceLoc subKindLoc;
-      if (parseSILIdentifier(subKind, subKindLoc,
-                             diag::sil_keypath_expected_component_kind))
-        return true;
-
-      if (subKind.str() == "indices_equals") {
-        if (parseSILFunctionRef(InstLoc, equals))
-          return true;
-      } else if (subKind.str() == "indices_hash") {
-        if (parseSILFunctionRef(InstLoc, hash))
-          return true;
-      } else {
-        P.diagnose(subKindLoc, diag::sil_keypath_unknown_component_kind,
-                   subKind);
-        return true;
-      }
-    }
-
-    if (!indexes.empty() != (equals && hash)) {
-      P.diagnose(componentLoc,
-                 diag::sil_keypath_external_missing_part);
-      return true;
-    }
-
-    SubstitutionMap subsMap;
-    if (!parsedSubs.empty()) {
-      auto genericEnv = externalDecl->getInnermostDeclContext()
-                                    ->getGenericEnvironmentOfContext();
-      if (!genericEnv) {
-        P.diagnose(P.Tok,
-                   diag::sil_substitutions_on_non_polymorphic_type);
-        return true;
-      }
-      subsMap = getApplySubstitutionsFromParsed(*this, genericEnv, parsedSubs);
-      if (!subsMap) return true;
-
-      // Map the substitutions out of the pattern context so that they
-      // use interface types.
-      subsMap = subsMap.mapReplacementTypesOutOfContext().getCanonical();
-    }
-
-    auto indexesCopy = P.Context.AllocateCopy(indexes);
-
-    component = KeyPathPatternComponent::forExternal(
-        cast<AbstractStorageDecl>(externalDecl),
-        subsMap, indexesCopy, equals, hash, ty);
-    return false;
   } else if (componentKind.str() == "gettable_property"
              || componentKind.str() == "settable_property") {
     bool isSettable = componentKind.str()[0] == 's';
@@ -2033,6 +1960,8 @@
     SILFunction *setter = nullptr;
     SILFunction *equals = nullptr;
     SILFunction *hash = nullptr;
+    AbstractStorageDecl *externalDecl = nullptr;
+    SubstitutionMap externalSubs;
     SmallVector<KeyPathPatternComponent::Index, 4> indexes;
     while (true) {
       Identifier subKind;
@@ -2078,6 +2007,34 @@
       } else if (subKind.str() == "indices_hash") {
         if (parseSILFunctionRef(InstLoc, hash))
           return true;
+      } else if (subKind.str() == "external") {
+        ValueDecl *parsedExternalDecl;
+        SmallVector<ParsedSubstitution, 4> parsedSubs;
+
+        if (parseSILDottedPath(parsedExternalDecl)
+            || parseSubstitutions(parsedSubs, patternEnv))
+          return true;
+
+        externalDecl = cast<AbstractStorageDecl>(parsedExternalDecl);
+
+        if (!parsedSubs.empty()) {
+          auto genericEnv = externalDecl->getInnermostDeclContext()
+                                        ->getGenericEnvironmentOfContext();
+          if (!genericEnv) {
+            P.diagnose(P.Tok,
+                       diag::sil_substitutions_on_non_polymorphic_type);
+            return true;
+          }
+          externalSubs = getApplySubstitutionsFromParsed(*this, genericEnv,
+                                                         parsedSubs);
+          if (!externalSubs) return true;
+
+          // Map the substitutions out of the pattern context so that they
+          // use interface types.
+          externalSubs =
+            externalSubs.mapReplacementTypesOutOfContext().getCanonical();
+        }
+
       } else {
         P.diagnose(subKindLoc, diag::sil_keypath_unknown_component_kind,
                    subKind);
@@ -2126,11 +2083,13 @@
     if (isSettable) {
       component = KeyPathPatternComponent::forComputedSettableProperty(
                              id, getter, setter,
-                             indexesCopy, equals, hash, componentTy);
+                             indexesCopy, equals, hash,
+                             externalDecl, externalSubs, componentTy);
     } else {
       component = KeyPathPatternComponent::forComputedGettableProperty(
                              id, getter,
-                             indexesCopy, equals, hash, componentTy);
+                             indexesCopy, equals, hash,
+                             externalDecl, externalSubs, componentTy);
     }
     return false;
   } else if (componentKind.str() == "optional_wrap"
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index 3724703..4baaa31 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -2041,7 +2041,6 @@
   case Kind::OptionalChain:
   case Kind::OptionalWrap:
   case Kind::OptionalForce:
-  case Kind::External:
     llvm_unreachable("not a settable computed property");
   case Kind::SettableProperty: {
     auto setter = getComputedPropertySetter();
@@ -2059,7 +2058,6 @@
   case KeyPathPatternComponent::Kind::OptionalChain:
   case KeyPathPatternComponent::Kind::OptionalWrap:
   case KeyPathPatternComponent::Kind::OptionalForce:
-  case KeyPathPatternComponent::Kind::External:
     return;
   case KeyPathPatternComponent::Kind::SettableProperty:
     forFunction(component.getComputedPropertySetter());
@@ -2118,7 +2116,6 @@
     case KeyPathPatternComponent::Kind::OptionalForce:
       break;
     
-    case KeyPathPatternComponent::Kind::External:
     case KeyPathPatternComponent::Kind::GettableProperty:
     case KeyPathPatternComponent::Kind::SettableProperty:
       for (auto &index : component.getSubscriptIndices()) {
@@ -2196,14 +2193,7 @@
     case KeyPathPatternComponent::Kind::StoredProperty:
       ID.AddPointer(component.getStoredPropertyDecl());
       break;
-      
-    case KeyPathPatternComponent::Kind::External: {
-      ID.AddPointer(component.getExternalDecl());
-      component.getExternalSubstitutions().profile(ID);
-      profileIndices(component.getSubscriptIndices());
-      break;
-    }
-      
+            
     case KeyPathPatternComponent::Kind::SettableProperty:
       ID.AddPointer(component.getComputedPropertySetter());
       LLVM_FALLTHROUGH;
@@ -2233,6 +2223,8 @@
       }
       }
       profileIndices(component.getSubscriptIndices());
+      ID.AddPointer(component.getExternalDecl());
+      component.getExternalSubstitutions().profile(ID);
       break;
     }
   }
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 7b33dad..30ddd56 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -2132,6 +2132,16 @@
         *this << " : "
               << component.getSubscriptIndexHash()->getLoweredType();
       }
+      
+      if (auto external = component.getExternalDecl()) {
+        *this << ", external #";
+        printValueDecl(external, PrintState.OS);
+        auto subs = component.getExternalSubstitutions();
+        if (!subs.empty()) {
+          printSubstitutions(subs);
+        }
+      }
+      
       break;
     }
     case KeyPathPatternComponent::Kind::OptionalWrap:
@@ -2153,30 +2163,6 @@
       *this << component.getComponentType();
       break;
     }
-    case KeyPathPatternComponent::Kind::External: {
-      *this << "external #";
-      printValueDecl(component.getExternalDecl(), PrintState.OS);
-      if (!component.getExternalSubstitutions().empty()) {
-        printSubstitutions(component.getExternalSubstitutions());
-      }
-      
-      if (!component.getSubscriptIndices().empty()) {
-        printComponentIndices(component.getSubscriptIndices());
-      }
-      
-      *this << " : $" << component.getComponentType();
-      
-      if (!component.getSubscriptIndices().empty()) {
-        *this << ", indices_equals ";
-        component.getSubscriptIndexEquals()->printName(PrintState.OS);
-        *this << " : "
-              << component.getSubscriptIndexEquals()->getLoweredType();
-        *this << ", indices_hash ";
-        component.getSubscriptIndexHash()->printName(PrintState.OS);
-        *this << " : "
-              << component.getSubscriptIndexHash()->getLoweredType();
-      }
-    }
     }
   }
 };
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index ab1eff6..84519b1 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -344,54 +344,6 @@
     
     break;
   }
-  case KeyPathPatternComponent::Kind::External: {
-    // The component type should match the substituted type of the
-    // referenced property.
-    auto decl = component.getExternalDecl();
-    auto sig = decl->getInnermostDeclContext()
-                   ->getGenericSignatureOfContext();
-    SubstitutionMap subs;
-    CanGenericSignature canSig = nullptr;
-    if (sig) {
-      canSig = sig->getCanonicalSignature();
-      subs = component.getExternalSubstitutions();
-    }
-    auto substType = component.getExternalDecl()->getStorageInterfaceType()
-      .subst(subs);
-    require(substType->isEqual(component.getComponentType()),
-            "component type should match storage type of referenced "
-            "declaration");
-
-    // Index types should match the lowered index types expected by the
-    // external declaration.
-    if (auto sub = dyn_cast<SubscriptDecl>(decl)) {
-      auto indexParams = sub->getIndices();
-      require(indexParams->size() == component.getSubscriptIndices().size(),
-              "number of subscript indices should match referenced decl");
-      for (unsigned i : indices(*indexParams)) {
-        auto param = (*indexParams)[i];
-        auto &index = component.getSubscriptIndices()[i];
-        auto paramTy = param->getInterfaceType()->getCanonicalType();
-        auto substParamTy = paramTy.subst(subs);
-        auto loweredTy = M.Types.getLoweredType(
-          AbstractionPattern(canSig, paramTy), substParamTy);
-        require(index.LoweredType == loweredTy,
-                "index lowered types should match referenced decl");
-        require(index.FormalType == substParamTy->getCanonicalType(),
-                "index formal types should match referenced decl");
-      }
-      
-      checkIndexEqualsAndHash();
-    } else {
-      require(component.getSubscriptIndices().empty(),
-              "external var reference should not apply indices");
-      require(!component.getSubscriptIndexEquals()
-              && !component.getSubscriptIndexHash(),
-              "external var reference should not apply hash");
-    }
-    
-    break;
-  }
   case KeyPathPatternComponent::Kind::OptionalChain: {
     require(baseTy->getOptionalObjectType()->isEqual(componentTy),
             "chaining component should unwrap optional");
@@ -4222,14 +4174,6 @@
       for (auto &component : pattern->getComponents()) {
         bool hasIndices;
         switch (component.getKind()) {
-        case KeyPathPatternComponent::Kind::External:
-          if (auto subscript =
-                           dyn_cast<SubscriptDecl>(component.getExternalDecl()))
-            hasIndices = subscript->getIndices()->size() != 0;
-          else
-            hasIndices = false;
-          break;
-        
         case KeyPathPatternComponent::Kind::GettableProperty:
         case KeyPathPatternComponent::Kind::SettableProperty:
           hasIndices = !component.getSubscriptIndices().empty();
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 03453e1..cdefc3b 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -3637,10 +3637,38 @@
                                 ArrayRef<ProtocolConformanceRef> indexHashables,
                                 CanType baseTy,
                                 bool forPropertyDescriptor) {
+  /// Returns true if a key path component for the given property or
+  /// subscript should be externally referenced.
+  auto shouldUseExternalKeyPathComponent =
+    [&]() -> bool {
+      return getASTContext().LangOpts.EnableKeyPathResilience
+        && !forPropertyDescriptor
+        && storage->getModuleContext() != SwiftModule;
+    };
+  
   auto strategy = storage->getAccessStrategy(AccessSemantics::Ordinary,
                                              storage->supportsMutation()
                                                ? AccessKind::ReadWrite
-                                               : AccessKind::Read);
+                                               : AccessKind::Read,
+                                             M.getSwiftModule());
+
+  AbstractStorageDecl *externalDecl = nullptr;
+  SubstitutionMap externalSubs;
+  
+  if (shouldUseExternalKeyPathComponent()) {
+    externalDecl = storage;
+    // Map the substitutions out of context.
+    if (!subs.empty()) {
+      externalSubs = subs;
+      // If any of the substitutions involve local archetypes, then the
+      // key path pattern needs to capture the generic context, and we need
+      // to map the pattern substitutions out of this context.
+      if (externalSubs.hasArchetypes()) {
+        needsGenericContext = true;
+        externalSubs = externalSubs.mapReplacementTypesOutOfContext();
+      }
+    }
+  }
 
   if (auto var = dyn_cast<VarDecl>(storage)) {
     CanType componentTy;
@@ -3698,10 +3726,12 @@
                {},
                baseTy, componentTy);
         return KeyPathPatternComponent::forComputedSettableProperty(id,
-            getter, setter, {}, nullptr, nullptr, componentTy);
+            getter, setter, {}, nullptr, nullptr,
+            externalDecl, externalSubs, componentTy);
       } else {
         return KeyPathPatternComponent::forComputedGettableProperty(id,
-            getter, {}, nullptr, nullptr, componentTy);
+            getter, {}, nullptr, nullptr,
+            externalDecl, externalSubs, componentTy);
       }
     }
     }
@@ -3754,6 +3784,8 @@
                                                            indexPatternsCopy,
                                                            indexEquals,
                                                            indexHash,
+                                                           externalDecl,
+                                                           externalSubs,
                                                            componentTy);
     } else {
       return KeyPathPatternComponent::forComputedGettableProperty(id,
@@ -3761,6 +3793,8 @@
                                                            indexPatternsCopy,
                                                            indexEquals,
                                                            indexHash,
+                                                           externalDecl,
+                                                           externalSubs,
                                                            componentTy);
     }
   }
@@ -3810,87 +3844,28 @@
       }
     };
   
-  /// Returns true if a key path component for the given property or
-  /// subscript should be externally referenced.
-  auto shouldUseExternalKeyPathComponent =
-    [&](AbstractStorageDecl *storage) -> bool {
-      return SGF.getASTContext().LangOpts.EnableKeyPathResilience
-        && storage->getModuleContext() != SGF.SGM.SwiftModule;
-    };
-  
-  /// Build an external key path component referencing a property or subscript
-  /// from another module.
-  auto makeExternalKeyPathComponent =
-    [&](const KeyPathExpr::Component &component) -> KeyPathPatternComponent {
-      SmallVector<KeyPathPatternComponent::Index, 4> indices;
-      SubstitutionMap subMap = component.getDeclRef().getSubstitutions();
-      auto decl = cast<AbstractStorageDecl>(component.getDeclRef().getDecl());
-      auto ty = decl->getStorageInterfaceType();
-      // Map the substitutions out of context.
-      if (!subMap.empty()) {
-        // If any of the substitutions involve local archetypes, then the
-        // key path pattern needs to capture the generic context, and we need
-        // to map the pattern substitutions out of this context.
-        if (subMap.hasArchetypes()) {
-          needsGenericContext = true;
-          subMap = subMap.mapReplacementTypesOutOfContext();
-        }
-        ty = ty.subst(subMap);
-      }
-      
-      SILFunction *indexEquals = nullptr, *indexHash = nullptr;
-      if (component.getKind() ==  KeyPathExpr::Component::Kind::Subscript) {
-        unsigned numOperands = operands.size();
-        SmallVector<IndexTypePair, 4> indexTypes;
-        auto sub = cast<SubscriptDecl>(component.getDeclRef().getDecl());
-        lowerKeyPathSubscriptIndexTypes(
-                          SGF.SGM, indexTypes, sub,
-                          component.getDeclRef().getSubstitutions(),
-                          needsGenericContext);
-        lowerKeyPathSubscriptIndexPatterns(indices, indexTypes,
-             component.getSubscriptIndexHashableConformances(),
-             numOperands);
-        
-        lowerSubscriptOperands(component);
-        
-        assert(numOperands == operands.size()
-               && "operand count out of sync");
-        getOrCreateKeyPathEqualsAndHash(SGF.SGM, SILLocation(E),
-                 needsGenericContext ? SGF.F.getGenericEnvironment() : nullptr,
-                 indices,
-                 indexEquals, indexHash);
-      }
-      return KeyPathPatternComponent::forExternal(
-        decl, subMap, SGF.getASTContext().AllocateCopy(indices),
-        indexEquals, indexHash,
-        ty->getCanonicalType());
-    };
-  
+
   for (auto &component : E->getComponents()) {
     switch (auto kind = component.getKind()) {
     case KeyPathExpr::Component::Kind::Property:
     case KeyPathExpr::Component::Kind::Subscript: {
       auto decl = cast<AbstractStorageDecl>(component.getDeclRef().getDecl());
 
-      if (shouldUseExternalKeyPathComponent(decl)) {
-        loweredComponents.push_back(makeExternalKeyPathComponent(component));
-      } else {
-        unsigned numOperands = operands.size();
-        loweredComponents.push_back(
-          SGF.SGM.emitKeyPathComponentForDecl(SILLocation(E),
-                              SGF.F.getGenericEnvironment(),
-                              numOperands,
-                              needsGenericContext,
-                              component.getDeclRef().getSubstitutions(),
-                              decl,
-                              component.getSubscriptIndexHashableConformances(),
-                              baseTy,
-                              /*for descriptor*/ false));
-        lowerSubscriptOperands(component);
-      
-        assert(numOperands == operands.size()
-               && "operand count out of sync");
-      }
+      unsigned numOperands = operands.size();
+      loweredComponents.push_back(
+        SGF.SGM.emitKeyPathComponentForDecl(SILLocation(E),
+                            SGF.F.getGenericEnvironment(),
+                            numOperands,
+                            needsGenericContext,
+                            component.getDeclRef().getSubstitutions(),
+                            decl,
+                            component.getSubscriptIndexHashableConformances(),
+                            baseTy,
+                            /*for descriptor*/ false));
+      lowerSubscriptOperands(component);
+    
+      assert(numOperands == operands.size()
+             && "operand count out of sync");
       baseTy = loweredComponents.back().getComponentType();
 
       break;
diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
index 1989c32..59ccf91 100644
--- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
+++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
@@ -234,7 +234,6 @@
     case KeyPathPatternComponent::Kind::OptionalChain:
     case KeyPathPatternComponent::Kind::OptionalForce:
     case KeyPathPatternComponent::Kind::OptionalWrap:
-    case KeyPathPatternComponent::Kind::External:
       break;
     }
   }
diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp
index 3440a83..8c8d8b5 100644
--- a/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp
+++ b/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp
@@ -184,7 +184,6 @@
         break;
       case KeyPathPatternComponent::Kind::GettableProperty:
       case KeyPathPatternComponent::Kind::SettableProperty:
-      case KeyPathPatternComponent::Kind::External:
       case KeyPathPatternComponent::Kind::OptionalChain:
       case KeyPathPatternComponent::Kind::OptionalForce:
       case KeyPathPatternComponent::Kind::OptionalWrap:
diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp
index 2e3ffd6..32d393e 100644
--- a/lib/Sema/TypeCheckSwitchStmt.cpp
+++ b/lib/Sema/TypeCheckSwitchStmt.cpp
@@ -319,38 +319,6 @@
         return TypeAndVal.getInt();
       }
 
-      // Defines a "usefulness" metric that returns whether the given space
-      // contributes meaningfully to the exhaustiveness of a pattern.
-      bool isUseful() const {
-        auto subspacesUseful = [](const Space &space) {
-          for (auto &subspace : space.getSpaces()) {
-            if (!subspace.isUseful()) {
-              return false;
-            }
-          }
-          return true;
-        };
-
-        switch (getKind()) {
-        case SpaceKind::Empty:
-          return false;
-        case SpaceKind::Type:
-        case SpaceKind::BooleanConstant:
-        case SpaceKind::UnknownCase:
-          return true;
-        case SpaceKind::Disjunct:
-          if (getSpaces().empty()) {
-            return false;
-          }
-          return subspacesUseful(*this);
-        case SpaceKind::Constructor:
-          if (getSpaces().empty()) {
-            return true;
-          }
-          return subspacesUseful(*this);
-        }
-      }
-
       // An optimization that computes if the difference of this space and
       // another space is empty.
       bool isSubspace(const Space &other, TypeChecker &TC,
@@ -1178,13 +1146,14 @@
           Space projection = projectPattern(TC, caseItem.getPattern(),
                                             sawDowngradablePattern);
 
-          if (projection.isUseful()
-                && projection.isSubspace(Space::forDisjunct(spaces), TC, DC)) {
+          if (!projection.isEmpty() &&
+              projection.isSubspace(Space::forDisjunct(spaces), TC, DC)) {
             sawRedundantPattern |= true;
 
             TC.diagnose(caseItem.getStartLoc(),
                           diag::redundant_particular_case)
               .highlight(caseItem.getSourceRange());
+            continue;
           } else {
             Expr *cachedExpr = nullptr;
             if (checkRedundantLiteral(caseItem.getPattern(), cachedExpr)) {
@@ -1195,6 +1164,7 @@
               TC.diagnose(cachedExpr->getLoc(),
                           diag::redundant_particular_literal_case_here)
                 .highlight(cachedExpr->getSourceRange());
+              continue;
             }
           }
           spaces.push_back(projection);
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 7a689f2..1b6a62f 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -838,8 +838,15 @@
   ArrayRef<KeyPathPatternComponent::Index> indices;
   SILFunction *indicesEquals = nullptr;
   SILFunction *indicesHash = nullptr;
+  AbstractStorageDecl *externalDecl = nullptr;
+  SubstitutionMap externalSubs;
 
-  auto handleComputedIndices = [&] {
+  auto handleComputedExternalReferenceAndIndices = [&] {
+    auto externalDeclID = ListOfValues[nextValue++];
+    externalDecl =
+      cast_or_null<AbstractStorageDecl>(MF->getDecl(externalDeclID));
+    externalSubs = MF->getSubstitutionMap(ListOfValues[nextValue++]);
+    
     SmallVector<KeyPathPatternComponent::Index, 4> indicesBuf;
     auto numIndexes = ListOfValues[nextValue++];
     indicesBuf.reserve(numIndexes);
@@ -874,9 +881,10 @@
     auto id = handleComputedId();
     auto getterName = MF->getIdentifier(ListOfValues[nextValue++]);
     auto getter = getFuncForReference(getterName.str());
-    handleComputedIndices();
+    handleComputedExternalReferenceAndIndices();
     return KeyPathPatternComponent::forComputedGettableProperty(
-        id, getter, indices, indicesEquals, indicesHash, type);
+        id, getter, indices, indicesEquals, indicesHash,
+        externalDecl, externalSubs, type);
   }
   case KeyPathComponentKindEncoding::SettableProperty: {
     auto id = handleComputedId();
@@ -884,9 +892,10 @@
     auto getter = getFuncForReference(getterName.str());
     auto setterName = MF->getIdentifier(ListOfValues[nextValue++]);
     auto setter = getFuncForReference(setterName.str());
-    handleComputedIndices();
+    handleComputedExternalReferenceAndIndices();
     return KeyPathPatternComponent::forComputedSettableProperty(
-        id, getter, setter, indices, indicesEquals, indicesHash, type);
+        id, getter, setter, indices, indicesEquals, indicesHash,
+        externalDecl, externalSubs, type);
     break;
   }
   case KeyPathComponentKindEncoding::OptionalChain:
@@ -898,15 +907,6 @@
   case KeyPathComponentKindEncoding::OptionalWrap:
     return KeyPathPatternComponent::forOptional(
         KeyPathPatternComponent::Kind::OptionalWrap, type);
-  case KeyPathComponentKindEncoding::External: {
-    auto declID = ListOfValues[nextValue++];
-    auto decl = cast<AbstractStorageDecl>(MF->getDecl(declID));
-    auto subMap = MF->getSubstitutionMap(ListOfValues[nextValue++]);
-    handleComputedIndices();
-    return KeyPathPatternComponent::forExternal(decl, subMap, indices,
-                                                indicesEquals, indicesHash,
-                                                type);
-  }
   case KeyPathComponentKindEncoding::Trivial:
     llvm_unreachable("handled above");
   }
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index 7f5f9ce..537c242 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -84,7 +84,6 @@
   OptionalChain,
   OptionalForce,
   OptionalWrap,
-  External,
   Trivial,
 };
 enum class KeyPathComputedComponentIdKindEncoding : uint8_t {
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index e61b3f9..c238d3b 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -624,8 +624,12 @@
       break;
     }
   };
-  auto handleComputedIndices
+  auto handleComputedExternalReferenceAndIndices
     = [&](const KeyPathPatternComponent &component) {
+      ListOfValues.push_back(S.addDeclRef(component.getExternalDecl()));
+      ListOfValues.push_back(
+        S.addSubstitutionMapRef(component.getExternalSubstitutions()));
+  
       auto indices = component.getSubscriptIndices();
       ListOfValues.push_back(indices.size());
       for (auto &index : indices) {
@@ -654,7 +658,7 @@
     handleComputedId(component.getComputedPropertyId());
     ListOfValues.push_back(
                   addSILFunctionRef(component.getComputedPropertyGetter()));
-    handleComputedIndices(component);
+    handleComputedExternalReferenceAndIndices(component);
     break;
   case KeyPathPatternComponent::Kind::SettableProperty:
     handleComponentCommon(KeyPathComponentKindEncoding::SettableProperty);
@@ -663,7 +667,7 @@
                   addSILFunctionRef(component.getComputedPropertyGetter()));
     ListOfValues.push_back(
                   addSILFunctionRef(component.getComputedPropertySetter()));
-    handleComputedIndices(component);
+    handleComputedExternalReferenceAndIndices(component);
     break;
   case KeyPathPatternComponent::Kind::OptionalChain:
     handleComponentCommon(KeyPathComponentKindEncoding::OptionalChain);
@@ -674,13 +678,6 @@
   case KeyPathPatternComponent::Kind::OptionalWrap:
     handleComponentCommon(KeyPathComponentKindEncoding::OptionalWrap);
     break;
-  case KeyPathPatternComponent::Kind::External:
-    handleComponentCommon(KeyPathComponentKindEncoding::External);
-    ListOfValues.push_back(S.addDeclRef(component.getExternalDecl()));
-    ListOfValues.push_back(
-      S.addSubstitutionMapRef(component.getExternalSubstitutions()));
-    handleComputedIndices(component);
-    break;
   }
 }
 
diff --git a/test/Constraints/tuple-arguments-supported.swift b/test/Constraints/tuple-arguments-supported.swift
new file mode 100644
index 0000000..42da669
--- /dev/null
+++ b/test/Constraints/tuple-arguments-supported.swift
@@ -0,0 +1,48 @@
+// RUN: %target-typecheck-verify-swift
+
+func test1(_: ()) {}
+test1(())
+func test2() {}
+test2()
+
+func test4(_: (Int, Int) -> ()) {}
+test4({ (x,y) in })
+func test5(_: (Int, Int, Int) -> ()) {}
+test5({ (x,y,z) in })
+
+func test6(_: ((Int, Int)) -> ()) {}
+test6({ (x,y) in })
+func test7(_: ((Int, Int, Int)) -> ()) {}
+test7({ (x,y,z) in })
+test6({ (_ x, _ y) in })
+test6({ (_, _) in })
+test6({ (x:Int, y:Int) in })
+test6({ (_, _) ->() in })
+
+func test8(_: ((Int, Int)) -> Int) {}
+test8 { (_, _) -> Int in 2 }
+test8 { (x, y) in x }
+
+func isEven(_ x: Int) -> Bool { return x % 2 == 0 }
+let items = Array(zip(0..<10, 0..<10))
+_ = items.filter { (_, x) in isEven(x) }
+_ = items.filter { _ in true }
+
+func toString(indexes: Int?...) -> String {
+  let _ = indexes.enumerated().map({ (i: Int, index: Int?) -> String? in
+    let _: Int = i
+    if index != nil {}
+    return ""
+  })
+  let _ = [(1, 2)].contains { $0 != $1 }
+  _ = ["Hello" : 2].map { ($0, ($1)) }
+}
+
+extension Dictionary {
+  public mutating func merge(with dictionary: Dictionary) {
+    dictionary.forEach { updateValue($1, forKey: $0) }
+  }
+}
+
+let dictionary: [String: String] = [:]
+_ = dictionary.first { (column, value) in true }!.value
diff --git a/test/Constraints/tuple-arguments-unsupported.swift b/test/Constraints/tuple-arguments-unsupported.swift
new file mode 100644
index 0000000..5994829
--- /dev/null
+++ b/test/Constraints/tuple-arguments-unsupported.swift
@@ -0,0 +1,25 @@
+// RUN: %target-typecheck-verify-swift
+
+func test1(_: ()) {} // expected-note {{'test1' declared here}}
+test1() // expected-error {{missing argument for parameter #1 in call}}
+
+enum Result<T> {
+  case success(T) // expected-note {{'success' declared here}}
+}
+func test3(_: Result<()>) {}
+test3(.success()) // expected-error {{missing argument for parameter #1 in call}}
+
+func toString(indexes: Int?...) -> String {
+  let _ = indexes.reduce(0) { print($0); return $0.0 + ($0.1 ?? 0)}
+  // expected-error@-1 {{contextual closure type '(_, Int?) throws -> _' expects 2 arguments, but 1 was used in closure body}}
+  let _ = indexes.reduce(0) { (true ? $0 : (1, 2)).0 + ($0.1 ?? 0) }
+  // expected-error@-1 {{contextual closure type '(_, Int?) throws -> _' expects 2 arguments, but 1 was used in closure body}}
+  _ = ["Hello", "Foo"].sorted { print($0); return $0.0.count > ($0).1.count }
+  // expected-error@-1 {{argument passed to call that takes no arguments}}
+}
+
+func doit(_ x: Int) -> Bool { return x > 0 }
+let _: ((String, Int)) -> [String:Bool] = { [$0: doit($1)] }
+// expected-error@-1 {{closure tuple parameter '(String, Int)' does not support destructuring with implicit parameters}}
+func returnClosure() -> ((Int, Int)) -> Bool { return {$1 > $0} }
+// expected-error@-1 {{closure tuple parameter '(Int, Int)' does not support destructuring with implicit parameters}}
diff --git a/test/IDE/complete_func_reference.swift b/test/IDE/complete_func_reference.swift
index 94fdfa6..9d0005d 100644
--- a/test/IDE/complete_func_reference.swift
+++ b/test/IDE/complete_func_reference.swift
@@ -1,24 +1,24 @@
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=VOID_VOID_0 | %FileCheck %s -check-prefix=VOID_VOID
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=VOID_VOID_1 | %FileCheck %s -check-prefix=VOID_VOID
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=VOID_VOID_2 | %FileCheck %s -check-prefix=VOID_VOID
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=VOID_VOID_3 | %FileCheck %s -check-prefix=VOID_VOID
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=VOID_VOID_4 | %FileCheck %s -check-prefix=VOID_VOID
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=ANY_INT_0 | %FileCheck %s -check-prefix=ANY_INT
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=ANY_INT_1 | %FileCheck %s -check-prefix=ANY_INT
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=ANY_INT_2 > %t.results
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_0 | %FileCheck %s -check-prefix=VOID_VOID
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_1 | %FileCheck %s -check-prefix=VOID_VOID
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_2 | %FileCheck %s -check-prefix=VOID_VOID
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_3 | %FileCheck %s -check-prefix=VOID_VOID
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_VOID_4 | %FileCheck %s -check-prefix=VOID_VOID
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_INT_0 | %FileCheck %s -check-prefix=ANY_INT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_INT_1 | %FileCheck %s -check-prefix=ANY_INT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_INT_2 > %t.results
 // RUN:%FileCheck %s -check-prefix=ANY_INT < %t.results
 // RUN:%FileCheck %s -check-prefix=ANY_INT_STATIC_CURRY < %t.results
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=ANY_INT_3 | %FileCheck %s -check-prefix=ANY_INT
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=ANY_INT_4 | %FileCheck %s -check-prefix=ANY_INT
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=INT_ANY_0 | %FileCheck %s -check-prefix=INT_ANY
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=INT_ANY_1 | %FileCheck %s -check-prefix=INT_ANY
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=INT_ANY_2 > %t.results
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_INT_3 | %FileCheck %s -check-prefix=ANY_INT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=ANY_INT_4 | %FileCheck %s -check-prefix=ANY_INT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INT_ANY_0 | %FileCheck %s -check-prefix=INT_ANY
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INT_ANY_1 | %FileCheck %s -check-prefix=INT_ANY
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INT_ANY_2 > %t.results
 // RUN: %FileCheck %s -check-prefix=INT_ANY < %t.results
 // RUN: %FileCheck %s -check-prefix=INT_ANY_STATIC_CURRY < %t.results
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=INT_ANY_3 > %t.results
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_0 | %FileCheck %s -check-prefix=VOID_INT_INT
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_1 | %FileCheck %s -check-prefix=VOID_INT_INT
-// RUN: %target-swift-ide-test -swift-version 3 -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_2 | %FileCheck %s -check-prefix=VOID_INT_INT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INT_ANY_3 > %t.results
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_0 | %FileCheck %s -check-prefix=VOID_INT_INT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_1 | %FileCheck %s -check-prefix=VOID_INT_INT
+// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=VOID_INT_INT_2 | %FileCheck %s -check-prefix=VOID_INT_INT
 
 func voidToVoid() {}
 func voidToInt() -> Int {}
@@ -122,7 +122,7 @@
 }
 
 // ANY_INT: Begin completions
-// ANY_INT-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToInt(a:);
+// ANY_INT-DAG: Decl{{.*}}:      anyToInt({#a: Any#})[#Int#]; name=anyToInt(a: Any)
 // ANY_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: intToVoid({#a: Int#})[#Void#];
 // ANY_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: anyToVoid({#a: Any#})[#Void#];
 // ANY_INT-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: voidToVoid()[#Void#];
@@ -135,7 +135,7 @@
 // ANY_INT: End completions
 
 // ANY_INT_STATIC_CURRY: Begin completions
-// ANY_INT_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: anyToInt({#self: S0#})[#(a: Any) -> Int#];
+// ANY_INT_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal:   anyToInt({#self: S0#})[#(a: Any) -> Int#]; name=anyToInt(S0)
 // ANY_INT_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: voidToVoid({#self: S0#})[#() -> Void#];
 // ANY_INT_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: intToVoid({#self: S0#})[#(a: Int) -> Void#];
 // ANY_INT_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: anyToVoid({#self: S0#})[#(a: Any) -> Void#];
@@ -153,12 +153,12 @@
 }
 
 // INT_ANY: Begin completions
-// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: intToAny(a:);
-// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: intToInt(a:);
-// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: intToVoid(a:);
-// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToAny(a:);
-// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToInt(a:);
-// INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: anyToVoid(a:);
+// INT_ANY-DAG: Decl{{.*}}:      intToAny({#a: Int#})[#Any#]; name=intToAny(a: Int)
+// INT_ANY-DAG: Decl{{.*}}:      intToInt({#a: Int#})[#Int#]; name=intToInt(a: Int)
+// INT_ANY-DAG: Decl{{.*}}:      intToVoid({#a: Int#})[#Void#]; name=intToVoid(a: Int)
+// INT_ANY-DAG: Decl{{.*}}:      anyToAny({#a: Any#})[#Any#]; name=anyToAny(a: Any)
+// INT_ANY-DAG: Decl{{.*}}:      anyToInt({#a: Any#})[#Int#]; name=anyToInt(a: Any)
+// INT_ANY-DAG: Decl{{.*}}:      anyToVoid({#a: Any#})[#Void#]; name=anyToVoid(a: Any)
 // INT_ANY-DAG: Decl{{.*}}/TypeRelation[Convertible]: returnsIntToInt()[#(Int) -> Int#];
 // INT_ANY-DAG: Decl{{.*}}/NotRecommended/TypeRelation[Invalid]: voidToVoid()[#Void#];
 // INT_ANY-DAG: Decl{{.*}}:      voidToInt()[#Int#];
@@ -166,12 +166,12 @@
 // INT_ANY: End completions
 
 // INT_ANY_STATIC_CURRY: Begin completions
-// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: intToInt({#self: S0#})[#(a: Int) -> Int#];
-// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: intToVoid({#self: S0#})[#(a: Int) -> Void#];
-// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: anyToAny({#self: S0#})[#(a: Any) -> Any#];
-// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: anyToVoid({#self: S0#})[#(a: Any) -> Void#];
-// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: intToAny({#self: S0#})[#(a: Int) -> Any#];
-// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: anyToInt({#self: S0#})[#(a: Any) -> Int#];
+// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal:   intToInt({#self: S0#})[#(a: Int) -> Int#]; name=intToInt(S0)
+// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: intToVoid({#self: S0#})[#(a: Int) -> Void#]; name=intToVoid(S0)
+// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal:   anyToAny({#self: S0#})[#(a: Any) -> Any#]; name=anyToAny(S0)
+// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/NotRecommended/TypeRelation[Invalid]: anyToVoid({#self: S0#})[#(a: Any) -> Void#]; name=anyToVoid(S0)
+// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal:   intToAny({#self: S0#})[#(a: Int) -> Any#]; name=intToAny(S0)
+// INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal:   anyToInt({#self: S0#})[#(a: Any) -> Int#]; name=anyToInt(S0)
 // INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Convertible]: returnsIntToInt({#self: S0#})[#() -> (Int) -> Int#];
 // INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal:   voidToAny({#self: S0#})[#() -> Any#];
 // INT_ANY_STATIC_CURRY-DAG: Decl[InstanceMethod]/CurrNominal:   voidToInt({#self: S0#})[#() -> Int#];
diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil
index c35019c..dc0260f 100644
--- a/test/IRGen/keypaths.sil
+++ b/test/IRGen/keypaths.sil
@@ -410,33 +410,6 @@
   return undef : $()
 }
 
-sil @generic_external : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed A, @in_guaranteed B, @in_guaranteed A, @in_guaranteed B, @in_guaranteed A, @in_guaranteed B) -> () {
-entry(%0 : $*A, %1 : $*B, %2 : $*A, %3 : $*B, %4 : $*A, %5 : $*B):
-  %t = keypath $KeyPath<G<B>, B>, <Z> (
-    root $G<Z>;
-    external #G.x<Z> : $Z
-  ) <B>
-
-  %u = keypath $KeyPath<G<A>, A>, <X: Hashable, Y: Hashable> (
-    root $G<Y>;
-    external #G.subscript<Y, X> [%$0 : $X : $*X] : $Y,
-      indices_equals @s_equals : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
-      indices_hash @s_hash : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer) -> Int
-  ) <B, A> (%1)
-
-  %v = keypath $KeyPath<G<G<B>>, B>, <X: Hashable, Y: Hashable> (
-    root $G<G<X>>;
-    external #G.subscript<G<X>, Y> [%$1 : $Y : $*Y] : $G<X>,
-      indices_equals @s_equals : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
-      indices_hash @s_hash : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer) -> Int;
-    external #G.subscript<X, X> [%$0 : $X : $*X] : $X,
-      indices_equals @s_equals : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
-      indices_hash @s_hash : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer) -> Int
-  ) <B, A> (%3, %4)
-
-  return undef : $()
-}
-
 sil @s_get : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed A, UnsafeRawPointer) -> @out B
 sil @s_set : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed B, @in_guaranteed A, UnsafeRawPointer) -> ()
 sil @s_equals : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool
diff --git a/test/IRGen/type_layout_reference_storage.swift b/test/IRGen/type_layout_reference_storage.swift
index 2305cdf..ef53e24 100644
--- a/test/IRGen/type_layout_reference_storage.swift
+++ b/test/IRGen/type_layout_reference_storage.swift
@@ -41,43 +41,43 @@
   // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_[[REF_XI]]_bt, i32 0, i32 0)
   // CHECK-objc-64:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff, i32 0, i32 0)
   // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_[[REF_XI]]_bt, i32 0, i32 0)
-  // CHECK-objc-32:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_7fffffff, i32 0, i32 0)
+  // CHECK-objc-32:   store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_8_4_[[REF_XI32:[0-9a-f]+]], i32 0, i32 0)
   unowned(safe)   var ps:  P
   // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff, i32 0, i32 0)
-  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_7fffffff, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_8_4_[[REF_XI32_2:[0-9a-f]+]], i32 0, i32 0)
   weak            var pwo: P?
   // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_16_8_7fffffff, i32 0, i32 0)
-  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_8_4_7fffffff, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_8_4_[[REF_XI32_2]], i32 0, i32 0)
   weak            var pwi: P!
 
   // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_[[REF_XI]]_bt, i32 0, i32 0)
   // CHECK-objc-64:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
   // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_[[REF_XI]]_bt, i32 0, i32 0)
-  // CHECK-objc-32:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+  // CHECK-objc-32:   store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_12_4_[[REF_XI32]], i32 0, i32 0)
   unowned(safe)   var pqs:  P & Q
   // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_[[REF_XI]]_pod, i32 0, i32 0)
   // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_[[REF_XI]]_pod, i32 0, i32 0)
   unowned(unsafe) var pqu:  P & Q
   // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
-  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_12_4_[[REF_XI32_2]], i32 0, i32 0)
   weak            var pqwo: (P & Q)?
   // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
-  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_12_4_[[REF_XI32_2]], i32 0, i32 0)
   weak            var pqwi: (P & Q)!
 
   // CHECK-native-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_[[REF_XI]]_bt, i32 0, i32 0)
   // CHECK-objc-64:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff_bt, i32 0, i32 0)
   // CHECK-native-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_[[REF_XI]]_bt, i32 0, i32 0)
-  // CHECK-objc-32:   store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff_bt, i32 0, i32 0)
+  // CHECK-objc-32:   store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_12_4_[[REF_XI32]]_bt, i32 0, i32 0)
   unowned(safe)   var pqcs:  P & Q & C
   // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_[[REF_XI]]_pod, i32 0, i32 0)
-  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_[[REF_XI]]_pod, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_12_4_[[REF_XI]]_pod, i32 0, i32 0)
   unowned(unsafe) var pqcu:  P & Q & C
   // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
-  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_12_4_[[REF_XI32_2]], i32 0, i32 0)
   weak            var pqcwo: (P & Q & C)?
   // CHECK-64: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_24_8_7fffffff, i32 0, i32 0)
-  // CHECK-32: store i8** getelementptr inbounds ([4 x i8*], [4 x i8*]* @type_layout_12_4_7fffffff, i32 0, i32 0)
+  // CHECK-32: store i8** getelementptr inbounds ([{{(3|4)}} x i8*], [{{(3|4)}} x i8*]* @type_layout_12_4_[[REF_XI32_2]], i32 0, i32 0)
   weak            var pqcwi: (P & Q & C)!
 
   // -- Unknown-refcounted existential without witness tables.
diff --git a/test/Interpreter/currying_generics.swift b/test/Interpreter/currying_generics.swift
index 850856b..a38aec3 100644
--- a/test/Interpreter/currying_generics.swift
+++ b/test/Interpreter/currying_generics.swift
@@ -1,4 +1,4 @@
-// RUN: %target-run-simple-swift-swift3 | %FileCheck %s
+// RUN: %target-run-simple-swift | %FileCheck %s
 // REQUIRES: executable_test
 
 func curry<T, U, V>(_ f: @escaping (T, U) -> V) -> (T) -> (U) -> V {
@@ -120,8 +120,8 @@
 
 let a : Int? = 23
 let b : Int? = 42
-print((b <+> pair)(a!)) // CHECK-NEXT: (42, 23)
-print((b <+> pair_)(a!)) // CHECK-NEXT: (42, 23)
+print((b <+> pair)(a!) as Any) // CHECK-NEXT: (42, 23)
+print((b <+> pair_)(a!) as Any) // CHECK-NEXT: (42, 23)
 
 //
 // rdar://problem/20475584
@@ -172,12 +172,12 @@
 	return { x in { y in over(lens)(const(x))(y) } }
 }
 
-func _1<A, B, C, D>(_ f: @escaping (A) -> C) -> (A, B) -> (@escaping (@escaping (A) -> (A, B)) -> (C) -> D) -> D {
-	return { (x, y) in { fmap in fmap({ ($0, y) })(f(x)) } }
+func _1<A, B, C, D>(_ f: @escaping (A) -> C) -> ((A, B)) -> (@escaping (@escaping (A) -> (A, B)) -> (C) -> D) -> D {
+	return { pair in { fmap in fmap({ ($0, pair.1) })(f(pair.0)) } }
 }
 
-func _2<A, B, C, D>(_ f: @escaping (B) -> C) -> (A, B) -> (@escaping (@escaping (B) -> (A, B)) -> (C) -> D) -> D {
-    return { (x, y) in { fmap in fmap({ (x, $0) })(f(y)) } }
+func _2<A, B, C, D>(_ f: @escaping (B) -> C) -> ((A, B)) -> (@escaping (@escaping (B) -> (A, B)) -> (C) -> D) -> D {
+    return { pair in { fmap in fmap({ (pair.0, $0) })(f(pair.1)) } }
 }
 
 
@@ -199,6 +199,6 @@
 print(pt2) // CHECK-NEXT: (4, 2)
 let pt3 = set(_1)(3)((1, 2))
 print(pt3) // CHECK-NEXT: (3, 2)
-let pt4 = view(_2)("hello", 5)
+let pt4 = view(_2)(("hello", 5))
 print(pt4) // CHECK-NEXT: 5
 
diff --git a/test/Migrator/Inputs/ignore_type_placeholder.swift b/test/Migrator/Inputs/ignore_type_placeholder.swift
deleted file mode 100644
index 26908f3..0000000
--- a/test/Migrator/Inputs/ignore_type_placeholder.swift
+++ /dev/null
@@ -1,3 +0,0 @@
-func foo(f: (Void) -> ()) {
-  f()
-}
diff --git a/test/Migrator/fixit_void.swift b/test/Migrator/fixit_void.swift
deleted file mode 100644
index 31aaec9..0000000
--- a/test/Migrator/fixit_void.swift
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %target-swift-frontend -typecheck %s -swift-version 3
-// RUN: %target-swift-frontend -typecheck -update-code -primary-file %s -emit-migrated-file-path %t.result -swift-version 3
-// RUN: diff -u %s.expected %t.result
-// RUN: %target-swift-frontend -typecheck %s.expected -swift-version 4
-
-func takesNothing(_ f: () -> ()) {
-  f()
-  f(())
-}
-
-func takesVoidFunction(_ f: (Void) -> ()) {
-  f()
-  f(())
-}
-
-takesNothing { print("Hello") }
-takesVoidFunction { print("Hello") }
diff --git a/test/Migrator/fixit_void.swift.expected b/test/Migrator/fixit_void.swift.expected
deleted file mode 100644
index 4c978d6..0000000
--- a/test/Migrator/fixit_void.swift.expected
+++ /dev/null
@@ -1,17 +0,0 @@
-// RUN: %target-swift-frontend -typecheck %s -swift-version 3
-// RUN: %target-swift-frontend -typecheck -update-code -primary-file %s -emit-migrated-file-path %t.result -swift-version 3
-// RUN: diff -u %s.expected %t.result
-// RUN: %target-swift-frontend -typecheck %s.expected -swift-version 4
-
-func takesNothing(_ f: () -> ()) {
-  f()
-  f()
-}
-
-func takesVoidFunction(_ f: () -> ()) {
-  f()
-  f()
-}
-
-takesNothing { print("Hello") }
-takesVoidFunction { print("Hello") }
diff --git a/test/Migrator/ignore_type_placeholder.swift b/test/Migrator/ignore_type_placeholder.swift
deleted file mode 100644
index e6c06cd..0000000
--- a/test/Migrator/ignore_type_placeholder.swift
+++ /dev/null
@@ -1,3 +0,0 @@
-// RUN: %empty-directory(%t) && %target-swift-frontend -c -primary-file %S/Inputs/ignore_type_placeholder.swift -emit-migrated-file-path %t/ignore_type_placeholder.swift.result -emit-remap-file-path %t/ignore_type_placeholder.swift.remap -swift-version 3
-// RUN: %FileCheck %s < %t/ignore_type_placeholder.swift.result
-// CHECK-NOT: f(<#Void#>)
diff --git a/test/Migrator/tuple-arguments.swift b/test/Migrator/tuple-arguments.swift
deleted file mode 100644
index 4684b7c..0000000
--- a/test/Migrator/tuple-arguments.swift
+++ /dev/null
@@ -1,65 +0,0 @@
-// RUN: %target-swift-frontend -typecheck %s -swift-version 3
-// RUN: %target-swift-frontend -typecheck -update-code -primary-file %s -emit-migrated-file-path %t.result -disable-migrator-fixits -swift-version 3
-// RUN: diff -u %s.expected %t.result
-// RUN: %target-swift-frontend -typecheck %s.expected -swift-version 4
-
-func test1(_: ()) {}
-test1(())
-test1()
-func test2() {}
-test2()
-
-enum Result<T> {
-	case success(T)
-}
-func test3(_: Result<()>) {}
-test3(.success())
-
-func test4(_: (Int, Int) -> ()) {}
-test4({ (x,y) in })
-func test5(_: (Int, Int, Int) -> ()) {}
-test5({ (x,y,z) in })
-
-func test6(_: ((Int, Int)) -> ()) {}
-test6({ (x,y) in })
-func test7(_: ((Int, Int, Int)) -> ()) {}
-test7({ (x,y,z) in })
-test6({ (_ x, _ y) in })
-test6({ (_, _) in })
-test6({ (x:Int, y:Int) in })
-test6({ (_, _) ->() in })
-
-func test8(_: ((Int, Int)) -> Int) {}
-test8 { (_, _) -> Int in 2 }
-test8 { (x, y) in x }
-
-func isEven(_ x: Int) -> Bool { return x % 2 == 0 }
-let items = Array(zip(0..<10, 0..<10))
-_ = items.filter { (_, x) in isEven(x) }
-_ = items.filter { _ in true }
-
-func toString(indexes: Int?...) -> String {
-  let _ = indexes.enumerated().map({ (i: Int, index: Int?) -> String? in
-    let _: Int = i
-    if index != nil {}
-    return ""
-  })
-  let _ = indexes.reduce(0) { print($0); return $0.0 + ($0.1 ?? 0)}
-  let _ = indexes.reduce(0) { (true ? $0 : (1, 2)).0 + ($0.1 ?? 0) }
-  let _ = [(1, 2)].contains { $0 != $1 }
-  _ = ["Hello", "Foo"].sorted { print($0); return $0.0.count > ($0).1.count }
-  _ = ["Hello" : 2].map { ($0, ($1)) }
-}
-
-extension Dictionary {
-  public mutating func merge(with dictionary: Dictionary) {
-    dictionary.forEach { updateValue($1, forKey: $0) }
-  }
-}
-
-let dictionary: [String: String] = [:]
-_ = dictionary.first { (column, value) in true }!.value
-
-func doit(_ x: Int) -> Bool { return x > 0 }
-let _: ((String, Int)) -> [String:Bool] = { [$0: doit($1)] }
-func returnClosure() -> ((Int, Int)) -> Bool { return {$1 > $0} }
diff --git a/test/Migrator/tuple-arguments.swift.expected b/test/Migrator/tuple-arguments.swift.expected
deleted file mode 100644
index 800d990..0000000
--- a/test/Migrator/tuple-arguments.swift.expected
+++ /dev/null
@@ -1,65 +0,0 @@
-// RUN: %target-swift-frontend -typecheck %s -swift-version 3
-// RUN: %target-swift-frontend -typecheck -update-code -primary-file %s -emit-migrated-file-path %t.result -disable-migrator-fixits -swift-version 3
-// RUN: diff -u %s.expected %t.result
-// RUN: %target-swift-frontend -typecheck %s.expected -swift-version 4
-
-func test1(_: ()) {}
-test1(())
-test1(())
-func test2() {}
-test2()
-
-enum Result<T> {
-	case success(T)
-}
-func test3(_: Result<()>) {}
-test3(.success(()))
-
-func test4(_: (Int, Int) -> ()) {}
-test4({ (x,y) in })
-func test5(_: (Int, Int, Int) -> ()) {}
-test5({ (x,y,z) in })
-
-func test6(_: ((Int, Int)) -> ()) {}
-test6({ (x,y) in })
-func test7(_: ((Int, Int, Int)) -> ()) {}
-test7({ (x,y,z) in })
-test6({ (_ x, _ y) in })
-test6({ (_, _) in })
-test6({ (x:Int, y:Int) in })
-test6({ (_, _) ->() in })
-
-func test8(_: ((Int, Int)) -> Int) {}
-test8 { (_, _) -> Int in 2 }
-test8 { (x, y) in x }
-
-func isEven(_ x: Int) -> Bool { return x % 2 == 0 }
-let items = Array(zip(0..<10, 0..<10))
-_ = items.filter { (_, x) in isEven(x) }
-_ = items.filter { _ in true }
-
-func toString(indexes: Int?...) -> String {
-  let _ = indexes.enumerated().map({ (i: Int, index: Int?) -> String? in
-    let _: Int = i
-    if index != nil {}
-    return ""
-  })
-  let _ = indexes.reduce(0) { print(($0, $1)); return $0 + ($1 ?? 0)}
-  let _ = indexes.reduce(0) { (true ? ($0, $1) : (1, 2)).0 + ($1 ?? 0) }
-  let _ = [(1, 2)].contains { $0 != $1 }
-  _ = ["Hello", "Foo"].sorted { print(($0, $1)); return $0.count > $1.count }
-  _ = ["Hello" : 2].map { ($0, ($1)) }
-}
-
-extension Dictionary {
-  public mutating func merge(with dictionary: Dictionary) {
-    dictionary.forEach { updateValue($1, forKey: $0) }
-  }
-}
-
-let dictionary: [String: String] = [:]
-_ = dictionary.first { (column, value) in true }!.value
-
-func doit(_ x: Int) -> Bool { return x > 0 }
-let _: ((String, Int)) -> [String:Bool] = { [$0.0: doit($0.1)] }
-func returnClosure() -> ((Int, Int)) -> Bool { return {$0.1 > $0.0} }
diff --git a/test/Prototypes/Result.swift b/test/Prototypes/Result.swift
index 0eb320b..320e1ee 100644
--- a/test/Prototypes/Result.swift
+++ b/test/Prototypes/Result.swift
@@ -9,7 +9,7 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
 //===----------------------------------------------------------------------===//
-// RUN: %target-run-stdlib-swift-swift3
+// RUN: %target-run-stdlib-swift
 // REQUIRES: executable_test
 
 public enum Result<Value> {
@@ -138,8 +138,8 @@
 print(catchResult { try mayFail(true) })
 print(catchResult { try mayFail(false) })
 
-print(catchResult { _ in 1 }.flatMap { _ in Result(success: 4) }.flatMap { _ in Result<String>(error: Icky.Poor) })
-print(catchResult { _ in 1 }.map { _ in three }.flatMap {$0} )
+print(catchResult { 1 }.flatMap { _ in Result(success: 4) }.flatMap { _ in Result<String>(error: Icky.Poor) })
+print(catchResult { 1 }.map { _ in three }.flatMap {$0} )
 
 let results = [three, nasty, four]
 print(results.flatMap { $0.success })
diff --git a/test/SIL/Parser/keypath.sil b/test/SIL/Parser/keypath.sil
index 4f6981f..3642187 100644
--- a/test/SIL/Parser/keypath.sil
+++ b/test/SIL/Parser/keypath.sil
@@ -144,28 +144,10 @@
 }
 
 // CHECK-LABEL: sil @external
-sil @external : $@convention(thin) <A, B: Hashable> (@in_guaranteed B) -> () {
-entry(%z : $*B):
-  // CHECK: %1 = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
-  %a = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
-
-  // CHECK: %2 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1, τ_0_2> (root $External<τ_0_2>; external #External.ro<τ_0_2> : $τ_0_2) <A, A, A>
-  %b = keypath $KeyPath<External<A>, A>, <C, D, E> (root $External<E>; external #External.ro <E> : $E) <A, A, A>
-
-  // CHECK: %3 = keypath $KeyPath<External<Int>, Int>, <τ_0_0> (root $External<τ_0_0>; external #External.ro<τ_0_0> : $τ_0_0) <Int>
-  %c = keypath $KeyPath<External<Int>, Int>, <F> (root $External<F>; external #External.ro <F> : $F) <Int>
-
-  // CHECK: %4 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (
-  // CHECK-SAME: root $External<τ_0_1>;
-  // CHECK-SAME: external #External.subscript<τ_0_1, τ_0_0>[%$0 : $τ_0_0 : $*τ_0_0] : $τ_0_1,
-  // CHECK-SAME: indices_equals @equals_external_subscript
-  // CHECK-SAME: indices_hash @hash_external_subscript
-  // CHECK-SAME: ) <B, A> (%0)
-  %d = keypath $KeyPath<External<A>, A>, <G: Hashable, H> (
-    root $External<H>;
-    external #External.subscript <H, G> [%$0 : $G : $*G] : $H,
-      indices_equals @equals_external_subscript : $@convention(thin) <U: Hashable, T> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
-      indices_hash @hash_external_subscript : $@convention(thin) <U: Hashable, T> (UnsafeRawPointer) -> Int) <B, A> (%z)
+sil @external : $@convention(thin) <D: P, E: Q, F: R> () -> () {
+entry:
+  // CHECK: keypath $KeyPath<Gen<D, E, F>, D>, <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (root $Gen<τ_0_0, τ_0_1, τ_0_2>; settable_property $τ_0_0, id @id_a : $@convention(thin) () -> (), getter @get_gen_a : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (@in_guaranteed Gen<τ_0_0, τ_0_1, τ_0_2>) -> @out τ_0_0, setter @set_gen_a : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (@in_guaranteed τ_0_0, @in_guaranteed Gen<τ_0_0, τ_0_1, τ_0_2>) -> (), external #Gen.x<τ_0_0, τ_0_1, τ_0_2>) <D, E, F>
+  %a = keypath $KeyPath<Gen<D, E, F>, D>, <G: P, H: Q, I: R> (root $Gen<G, H, I>; settable_property $G, id @id_a : $@convention(thin) () -> (), getter @get_gen_a : $@convention(thin) <X3: P, Y3: Q, Z3: R> (@in_guaranteed Gen<X3, Y3, Z3>) -> @out X3, setter @set_gen_a : $@convention(thin) <X4: P, Y4: Q, Z4: R> (@in_guaranteed X4, @in_guaranteed Gen<X4, Y4, Z4>) -> (), external #Gen.x<G, H, I>) <D, E, F>
 
   return undef : $()
 }
diff --git a/test/SIL/Serialization/keypath.sil b/test/SIL/Serialization/keypath.sil
index b5d011b..a5e1ed5 100644
--- a/test/SIL/Serialization/keypath.sil
+++ b/test/SIL/Serialization/keypath.sil
@@ -149,28 +149,10 @@
 }
 
 // CHECK-LABEL: sil shared [serialized] @external
-sil shared [serialized] @external : $@convention(thin) <A, B: Hashable> (@in_guaranteed B) -> () {
-entry(%z : $*B):
-  // CHECK: %1 = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
-  %a = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
-
-  // CHECK: %2 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1, τ_0_2> (root $External<τ_0_2>; external #External.ro<τ_0_2> : $τ_0_2) <A, A, A>
-  %b = keypath $KeyPath<External<A>, A>, <C, D, E> (root $External<E>; external #External.ro <E> : $E) <A, A, A>
-
-  // CHECK: %3 = keypath $KeyPath<External<Int>, Int>, <τ_0_0> (root $External<τ_0_0>; external #External.ro<τ_0_0> : $τ_0_0) <Int>
-  %c = keypath $KeyPath<External<Int>, Int>, <F> (root $External<F>; external #External.ro <F> : $F) <Int>
-
-  // CHECK: %4 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (
-  // CHECK-SAME: root $External<τ_0_1>;
-  // CHECK-SAME: external #External.subscript<τ_0_1, τ_0_0>[%$0 : $τ_0_0 : $*τ_0_0] : $τ_0_1,
-  // CHECK-SAME: indices_equals @equals_external_subscript
-  // CHECK-SAME: indices_hash @hash_external_subscript
-  // CHECK-SAME: ) <B, A> (%0)
-  %d = keypath $KeyPath<External<A>, A>, <G: Hashable, H> (
-    root $External<H>;
-    external #External.subscript <H, G> [%$0 : $G : $*G] : $H,
-      indices_equals @equals_external_subscript : $@convention(thin) <U: Hashable, T> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
-      indices_hash @hash_external_subscript : $@convention(thin) <U: Hashable, T> (UnsafeRawPointer) -> Int) <B, A> (%z)
+sil shared [serialized] @external : $@convention(thin) <D: P, E: Q, F: R> () -> () {
+entry:
+  // CHECK: keypath $KeyPath<Gen<D, E, F>, D>, <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (root $Gen<τ_0_0, τ_0_1, τ_0_2>; settable_property $τ_0_0, id @id_a : $@convention(thin) () -> (), getter @get_gen_a : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (@in_guaranteed Gen<τ_0_0, τ_0_1, τ_0_2>) -> @out τ_0_0, setter @set_gen_a : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (@in_guaranteed τ_0_0, @in_guaranteed Gen<τ_0_0, τ_0_1, τ_0_2>) -> (), external #Gen.x<τ_0_0, τ_0_1, τ_0_2>) <D, E, F>
+  %a = keypath $KeyPath<Gen<D, E, F>, D>, <G: P, H: Q, I: R> (root $Gen<G, H, I>; settable_property $G, id @id_a : $@convention(thin) () -> (), getter @get_gen_a : $@convention(thin) <X3: P, Y3: Q, Z3: R> (@in_guaranteed Gen<X3, Y3, Z3>) -> @out X3, setter @set_gen_a : $@convention(thin) <X4: P, Y4: Q, Z4: R> (@in_guaranteed X4, @in_guaranteed Gen<X4, Y4, Z4>) -> (), external #Gen.x<G, H, I>) <D, E, F>
 
   return undef : $()
 }
@@ -183,7 +165,7 @@
   %3 = function_ref @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
   %4 = function_ref @optional : $@convention(thin) () -> ()
   %5 = function_ref @indexes : $@convention(thin) (S, C) -> ()
-  %6 = function_ref @external : $@convention(thin) <A, B: Hashable> (@in_guaranteed B) -> ()
+  %6 = function_ref @external : $@convention(thin) <D: P, E: Q, F: R> () -> ()
 
   unreachable
 }
diff --git a/test/SILGen/external-keypath.swift b/test/SILGen/external-keypath.swift
index 0b81600..88c41d6 100644
--- a/test/SILGen/external-keypath.swift
+++ b/test/SILGen/external-keypath.swift
@@ -1,5 +1,5 @@
 // RUN: %empty-directory(%t)
-// RUN: %target-swift-frontend -emit-module -o %t/ExternalKeyPaths.swiftmodule -module-name ExternalKeyPaths %S/Inputs/ExternalKeyPaths.swift
+// RUN: %target-swift-frontend -enable-resilience -emit-module -o %t/ExternalKeyPaths.swiftmodule -module-name ExternalKeyPaths %S/Inputs/ExternalKeyPaths.swift
 // RUN: %target-swift-emit-silgen -enable-key-path-resilience -I %t %s | %FileCheck %s
 
 import ExternalKeyPaths
@@ -11,47 +11,47 @@
 
 // CHECK-LABEL: sil hidden @{{.*}}16externalKeyPaths
 func externalKeyPaths<T: Hashable, U>(_ x: T, _ y: U, _ z: Int) {
-  // CHECK: keypath $WritableKeyPath<External<Int>, Int>, (root $External<Int>; external #External.property<Int> : $Int)
+  // CHECK: keypath $WritableKeyPath<External<Int>, Int>, (root $External<Int>; {{.*}} external #External.property<Int>)
   _ = \External<Int>.property
 
-  // CHECK: keypath $WritableKeyPath<External<Int>, Int>, (root $External<Int>; external #External.intProperty<Int> : $Int)
+  // CHECK: keypath $WritableKeyPath<External<Int>, Int>, (root $External<Int>; {{.*}} external #External.intProperty<Int>)
   _ = \External<Int>.intProperty
 
-  // CHECK: keypath $WritableKeyPath<External<T>, T>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_0>; external #External.property<T> : $τ_0_0) <T, U> 
+  // CHECK: keypath $WritableKeyPath<External<T>, T>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_0>; {{.*}} external #External.property<T>) <T, U> 
   _ = \External<T>.property
 
-  // CHECK: keypath $WritableKeyPath<External<T>, Int>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_0>; external #External.intProperty<T> : $Int) <T, U>
+  // CHECK: keypath $WritableKeyPath<External<T>, Int>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_0>; {{.*}} external #External.intProperty<T>) <T, U>
   _ = \External<T>.intProperty
 
-  // CHECK: keypath $WritableKeyPath<External<U>, U>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; external #External.property<U> : $τ_0_1) <T, U>
+  // CHECK: keypath $WritableKeyPath<External<U>, U>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; {{.*}} external #External.property<U>) <T, U>
   _ = \External<U>.property
 
-  // CHECK: keypath $WritableKeyPath<External<U>, Int>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; external #External.intProperty<U> : $Int) <T, U>
+  // CHECK: keypath $WritableKeyPath<External<U>, Int>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; {{.*}} external #External.intProperty<U>) <T, U>
   _ = \External<U>.intProperty
 
-  // CHECK: keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.subscript<Int, Int>[%$0 : $Int : $Int] : $Int, indices_equals @{{.*}}) (%2)
+  // CHECK: keypath $KeyPath<External<Int>, Int>, (root $External<Int>; {{.*}} external #External.subscript<Int, Int>) (%2)
   _ = \External<Int>.[z]
 
-  // CHECK: keypath $KeyPath<External<T>, T>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_0>; external #External.subscript<T, T>[%$0 : $τ_0_0 : $*τ_0_0] : $τ_0_0, indices_equals @{{.*}}) <T, U> ({{.*}})
+  // CHECK: keypath $KeyPath<External<T>, T>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_0>; {{.*}} external #External.subscript<T, T>) <T, U> ({{.*}})
   _ = \External<T>.[x]
 
-  // CHECK: keypath $KeyPath<External<U>, U>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; external #External.subscript<U, T>[%$0 : $τ_0_0 : $*τ_0_0] : $τ_0_1, indices_equals @{{.*}}) <T, U> ({{.*}})
+  // CHECK: keypath $KeyPath<External<U>, U>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; {{.*}} external #External.subscript<U, T>) <T, U> ({{.*}})
   _ = \External<U>.[x]
 
   // CHECK: keypath $KeyPath<External<Local>, Int>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (
   // CHECK-SAME: root $External<Local>;
-  // CHECK-SAME: external #External.subscript<Local, T>[%$0 : $τ_0_0 : $*τ_0_0] : $Local, indices_equals @{{.*}};
+  // CHECK-SAME: external #External.subscript<Local, T>
   // CHECK-SAME: stored_property #Local.x : $Int) <T, U> ({{.*}})
   _ = \External<Local>.[x].x
 
   // CHECK: keypath $KeyPath<External<Local>, String>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (
   // CHECK-SAME: root $External<Local>;
-  // CHECK-SAME: external #External.subscript<Local, T>[%$0 : $τ_0_0 : $*τ_0_0] : $Local, indices_equals @{{.*}};
+  // CHECK-SAME: external #External.subscript<Local, T>
   // CHECK-SAME: stored_property #Local.y : $String) <T, U> ({{.*}})
   _ = \External<Local>.[x].y
 
   // CHECK: keypath $KeyPath<ExternalEmptySubscript, Int>, (
   // CHECK-SAME: root $ExternalEmptySubscript;
-  // CHECK-SAME: external #ExternalEmptySubscript.subscript : $Int)
+  // CHECK-SAME: external #ExternalEmptySubscript.subscript
   _ = \ExternalEmptySubscript.[]
 }
diff --git a/test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift b/test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift
index c9d1b7a..9e3797e 100644
--- a/test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift
+++ b/test/stdlib/Inputs/DictionaryKeyValueTypesObjC.swift
@@ -874,7 +874,8 @@
   for i in 0..<3 {
     var actualContents = [ExpectedDictionaryElement]()
     let sink: (AnyObjectTuple2) -> Void = {
-      (key, value) in
+      pair in
+      let (key, value) = pair
       actualContents.append(ExpectedDictionaryElement(
         key: convertKey(key),
         value: convertValue(value),
diff --git a/utils/dev-scripts/csvcolumn_to_scurve.py b/utils/dev-scripts/csvcolumn_to_scurve.py
new file mode 100755
index 0000000..621c7a9
--- /dev/null
+++ b/utils/dev-scripts/csvcolumn_to_scurve.py
@@ -0,0 +1,55 @@
+#!/usr/bin/env python
+
+# This is a simple script that reads in a csv file, selects a column, and then
+# forms an "s-curve" graph of that column.
+
+import argparse
+import csv
+import sys
+
+
+def get_data(input_file, before_column, after_column):
+
+    def get_selected_csv_rows(input_file, before_column, after_column):
+        for row in csv.DictReader(input_file):
+            before = float(row[before_column])
+            after = float(row[after_column])
+            delta = after / before
+            yield delta
+
+    def f(input_data):
+        result = list(enumerate(sorted(input_data)))
+        count = float(len(result) - 1)
+        return [(x[0] / count, x[1]) for x in result]
+
+    return f(get_selected_csv_rows(input_file, before_column, after_column))
+
+
+def main():
+    p = argparse.ArgumentParser(description="""
+
+    A script that reads in a csv file, splices out selected before/after
+    column, and then outputs a new csv file with that data in s-curve form. An
+    s-curve is a graph where one sorts the output %-change and graphs the %-n
+    vs %-change.
+
+    NOTE: We assume that the csv has a csv header that maps to the before and
+    after column names passed in.
+    """)
+
+    p.add_argument('input_file', type=argparse.FileType('r'))
+    p.add_argument('before_column_name', type=str)
+    p.add_argument('after_column_name', type=str)
+
+    args = p.parse_args()
+
+    data = get_data(args.input_file, args.before_column_name,
+                    args.after_column_name)
+    w = csv.DictWriter(sys.stdout, fieldnames=['N/total', 'New/Old'])
+    w.writeheader()
+    for d in data:
+        w.writerow({'N/total': d[0], 'New/Old': d[1]})
+
+
+if __name__ == "__main__":
+    main()
diff --git a/utils/dev-scripts/scurve_printer.py b/utils/dev-scripts/scurve_printer.py
new file mode 100755
index 0000000..2fea673
--- /dev/null
+++ b/utils/dev-scripts/scurve_printer.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+
+# This is a simple script that takes in an scurve file produced by
+# csvcolumn_to_scurve and produces a png graph of the scurve.
+
+import argparse
+import csv
+
+import matplotlib.pyplot as plt
+
+import numpy as np
+
+FIELDS = ['N/total', 'New/Old']
+
+
+def get_data(input_file):
+    global FIELDS
+    for row in csv.DictReader(input_file):
+        yield (float(row[FIELDS[0]]), float(row[FIELDS[1]]))
+
+
+def main():
+    p = argparse.ArgumentParser()
+    p.add_argument('input_csv_file', type=argparse.FileType('r'))
+    p.add_argument('output_file', type=str)
+    p.add_argument('-y-axis-num-tick-marks', type=int,
+                   help='The number of y tick marks to use above/below zero.')
+    p.add_argument('-y-axis-min', type=float,
+                   help='Override the min y axis that we use')
+    p.add_argument('-y-axis-max', type=float,
+                   help='Override the min y axis that we use')
+    p.add_argument('-title', type=str,
+                   help='Title of the graph')
+    p.add_argument('-x-axis-title', type=str,
+                   help='The title to use on the x-axis of the graph')
+    p.add_argument('-y-axis-title', type=str,
+                   help='The title to use on the x-axis of the graph')
+
+    args = p.parse_args()
+
+    data = np.array(list(get_data(args.input_csv_file)))
+    assert np.all(data >= 0)
+
+    x = data[:, 0]
+    y = data[:, 1]
+
+    x_axis_title = args.x_axis_title or FIELDS[0]
+    y_axis_title = args.y_axis_title or FIELDS[1]
+    title = args.title or "{} vs {}".format(x_axis_title, y_axis_title)
+
+    fig, ax = plt.subplots()
+    fig.set_size_inches(18.5, 18.5)
+
+    fig.suptitle(title, fontsize=20)
+    ax.set_xlabel(x_axis_title, fontsize=20)
+    ax.set_ylabel(y_axis_title, fontsize=20)
+    ax.plot(x, y)
+    ax.scatter(x, y)
+
+    # To get good bounds, we:
+    #
+    # 1. Re-center our data at 0 by subtracting 1. This will give us the %
+    # difference in between new and old (i.e. (new - old)/old)
+    #
+    # 2. Then we take the maximum absolute delta from zero and round to a
+    # multiple of 5 away from zero. Lets call this value limit.
+    #
+    # 3. We set [min_y, max_y] = [1.0 - limit, 1.0 + limit]
+    recentered_data = y - 1.0
+    max_magnitude = int(np.max(np.abs(recentered_data)) * 100.0)
+    y_limit = float(((max_magnitude // 5) + 1) * 5) * 0.01
+
+    ax.set_xlim(0.0, 1.0)
+    y_min = args.y_axis_min or 1.0 - y_limit
+    y_max = args.y_axis_max or 1.0 + y_limit
+    assert(y_min <= y_max)
+    ax.set_ylim(y_min, y_max)
+    ax.grid(True)
+    ax.xaxis.set_ticks(np.arange(0.0, 1.0, 0.05))
+    if args.y_axis_num_tick_marks:
+        y_delta = y_max - y_min
+        y_tickmark_frequency = y_delta / float(args.y_axis_num_tick_marks)
+        ax.yaxis.set_ticks(np.arange(y_min, y_max, y_tickmark_frequency))
+    plt.savefig(args.output_file)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/validation-test/compiler_crashers_fixed/26813-generic-enum-tuple-optional-payload.swift b/validation-test/compiler_crashers_fixed/26813-generic-enum-tuple-optional-payload.swift
index 64c07ba..2181e69 100644
--- a/validation-test/compiler_crashers_fixed/26813-generic-enum-tuple-optional-payload.swift
+++ b/validation-test/compiler_crashers_fixed/26813-generic-enum-tuple-optional-payload.swift
@@ -1,6 +1,6 @@
 // This source file is part of the Swift.org open source project
 //
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2018 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
diff --git a/validation-test/stdlib/Dictionary.swift b/validation-test/stdlib/Dictionary.swift
index fae87a1..f802af7 100644
--- a/validation-test/stdlib/Dictionary.swift
+++ b/validation-test/stdlib/Dictionary.swift
@@ -3,9 +3,9 @@
 // RUN: %gyb %s -o %t/main.swift
 // RUN: if [ %target-runtime == "objc" ]; then \
 // RUN:   %target-clang -fobjc-arc %S/Inputs/SlurpFastEnumeration/SlurpFastEnumeration.m -c -o %t/SlurpFastEnumeration.o; \
-// RUN:   %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Dictionary -Xfrontend -disable-access-control -swift-version 3; \
+// RUN:   %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %S/Inputs/DictionaryKeyValueTypesObjC.swift %t/main.swift -I %S/Inputs/SlurpFastEnumeration/ -Xlinker %t/SlurpFastEnumeration.o -o %t/Dictionary -Xfrontend -disable-access-control ; \
 // RUN: else \
-// RUN:   %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %t/main.swift -o %t/Dictionary -Xfrontend -disable-access-control -swift-version 3; \
+// RUN:   %line-directive %t/main.swift -- %target-build-swift %S/Inputs/DictionaryKeyValueTypes.swift %t/main.swift -o %t/Dictionary -Xfrontend -disable-access-control ; \
 // RUN: fi
 //
 // RUN: %line-directive %t/main.swift -- %target-run %t/Dictionary
@@ -1671,10 +1671,10 @@
   struct TE: Error {}
   do {
     // No duplicate keys, so no error thrown.
-    var d1 = try Dictionary([(10, 1), (20, 2), (30, 3)]) { _ in throw TE() }
+    var d1 = try Dictionary([(10, 1), (20, 2), (30, 3)]) { _, _ in throw TE() }
     expectEqual(d1.count, 3)
     // Duplicate keys, should throw error.
-    var d2 = try Dictionary([(10, 1), (10, 2)]) { _ in throw TE() }
+    var d2 = try Dictionary([(10, 1), (10, 2)]) { _, _ in throw TE() }
     assertionFailure()
   } catch {
     assert(error is TE)
@@ -1762,7 +1762,7 @@
 
   // Fill up to the limit, no reallocation.
   d1.merge(stride(from: 50, through: 240, by: 10).lazy.map { ($0, 1000 + $0) },
-    uniquingKeysWith: { _ in fatalError() })
+    uniquingKeysWith: { _, _ in fatalError() })
   expectEqual(24, d1.count)
   expectEqual(24, d1.capacity)
   d1[250] = 1250
@@ -4297,28 +4297,28 @@
 var ObjCThunks = TestSuite("ObjCThunks")
 
 class ObjCThunksHelper : NSObject {
-  dynamic func acceptArrayBridgedVerbatim(_ array: [TestObjCValueTy]) {
+  @objc dynamic func acceptArrayBridgedVerbatim(_ array: [TestObjCValueTy]) {
     expectEqual(10, array[0].value)
     expectEqual(20, array[1].value)
     expectEqual(30, array[2].value)
   }
 
-  dynamic func acceptArrayBridgedNonverbatim(_ array: [TestBridgedValueTy]) {
+  @objc dynamic func acceptArrayBridgedNonverbatim(_ array: [TestBridgedValueTy]) {
     // Cannot check elements because doing so would bridge them.
     expectEqual(3, array.count)
   }
 
-  dynamic func returnArrayBridgedVerbatim() -> [TestObjCValueTy] {
+  @objc dynamic func returnArrayBridgedVerbatim() -> [TestObjCValueTy] {
     return [ TestObjCValueTy(10), TestObjCValueTy(20),
         TestObjCValueTy(30) ]
   }
 
-  dynamic func returnArrayBridgedNonverbatim() -> [TestBridgedValueTy] {
+  @objc dynamic func returnArrayBridgedNonverbatim() -> [TestBridgedValueTy] {
     return [ TestBridgedValueTy(10), TestBridgedValueTy(20),
         TestBridgedValueTy(30) ]
   }
 
-  dynamic func acceptDictionaryBridgedVerbatim(
+  @objc dynamic func acceptDictionaryBridgedVerbatim(
       _ d: [TestObjCKeyTy : TestObjCValueTy]) {
     expectEqual(3, d.count)
     expectEqual(1010, d[TestObjCKeyTy(10)]!.value)
@@ -4326,13 +4326,13 @@
     expectEqual(1030, d[TestObjCKeyTy(30)]!.value)
   }
 
-  dynamic func acceptDictionaryBridgedNonverbatim(
+  @objc dynamic func acceptDictionaryBridgedNonverbatim(
       _ d: [TestBridgedKeyTy : TestBridgedValueTy]) {
     expectEqual(3, d.count)
     // Cannot check elements because doing so would bridge them.
   }
 
-  dynamic func returnDictionaryBridgedVerbatim() ->
+  @objc dynamic func returnDictionaryBridgedVerbatim() ->
       [TestObjCKeyTy : TestObjCValueTy] {
     return [
         TestObjCKeyTy(10): TestObjCValueTy(1010),
@@ -4341,7 +4341,7 @@
     ]
   }
 
-  dynamic func returnDictionaryBridgedNonverbatim() ->
+  @objc dynamic func returnDictionaryBridgedNonverbatim() ->
       [TestBridgedKeyTy : TestBridgedValueTy] {
     return [
         TestBridgedKeyTy(10): TestBridgedValueTy(1010),