Merge pull request #18317 from DougGregor/refactor-name-lookup

diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def
index a0187d2..10742d9 100644
--- a/include/swift/AST/DiagnosticsFrontend.def
+++ b/include/swift/AST/DiagnosticsFrontend.def
@@ -38,69 +38,70 @@
 #endif
 
 WARNING(warning_no_such_sdk,none,
-  "no such SDK: '%0'", (StringRef))
+        "no such SDK: '%0'", (StringRef))
 
 ERROR(error_no_frontend_args, none,
-  "no arguments provided to '-frontend'", ())
+      "no arguments provided to '-frontend'", ())
 
 ERROR(error_no_such_file_or_directory,none,
-  "no such file or directory: '%0'", (StringRef))
+      "no such file or directory: '%0'", (StringRef))
 
 ERROR(error_unsupported_target_os, none,
-  "unsupported target OS: '%0'", (StringRef))
+      "unsupported target OS: '%0'", (StringRef))
 
 ERROR(error_unsupported_target_arch, none,
-  "unsupported target architecture: '%0'", (StringRef))
+      "unsupported target architecture: '%0'", (StringRef))
 
 ERROR(error_unsupported_opt_for_target, none,
-  "unsupported option '%0' for target '%1'", (StringRef, StringRef))
+      "unsupported option '%0' for target '%1'", (StringRef, StringRef))
 
 ERROR(error_argument_not_allowed_with, none,
-  "argument '%0' is not allowed with '%1'", (StringRef, StringRef))
+      "argument '%0' is not allowed with '%1'", (StringRef, StringRef))
 
 WARNING(warning_argument_not_supported_with_optimization, none,
-  "argument '%0' is not supported with optimization", (StringRef))
+        "argument '%0' is not supported with optimization", (StringRef))
 
 ERROR(error_option_requires_sanitizer, none,
-  "option '%0' requires a sanitizer to be enabled. Use -sanitize= to enable a"
-  " sanitizer", (StringRef))
+      "option '%0' requires a sanitizer to be enabled. Use -sanitize= to "
+      "enable a sanitizer", (StringRef))
 
 ERROR(error_option_missing_required_argument, none,
-  "option '%0' is missing a required argument (%1)", (StringRef, StringRef))
+      "option '%0' is missing a required argument (%1)", (StringRef, StringRef))
 
 ERROR(cannot_open_file,none,
-  "cannot open file '%0' (%1)", (StringRef, StringRef))
+      "cannot open file '%0' (%1)", (StringRef, StringRef))
 ERROR(cannot_open_serialized_file,none,
-  "cannot open file '%0' for diagnostics emission (%1)", (StringRef, StringRef))
+      "cannot open file '%0' for diagnostics emission (%1)",
+      (StringRef, StringRef))
 ERROR(error_open_input_file,none,
-  "error opening input file '%0' (%1)", (StringRef, StringRef))
+      "error opening input file '%0' (%1)", (StringRef, StringRef))
 ERROR(error_clang_importer_create_fail,none,
-  "clang importer creation failed", ())
+      "clang importer creation failed", ())
 ERROR(error_missing_arg_value,none,
-  "missing argument value for '%0', expected %1 argument(s)",
-  (StringRef, unsigned))
+      "missing argument value for '%0', expected %1 argument(s)",
+      (StringRef, unsigned))
 ERROR(error_unknown_arg,none,
-  "unknown argument: '%0'", (StringRef))
+      "unknown argument: '%0'", (StringRef))
 ERROR(error_invalid_arg_value,none,
-  "invalid value '%1' in '%0'", (StringRef, StringRef))
+      "invalid value '%1' in '%0'", (StringRef, StringRef))
 WARNING(warning_cannot_multithread_batch_mode,none,
-  "ignoring -num-threads argument; cannot multithread batch mode", ())
+      "ignoring -num-threads argument; cannot multithread batch mode", ())
 ERROR(error_unsupported_option_argument,none,
-  "unsupported argument '%1' to option '%0'", (StringRef, StringRef))
+      "unsupported argument '%1' to option '%0'", (StringRef, StringRef))
 ERROR(error_immediate_mode_missing_stdlib,none,
-  "could not load the swift standard library", ())
+      "could not load the swift standard library", ())
 ERROR(error_immediate_mode_missing_library,none,
-  "could not load %select{shared library|framework}0 '%1'",
-  (unsigned, StringRef))
+      "could not load %select{shared library|framework}0 '%1'",
+      (unsigned, StringRef))
 ERROR(error_immediate_mode_primary_file,none,
-  "immediate mode is incompatible with -primary-file", ())
+      "immediate mode is incompatible with -primary-file", ())
 ERROR(error_missing_frontend_action,none,
-  "no frontend action was selected", ())
+      "no frontend action was selected", ())
 ERROR(error_invalid_source_location_str,none,
-  "invalid source location string '%0'", (StringRef))
+      "invalid source location string '%0'", (StringRef))
 ERROR(error_no_source_location_scope_map,none,
-  "-dump-scope-maps argument must be 'expanded' or a list of source locations",
-  ())
+      "-dump-scope-maps argument must be 'expanded' or a list of "
+      "source locations", ())
 
 NOTE(note_swift_version_major, none,
      "use major version, as in '-swift-version %0'", (unsigned))
