Repository: apple/swift
File: lib/Sema/ConstraintSystem.cpp (C++)

Code before:
    // Set up solver state.
    SolverState state(*this, FreeTypeVariableBinding::Disallow);
    state.recordFixes = true;

    // Solve the system.
    solveImpl(viable);

    // If we hit a threshold, we're done.
    if (isTooComplex(viable))
      return SolutionResult::forTooComplex(getTooComplexRange());

    // Before removing any "fixed" solutions, let's check
    // if ambiguity is caused by fixes and diagnose if possible.
    if (diagnoseAmbiguityWithFixes(viable))
      return SolutionResult::forAmbiguous(viable);

    // Check whether we have a best solution; this can happen if we found
    // a series of fixes that worked.
    if (auto best = findBestSolution(viable, /*minimize=*/true)) {
      if (*best != 0)
        viable[0] = std::move(viable[*best]);
      viable.erase(viable.begin() + 1, viable.end());

      if (getASTContext().TypeCheckerOpts.CrashOnValidSalvage) {
        auto &solution = viable[0];
        if (solution.Fixes.empty() &&
            diagnosticTransaction == nullptr &&
            !getASTContext().LangOpts.DisableAvailabilityChecking &&
            solution.getFixedScore().Data[SK_Unavailable] == 0) {
          ABORT([&](auto &out) {
            out << "Found valid solution in salvage()\n\n";
            solution.dump(out, 0);
          });
        }
      }

      return SolutionResult::forSolved(std::move(viable[0]));
    }

    if (shouldSuppressDiagnostics())
      return viable.empty() ? SolutionResult::forUndiagnosedError()
                            : SolutionResult::forAmbiguous(viable);

    // FIXME: If we were able to actually fix things along the way,
    // we may have to hunt for the best solution. For now, we don't care.

    // Remove solutions that require fixes; the fixes in those systems should
    // be diagnosed rather than any ambiguity.
    auto hasFixes = [](const Solution &sol) { return !sol.Fixes.empty(); };
    auto newEnd = std::remove_if(viable.begin(), viable.end(), hasFixes);
    viable.erase(newEnd, viable.end());

Review comment (suggestion):
Might replace this with SK_Fix and SK_Hole checks, it's possible to get SK_Hole without fixes, that's not a valid solution.

Code after:
    // Set up solver state.
    SolverState state(*this, FreeTypeVariableBinding::Disallow);
    state.recordFixes = true;

    // Solve the system.
    solveImpl(viable);

    // If we hit a threshold, we're done.
    if (isTooComplex(viable))
      return SolutionResult::forTooComplex(getTooComplexRange());

    // Before removing any "fixed" solutions, let's check
    // if ambiguity is caused by fixes and diagnose if possible.
    if (diagnoseAmbiguityWithFixes(viable))
      return SolutionResult::forAmbiguous(viable);

    // Check whether we have a best solution; this can happen if we found
    // a series of fixes that worked.
    if (auto best = findBestSolution(viable, /*minimize=*/true)) {
      if (*best != 0)
        viable[0] = std::move(viable[*best]);
      viable.erase(viable.begin() + 1, viable.end());

      if (getASTContext().TypeCheckerOpts.CrashOnValidSalvage) {
        auto &solution = viable[0];
        if (solution.Fixes.empty() &&
            diagnosticTransaction == nullptr &&
            !getASTContext().LangOpts.DisableAvailabilityChecking &&
            solution.getFixedScore().Data[SK_Unavailable] == 0 &&
            solution.getFixedScore().Data[SK_Hole] == 0 &&
            solution.getFixedScore().Data[SK_Fix] == 0) {
          ABORT([&](auto &out) {
            out << "Found valid solution in salvage()\n\n";
            solution.dump(out, 0);
          });
        }
      }

      return SolutionResult::forSolved(std::move(viable[0]));
    }

    if (shouldSuppressDiagnostics())
      return viable.empty() ? SolutionResult::forUndiagnosedError()
                            : SolutionResult::forAmbiguous(viable);

    // FIXME: If we were able to actually fix things along the way,
    // we may have to hunt for the best solution. For now, we don't care.

    // Remove solutions that require fixes; the fixes in those systems should
    // be diagnosed rather than any ambiguity.
    auto hasFixes = [](const Solution &sol) { return !sol.Fixes.empty(); };