Repository: carbon-language/carbon-lang
File: toolchain/check/check.cpp (C++)

Code before:
    // conflict with an explicit import of the prelude.
    if (options.prelude_import &&
        !(packaging && packaging->names.package_id == PackageNameId::Core)) {
      auto prelude_id =
          unit_info.unit->value_stores->string_literal_values().Add("prelude");
      TrackImport(api_map, &explicit_import_map, unit_info,
                  {.node_id = Parse::NoneNodeId(),
                   .package_id = PackageNameId::Core,
                   .library_id = prelude_id},
                  options.fuzzing);
    }

    for (const auto& import : unit_info.parse_tree().imports()) {
      TrackImport(api_map, &explicit_import_map, unit_info, import,
                  options.fuzzing);
    }

    // If there were no imports, mark the file as ready to check for below.
    if (unit_info.imports_remaining == 0) {
      ready_to_check.push_back(&unit_info);
    }
  }

  std::string target = !options.target.empty()
                           ? options.target.str()
                           : llvm::sys::getDefaultTargetTriple();

  // Check everything with no dependencies. Earlier entries with dependencies
  // will be checked as soon as all their dependencies have been checked.
  for (int check_index = 0;
       check_index < static_cast<int>(ready_to_check.size()); ++check_index) {
    auto* unit_info = ready_to_check[check_index];
    CheckUnit(unit_info, tree_and_subtrees_getters, fs, target,
              options.vlog_stream)
        .Run();
    for (auto* incoming_import : unit_info->incoming_imports) {
      --incoming_import->imports_remaining;
      if (incoming_import->imports_remaining == 0) {
        ready_to_check.push_back(incoming_import);
      }
    }
  }

  // If there are still units with remaining imports, it means there's a
  // dependency loop.
  if (ready_to_check.size() < unit_infos.size()) {
    // Go through units and mask out unevaluated imports. This breaks everything
    // associated with a loop equivalently, whether it's part of it or depending
    // on a part of it.
    // TODO: Better identify cycles, maybe try to untangle them.
    for (auto& unit_info : unit_infos) {

Review comment (bug):
I think this target defaulting logic should not be in check, and should instead live in the caller. (The language server in this case, which in turn should probably be getting the triple from a compilation database or similar eventually.)

It's probably reasonable to instead CHECK-fail here if the target isn't set.

Code after:
    if (options.prelude_import &&
        !(packaging && packaging->names.package_id == PackageNameId::Core)) {
      auto prelude_id =
          unit_info.unit->value_stores->string_literal_values().Add("prelude");
      TrackImport(api_map, &explicit_import_map, unit_info,
                  {.node_id = Parse::NoneNodeId(),
                   .package_id = PackageNameId::Core,
                   .library_id = prelude_id},
                  options.fuzzing);
    }

    for (const auto& import : unit_info.parse_tree().imports()) {
      TrackImport(api_map, &explicit_import_map, unit_info, import,
                  options.fuzzing);
    }

    // If there were no imports, mark the file as ready to check for below.
    if (unit_info.imports_remaining == 0) {
      ready_to_check.push_back(&unit_info);
    }
  }

  // Check everything with no dependencies. Earlier entries with dependencies
  // will be checked as soon as all their dependencies have been checked.
  for (int check_index = 0;
       check_index < static_cast<int>(ready_to_check.size()); ++check_index) {
    auto* unit_info = ready_to_check[check_index];
    CheckUnit(unit_info, tree_and_subtrees_getters, fs, target,
              options.vlog_stream)
        .Run();
    for (auto* incoming_import : unit_info->incoming_imports) {
      --incoming_import->imports_remaining;
      if (incoming_import->imports_remaining == 0) {
        ready_to_check.push_back(incoming_import);
      }
    }
  }

  // If there are still units with remaining imports, it means there's a
  // dependency loop.
  if (ready_to_check.size() < unit_infos.size()) {
    // Go through units and mask out unevaluated imports. This breaks everything
    // associated with a loop equivalently, whether it's part of it or depending
    // on a part of it.
    // TODO: Better identify cycles, maybe try to untangle them.
    for (auto& unit_info : unit_infos) {
      if (unit_info.imports_remaining > 0) {
        for (auto& package_imports : unit_info.package_imports) {
          for (auto* import_it = package_imports.imports.begin();
               import_it != package_imports.imports.end();) {
            if (import_it->unit_info->is_checked) {