@@ -140,46 +141,50 @@
       "underlying Objective-C module %0 not found", (Identifier))
 
 ERROR(error_unable_to_load_supplementary_output_file_map, none,
-      "unable to load supplementary output file map '%0': %1", (StringRef, StringRef))
+      "unable to load supplementary output file map '%0': %1",
+      (StringRef, StringRef))
 
 ERROR(error_missing_entry_in_supplementary_output_file_map, none,
-      "supplementary output file map '%0' is missing an entry for '%1' (this likely indicates a compiler issue; please file a bug report)", (StringRef, StringRef))
+      "supplementary output file map '%0' is missing an entry for '%1' "
+      "(this likely indicates a compiler issue; please file a bug report)",
+      (StringRef, StringRef))
 
 ERROR(error_repl_requires_no_input_files,none,
-  "REPL mode requires no input files", ())
+      "REPL mode requires no input files", ())
 ERROR(error_mode_requires_one_input_file,none,
-  "this mode requires a single input file", ())
+      "this mode requires a single input file", ())
 ERROR(error_mode_requires_an_input_file,none,
-  "this mode requires at least one input file", ())
+      "this mode requires at least one input file", ())
 ERROR(error_mode_requires_one_sil_multi_sib,none,
-  "this mode requires .sil for primary-file and only .sib for other inputs", ())
+      "this mode requires .sil for primary-file and only .sib for other inputs",
+      ())
 
 ERROR(error_no_output_filename_specified,none,
-  "an output filename was not specified for a mode which requires an output "
-  "filename", ())
+      "an output filename was not specified for a mode which requires an "
+      "output filename", ())
 
 ERROR(error_implicit_output_file_is_directory,none,
-  "the implicit output file '%0' is a directory; explicitly specify a filename "
-  "using -o", (StringRef))
+      "the implicit output file '%0' is a directory; explicitly specify a "
+      "filename using -o", (StringRef))
 
 ERROR(error_if_any_output_files_are_specified_they_all_must_be,none,
-  "if any output files are specified, they all must be", ())
+      "if any output files are specified, they all must be", ())
 
 ERROR(error_primary_file_not_found,none,
       "primary file '%0' was not found in file list '%1'",
       (StringRef, StringRef))
 
 ERROR(error_cannot_have_input_files_with_file_list,none,
-"cannot have input files with file list", ())
+      "cannot have input files with file list", ())
 
 ERROR(error_cannot_have_primary_files_with_primary_file_list,none,
-"cannot have primary input files with primary file list", ())
+      "cannot have primary input files with primary file list", ())
 
 ERROR(error_cannot_have_supplementary_outputs,none,
-"cannot have '%0' with '%1'", (StringRef, StringRef))
+      "cannot have '%0' with '%1'", (StringRef, StringRef))
 
 ERROR(error_duplicate_input_file,none,
-"duplicate input file '%0'", (StringRef))
+      "duplicate input file '%0'", (StringRef))
 
 ERROR(repl_must_be_initialized,none,
       "variables currently must have an initial value when entered at the "
@@ -192,33 +197,35 @@
       "fatal error encountered while in -verify mode", ())
 
 ERROR(error_parse_input_file,none,
-  "error parsing input file '%0' (%1)", (StringRef, StringRef))
+      "error parsing input file '%0' (%1)", (StringRef, StringRef))
 
 ERROR(error_write_index_unit,none,
-  "writing index unit file: %0", (StringRef))
+      "writing index unit file: %0", (StringRef))
 ERROR(error_create_index_dir,none,
-  "creating index directory: %0", (StringRef))
+      "creating index directory: %0", (StringRef))
 ERROR(error_write_index_record,none,
-  "writing index record file: %0", (StringRef))
+      "writing index record file: %0", (StringRef))
 ERROR(error_index_failed_status_check,none,
-  "failed file status check: %0", (StringRef))
+      "failed file status check: %0", (StringRef))
 ERROR(error_index_inputs_more_than_outputs,none,
-  "index output filenames do not match input source files", ())
+      "index output filenames do not match input source files", ())
 
 ERROR(error_wrong_number_of_arguments,none,
-"wrong number of '%0' arguments (expected %1, got %2)", (StringRef, int, int))
+      "wrong number of '%0' arguments (expected %1, got %2)",
+      (StringRef, int, int))
 
 ERROR(error_formatting_multiple_file_ranges,none,
-  "file ranges don't support multiple input files", ())
+      "file ranges don't support multiple input files", ())
 
 ERROR(error_formatting_invalid_range,none,
-  "file range is invalid", ())
+      "file range is invalid", ())
 
 WARNING(stats_disabled,none,
-  "compiler was not built with support for collecting statistics", ())
+        "compiler was not built with support for collecting statistics", ())
 
 WARNING(tbd_only_supported_in_whole_module,none,
-  "TBD generation is only supported when the whole module can be seen", ())
+        "TBD generation is only supported when the whole module can be seen",
+        ())
 
 ERROR(symbol_in_tbd_not_in_ir,none,
       "symbol '%0' (%1) is in TBD file, but not in generated IR",
@@ -232,12 +239,12 @@
       "add -Xfrontend -validate-tbd-against-ir=none to squash the errors", ())
 
 ERROR(redundant_prefix_compilation_flag,none,
-      "invalid argument '-D%0'; did you provide a redundant '-D' in your build settings?", 
-      (StringRef))    
+      "invalid argument '-D%0'; did you provide a redundant '-D' in your "
+      "build settings?", (StringRef))
 
 ERROR(invalid_conditional_compilation_flag,none,
-      "conditional compilation flags must be valid Swift identifiers (rather than '%0')",
-      (StringRef))
+      "conditional compilation flags must be valid Swift identifiers "
+      "(rather than '%0')", (StringRef))
 
 WARNING(cannot_assign_value_to_conditional_compilation_flag,none,
         "conditional compilation flags do not have values in Swift; they are "
diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp
index d89dc54..b02b9ca 100644
--- a/lib/Sema/CSBindings.cpp
+++ b/lib/Sema/CSBindings.cpp
@@ -15,6 +15,7 @@
 //===----------------------------------------------------------------------===//
 #include "ConstraintGraph.h"
 #include "ConstraintSystem.h"
+#include "llvm/ADT/SetVector.h"
 #include <tuple>
 
 using namespace swift;
@@ -361,8 +362,7 @@
   assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type");
 
   // Gather the constraints associated with this type variable.
-  SmallVector<Constraint *, 8> constraints;
-  llvm::SmallPtrSet<Constraint *, 4> visitedConstraints;
+  llvm::SetVector<Constraint *> constraints;
   getConstraintGraph().gatherConstraints(
       typeVar, constraints, ConstraintGraph::GatheringKind::EquivalenceClass);
 
@@ -377,10 +377,6 @@
   bool hasNonDependentMemberRelationalConstraints = false;
   bool hasDependentMemberRelationalConstraints = false;
   for (auto constraint : constraints) {
-    // Only visit each constraint once.
-    if (!visitedConstraints.insert(constraint).second)
-      continue;
-
     switch (constraint->getKind()) {
     case ConstraintKind::Bind:
     case ConstraintKind::Equal:
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index f039258..98baf07 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -30,6 +30,7 @@
 #include "swift/Basic/Defer.h"
 #include "swift/Basic/StringExtras.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/SaveAndRestore.h"
 
@@ -8728,29 +8729,27 @@
     // because type B would have no constraints associated with it.
     unsigned numConstraints = 0;
     {
-      llvm::SmallVector<Constraint *, 2> constraints;
+      llvm::SetVector<Constraint *> constraints;
       CS.getConstraintGraph().gatherConstraints(
-          tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass);
+          tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
+          [&](Constraint *constraint) -> bool {
+            // We are not interested in ConformsTo constraints because
+            // we can't derive any concrete type information from them.
+            if (constraint->getKind() == ConstraintKind::ConformsTo)
+              return false;
 
-      for (auto constraint : constraints) {
-        // We are not interested in ConformsTo constraints because
-        // such constraints specify restrictions on the archetypes themselves.
-        if (constraint->getKind() == ConstraintKind::ConformsTo)
-          continue;
+            if (constraint->getKind() == ConstraintKind::Bind) {
+              if (auto locator = constraint->getLocator()) {
+                auto anchor = locator->getAnchor();
+                if (anchor && isa<UnresolvedDotExpr>(anchor))
+                  return false;
+              }
+            }
 
-        // Some of the bind constraints specify relations between
-        // parent type and it's member fields/types, we are not
-        // interested in that, since it's not related to archetype resolution.
-        if (constraint->getKind() == ConstraintKind::Bind) {
-          if (auto locator = constraint->getLocator()) {
-            auto anchor = locator->getAnchor();
-            if (anchor && isa<UnresolvedDotExpr>(anchor))
-              continue;
-          }
-        }
+            return true;
+          });
 
-        numConstraints++;
-      }
+      numConstraints = constraints.size();
     }
 
     auto locator = impl.getLocator();
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 2a16263..41c1b06 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -23,6 +23,7 @@
 #include "swift/AST/SubstitutionMap.h"
 #include "swift/Sema/IDETypeChecking.h"
 #include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include <utility>
@@ -574,18 +575,19 @@
     // being applied, and the only constraint attached to it should
     // be the disjunction constraint for the overload group.
     auto &CG = CS.getConstraintGraph();
-    SmallVector<Constraint *, 4> constraints;
-    CG.gatherConstraints(tyvarType, constraints,
-                         ConstraintGraph::GatheringKind::EquivalenceClass);
-    if (constraints.empty())
+    llvm::SetVector<Constraint *> disjunctions;
+    CG.gatherConstraints(tyvarType, disjunctions,
+                         ConstraintGraph::GatheringKind::EquivalenceClass,
+                         [](Constraint *constraint) -> bool {
+                           return constraint->getKind() ==
+                                  ConstraintKind::Disjunction;
+                         });
+    if (disjunctions.empty())
       return;
     
     // Look for the disjunction that binds the overload set.
-    for (auto constraint : constraints) {
-      if (constraint->getKind() != ConstraintKind::Disjunction)
-        continue;
-      
-      auto oldConstraints = constraint->getNestedConstraints();
+    for (auto *disjunction : disjunctions) {
+      auto oldConstraints = disjunction->getNestedConstraints();
       auto csLoc = CS.getConstraintLocator(expr->getFn());
       
       // Only replace the disjunctive overload constraint.
@@ -633,8 +635,8 @@
 
       // Remove the original constraint from the inactive constraint
       // list and add the new one.
-      CS.removeInactiveConstraint(constraint);
-      
+      CS.removeInactiveConstraint(disjunction);
+
       // Create the disjunction of favored constraints.
       auto favoredConstraintsDisjunction =
           Constraint::createDisjunction(CS,
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 10343a5..3436519 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -21,6 +21,7 @@
 #include "swift/AST/ProtocolConformance.h"
 #include "swift/Basic/StringExtras.h"
 #include "swift/ClangImporter/ClangModule.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/Support/Compiler.h"
 
 using namespace swift;
@@ -5085,17 +5086,19 @@
   auto typeVar = getType(keyPathExpr)->getAs<TypeVariableType>();
   if (!typeVar)
     return;
-  
-  SmallVector<Constraint *, 4> constraints;
-  CG.gatherConstraints(typeVar, constraints,
-                       ConstraintGraph::GatheringKind::EquivalenceClass);
-  
+
+  llvm::SetVector<Constraint *> constraints;
+  CG.gatherConstraints(
+      typeVar, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
+      [&keyPathExpr](Constraint *constraint) -> bool {
+        return constraint->getKind() == ConstraintKind::KeyPath &&
+               constraint->getLocator()->getAnchor() == keyPathExpr;
+      });
+
   for (auto constraint : constraints) {
-    if (constraint->getKind() == ConstraintKind::KeyPath &&
-        constraint->getLocator()->getAnchor() == keyPathExpr) {
-      auto keyPathRootTy = constraint->getSecondType();
-      addConstraint(ConstraintKind::Subtype, root->getWithoutSpecifierType(), keyPathRootTy, locator);
-    }
+    auto keyPathRootTy = constraint->getSecondType();
+    addConstraint(ConstraintKind::Subtype, root->getWithoutSpecifierType(),
+                  keyPathRootTy, locator);
   }
 }
 
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 0ef36bc..bac7d4e 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -17,6 +17,7 @@
 #include "ConstraintSystem.h"
 #include "swift/AST/ParameterList.h"
 #include "swift/AST/TypeWalker.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/SaveAndRestore.h"
@@ -93,15 +94,18 @@
       *isNilLiteral = false;
 
       // Look for a literal-conformance constraint on the type variable.
-      SmallVector<Constraint *, 8> constraints;
+      llvm::SetVector<Constraint *> constraints;
       getConstraintGraph().gatherConstraints(
           bindingTypeVar, constraints,
-          ConstraintGraph::GatheringKind::EquivalenceClass);
+          ConstraintGraph::GatheringKind::EquivalenceClass,
+          [](Constraint *constraint) -> bool {
+            return constraint->getKind() == ConstraintKind::LiteralConformsTo &&
+                   constraint->getProtocol()->isSpecificProtocol(
+                       KnownProtocolKind::ExpressibleByNilLiteral);
+          });
+
       for (auto constraint : constraints) {
-        if (constraint->getKind() == ConstraintKind::LiteralConformsTo &&
-            constraint->getProtocol()->isSpecificProtocol(
-                KnownProtocolKind::ExpressibleByNilLiteral) &&
-            simplifyType(constraint->getFirstType())->isEqual(bindingTypeVar)) {
+        if (simplifyType(constraint->getFirstType())->isEqual(bindingTypeVar)) {
           *isNilLiteral = true;
           break;
         }
@@ -1899,14 +1903,14 @@
                    ->getAs<TypeVariableType>();
     assert(tv);
 
-    SmallVector<Constraint *, 8> constraints;
+    llvm::SetVector<Constraint *> constraints;
     cs.getConstraintGraph().gatherConstraints(
-        tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass);
+        tv, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
+        [](Constraint *constraint) {
+          return constraint->getKind() == ConstraintKind::Conversion;
+        });
 
     for (auto *constraint : constraints) {
-      if (constraint->getKind() != ConstraintKind::Conversion)
-        continue;
-
       auto toType =
           cs.simplifyType(constraint->getSecondType())->getRValueType();
       auto *toTV = toType->getAs<TypeVariableType>();
@@ -2224,26 +2228,23 @@
     return;
 
   auto conversionType = bindings.Bindings[0].BindingType;
-  SmallVector<Constraint *, 4> constraints;
+  llvm::SetVector<Constraint *> constraints;
   CS->CG.gatherConstraints(typeVar, constraints,
-                           ConstraintGraph::GatheringKind::EquivalenceClass);
+                           ConstraintGraph::GatheringKind::EquivalenceClass,
+                           [](Constraint *constraint) -> bool {
+                             switch (constraint->getKind()) {
+                             case ConstraintKind::Conversion:
+                             case ConstraintKind::Defaultable:
+                             case ConstraintKind::ConformsTo:
+                             case ConstraintKind::LiteralConformsTo:
+                               return false;
 
-  bool viableForBinding = true;
-  for (auto adjacent : constraints) {
-    switch (adjacent->getKind()) {
-    case ConstraintKind::Conversion:
-    case ConstraintKind::Defaultable:
-    case ConstraintKind::ConformsTo:
-    case ConstraintKind::LiteralConformsTo:
-      break;
+                             default:
+                               return true;
+                             }
+                           });
 
-    default:
-      viableForBinding = false;
-      break;
-    }
-  }
-
-  if (viableForBinding)
+  if (constraints.empty())
     CS->addConstraint(ConstraintKind::Bind, typeVar, conversionType,
                       Choice->getLocator());
 }
diff --git a/lib/Sema/ConstraintGraph.cpp b/lib/Sema/ConstraintGraph.cpp
index a493141..22a3d80 100644
--- a/lib/Sema/ConstraintGraph.cpp
+++ b/lib/Sema/ConstraintGraph.cpp
@@ -19,6 +19,7 @@
 #include "ConstraintGraphScope.h"
 #include "ConstraintSystem.h"
 #include "swift/Basic/Statistic.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/SaveAndRestore.h"
 #include <algorithm>
@@ -467,9 +468,9 @@
 }
 
 void ConstraintGraph::gatherConstraints(
-       TypeVariableType *typeVar,
-       SmallVectorImpl<Constraint *> &constraints,
-       GatheringKind kind) {
+    TypeVariableType *typeVar, llvm::SetVector<Constraint *> &constraints,
+    GatheringKind kind,
+    llvm::function_ref<bool(Constraint *)> acceptConstraint) {
   auto &reprNode = (*this)[CS.getRepresentative(typeVar)];
   auto equivClass = reprNode.getEquivalenceClass();
   llvm::SmallPtrSet<TypeVariableType *, 4> typeVars;
@@ -477,8 +478,10 @@
     if (!typeVars.insert(typeVar).second)
       continue;
 
-    for (auto constraint : (*this)[typeVar].getConstraints())
-      constraints.push_back(constraint);
+    for (auto constraint : (*this)[typeVar].getConstraints()) {
+      if (acceptConstraint(constraint))
+        constraints.insert(constraint);
+    }
 
     auto &node = (*this)[typeVar];
 
@@ -510,8 +513,10 @@
         if (!typeVars.insert(adjTypeVarEquiv).second)
           continue;
 
-        for (auto constraint : (*this)[adjTypeVarEquiv].getConstraints())
-          constraints.push_back(constraint);
+        for (auto constraint : (*this)[adjTypeVarEquiv].getConstraints()) {
+          if (acceptConstraint(constraint))
+            constraints.insert(constraint);
+        }
       }
     }
   }
