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

Code before:
  // final impls only in that case. Note as in the CHECK above, the query can
  // not be concrete in this case, so only final impls can produce a concrete
  // witness for this query.
  auto candidates = CollectCandidateImplsForQuery(
      context, facet_lookup_result.has_value(), query_self_const_id,
      *query_type_structure, query_specific_interface);

  bool query_is_concrete =
      QueryIsConcrete(context, query_self_const_id, query_specific_interface);
  CARBON_CHECK(!query_is_concrete || !facet_lookup_result.has_value(),
               "Non-concrete facet lookup value for concrete query");

  // Perform a lookup for an `impl` that matches the query. If we don't find a
  // final impl, the self value may still have been a facet that provides a
  // symbolic witness in the `facet_lookup_result`, which we want to fall back
  // to. It records that an `impl` will exist for the query, but is yet unknown.

  struct LookupResult {
    EvalImplLookupResult result;
    std::optional<TypeStructure> impl_type_structure;
    SemIR::LocId impl_loc = SemIR::LocId::None;
  };

  LookupResult lookup_result = {.result = facet_lookup_result};

  for (auto [impl, type_structure] : candidates.impls) {
    SemIR::LocId candidate_loc_id(impl->definition_id);

    // In deferred lookup for a symbolic impl witness, while building a
    // specific, there may be no stack yet as this may be the first lookup. If
    // further lookups are started as a result in deduce, they will build the
    // stack.
    if (!context.impl_lookup_stack().empty()) {
      context.impl_lookup_stack().back().impl_loc = candidate_loc_id;
    }

    auto result = GetWitnessIdForImpl(context, loc_id, query_is_concrete,
                                      query_self_const_id,
                                      query_specific_interface, *impl);
    if (result.has_value()) {
      PoisonImplLookupQuery(context, loc_id, mode, eval_query, result, *impl);
      lookup_result = {.result = result,
                       .impl_type_structure = std::move(type_structure),
                       .impl_loc = candidate_loc_id};
      break;
    }
  }

  if (query_is_concrete && candidates.consider_cpp_candidates) {
    // Also check for a C++ candidate that is a better match than whatever
    // `impl` we may have found in Carbon.

Review comment (suggestion):
Looking at this change, maybe `impl_type_structure` could store a pointer instead of a `std::optional`? That is, the lifetime of `candidates` is long enough that it'd actually be fine here, and it'd also avoid the ternary below.

Code after:
  // final impls only in that case. Note as in the CHECK above, the query can
  // not be concrete in this case, so only final impls can produce a concrete
  // witness for this query.
  auto candidates = CollectCandidateImplsForQuery(
      context, facet_lookup_result.has_value(), query_self_const_id,
      *query_type_structure, query_specific_interface);

  bool query_is_concrete =
      QueryIsConcrete(context, query_self_const_id, query_specific_interface);
  CARBON_CHECK(!query_is_concrete || !facet_lookup_result.has_value(),
               "Non-concrete facet lookup value for concrete query");

  // Perform a lookup for an `impl` that matches the query. If we don't find a
  // final impl, the self value may still have been a facet that provides a
  // symbolic witness in the `facet_lookup_result`, which we want to fall back
  // to. It records that an `impl` will exist for the query, but is yet unknown.

  struct LookupResult {
    EvalImplLookupResult result;
    const TypeStructure* impl_type_structure = nullptr;
    SemIR::LocId impl_loc_id = SemIR::LocId::None;
  };

  LookupResult lookup_result = {.result = facet_lookup_result};

  for (const auto& candidate : candidates.impls) {
    const auto& impl = *candidate.impl;

    // In deferred lookup for a symbolic impl witness, while building a
    // specific, there may be no stack yet as this may be the first lookup. If
    // further lookups are started as a result in deduce, they will build the
    // stack.
    if (!context.impl_lookup_stack().empty()) {
      context.impl_lookup_stack().back().impl_loc = impl.definition_id;
    }

    auto result = GetWitnessIdForImpl(context, loc_id, query_is_concrete,
                                      query_self_const_id,
                                      query_specific_interface, impl);
    if (result.has_value()) {
      PoisonImplLookupQuery(context, loc_id, mode, eval_query, result, impl);
      lookup_result = {.result = result,
                       .impl_type_structure = &candidate.type_structure,
                       .impl_loc_id = SemIR::LocId(impl.definition_id)};
      break;
    }
  }

  if (query_is_concrete && candidates.consider_cpp_candidates) {
    // Also check for a C++ candidate that is a better match than whatever
    // `impl` we may have found in Carbon.