diff --git a/lib/Sema/ConstraintGraph.h b/lib/Sema/ConstraintGraph.h
index 328dd76..eca1ddf 100644
--- a/lib/Sema/ConstraintGraph.h
+++ b/lib/Sema/ConstraintGraph.h
@@ -22,6 +22,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
 #include <functional>
@@ -221,11 +222,12 @@
   /// Gather the set of constraints that involve the given type variable,
   /// i.e., those constraints that will be affected when the type variable
   /// gets merged or bound to a fixed type.
-  ///
-  /// The resulting set of constraints may contain duplicates.
-  void gatherConstraints(TypeVariableType *typeVar,
-                         SmallVectorImpl<Constraint *> &constraints,
-                         GatheringKind kind);
+  void
+  gatherConstraints(TypeVariableType *typeVar,
+                    llvm::SetVector<Constraint *> &constraints,
+                    GatheringKind kind,
+                    llvm::function_ref<bool(Constraint *)> acceptConstraint =
+                        [](Constraint *constraint) { return true; });
 
   /// Retrieve the type variables that correspond to nodes in the graph.
   ///
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 60ae2e6..123033a 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -19,6 +19,7 @@
 #include "ConstraintGraph.h"
 #include "swift/AST/GenericEnvironment.h"
 #include "swift/Basic/Statistic.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Format.h"
@@ -213,17 +214,16 @@
 void ConstraintSystem::addTypeVariableConstraintsToWorkList(
        TypeVariableType *typeVar) {
   // Gather the constraints affected by a change to this type variable.
-  SmallVector<Constraint *, 8> constraints;
-  CG.gatherConstraints(typeVar, constraints,
-                       ConstraintGraph::GatheringKind::AllMentions);
+  llvm::SetVector<Constraint *> inactiveConstraints;
+  CG.gatherConstraints(
+      typeVar, inactiveConstraints, ConstraintGraph::GatheringKind::AllMentions,
+      [](Constraint *constraint) { return !constraint->isActive(); });
 
   // Add any constraints that aren't already active to the worklist.
-  for (auto constraint : constraints) {
-    if (!constraint->isActive()) {
-      ActiveConstraints.splice(ActiveConstraints.end(),
-                               InactiveConstraints, constraint);
-      constraint->setActive(true);
-    }
+  for (auto constraint : inactiveConstraints) {
+    ActiveConstraints.splice(ActiveConstraints.end(), InactiveConstraints,
+                             constraint);
+    constraint->setActive(true);
   }
 }
 
diff --git a/test/lit.cfg b/test/lit.cfg
index fb2701d..b9454b5 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -638,15 +638,12 @@
     elif run_os == 'ios' or run_os == 'tvos' or run_os == 'watchos':
         # iOS/tvOS/watchOS simulator
         if run_os == 'ios':
-            config.available_features('DARWIN_SIMULATOR=ios')
             lit_config.note("Testing iOS simulator " + config.variant_triple)
             xcrun_sdk_name = "iphonesimulator"
         elif run_os == 'watchos':
-            config.available_features('DARWIN_SIMULATOR=watchos')
             lit_config.note("Testing watchOS simulator " + config.variant_triple)
             xcrun_sdk_name = "watchsimulator"
         else:
-            config.available_features('DARWIN_SIMULATOR=tvos')
             lit_config.note("Testing AppleTV simulator " + config.variant_triple)
             xcrun_sdk_name = "appletvsimulator"
 
diff --git a/validation-test/Sema/type_checker_perf/fast/rdar19738292.swift.gyb b/validation-test/Sema/type_checker_perf/fast/rdar19738292.swift.gyb
index 3310736..0f86c0d 100644
--- a/validation-test/Sema/type_checker_perf/fast/rdar19738292.swift.gyb
+++ b/validation-test/Sema/type_checker_perf/fast/rdar19738292.swift.gyb
@@ -1,6 +1,7 @@
 // RUN: %scale-test --begin 7 --end 12 --step 1 --select incrementScopeCounter %s
 // REQUIRES: OS=macosx
 // REQUIRES: asserts
+// REQUIRES: rdar42650365
 
 let a = [[0]]
 _ = a[0][0]