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

Code before:
    return;
  }
  context.poisoned_concrete_impl_lookup_queries().push_back(
      {.loc_id = loc_id,
       .query = eval_query,
       .impl_witness = result.final_witness()});
}

auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
                                 SemIR::LookupImplWitness eval_query,
                                 SemIR::InstId self_facet_value_inst_id,
                                 EvalImplLookupMode mode)
    -> EvalImplLookupResult {
  auto query_specific_interface =
      context.specific_interfaces().Get(eval_query.query_specific_interface_id);

  // Ensure specifics don't substitute in weird things for the query self.
  CARBON_CHECK(context.types().IsFacetType(
      context.insts().Get(eval_query.query_self_inst_id).type_id()));
  SemIR::ConstantId query_self_const_id =
      context.constant_values().Get(eval_query.query_self_inst_id);

  auto query_type_structure = BuildTypeStructure(
      context, context.constant_values().GetInstId(query_self_const_id),
      query_specific_interface);
  if (!query_type_structure) {
    return EvalImplLookupResult::MakeNone();
  }

  auto facet_lookup_result = LookupImplWitnessInSelfFacetValue(
      context, loc_id, self_facet_value_inst_id, query_specific_interface);
  if (facet_lookup_result.has_final_value()) {
    return facet_lookup_result;
  }

  // If the self type is a facet that provides a witness, then we are in an
  // `interface` or an `impl`. In both cases, we don't want to do any impl
  // lookups. The query will eventually resolve to a concrete witness when it
  // can get it from the self facet value, when it has a specific applied in the
  // future.
  //
  // In particular, this avoids a LookupImplWitness instruction in the eval
  // block of an impl declaration from doing impl lookup. Specifically the
  // lookup of the implicit .Self in `impl ... where .X`. If it does impl lookup
  // when the eval block is run, it finds the same `impl`, tries to build a
  // specific from it, which runs the eval block, creating a recursive loop that
  // crashes.
  if (facet_lookup_result.has_value()) {
    if (auto bind = context.insts().TryGetAs<SemIR::SymbolicBinding>(
            eval_query.query_self_inst_id)) {
      const auto& entity = context.entity_names().Get(bind->entity_name_id);

Review comment (suggestion):
Regarding ordering of `query_type_structure` and `facet_lookup_result`, I see you're switching, but is there a particular reason for one ordering over the other? e.g. I assume `LookupImplWitnessInSelfFacetValue` could return a final value for valid code, and thus it may not be worth building the `query_type_structure` in that case. But is the converse also true, that `BuildTypeStructure` may return nothing for valid code?

(focusing on valid code on the idea that it's okay for invalid code to take longer)

Code after:
    return;
  }
  context.poisoned_concrete_impl_lookup_queries().push_back(
      {.loc_id = loc_id,
       .query = eval_query,
       .impl_witness = result.final_witness()});
}

auto EvalLookupSingleImplWitness(Context& context, SemIR::LocId loc_id,
                                 SemIR::LookupImplWitness eval_query,
                                 SemIR::InstId self_facet_value_inst_id,
                                 EvalImplLookupMode mode)
    -> EvalImplLookupResult {
  auto query_specific_interface =
      context.specific_interfaces().Get(eval_query.query_specific_interface_id);

  // Ensure specifics don't substitute in weird things for the query self.
  CARBON_CHECK(context.types().IsFacetType(
      context.insts().Get(eval_query.query_self_inst_id).type_id()));
  SemIR::ConstantId query_self_const_id =
      context.constant_values().Get(eval_query.query_self_inst_id);

  auto facet_lookup_result = LookupImplWitnessInSelfFacetValue(
      context, loc_id, self_facet_value_inst_id, query_specific_interface);
  if (facet_lookup_result.has_final_value()) {
    return facet_lookup_result;
  }

  // If the self type is a facet that provides a witness, then we are in an
  // `interface` or an `impl`. In both cases, we don't want to do any impl
  // lookups. The query will eventually resolve to a concrete witness when it
  // can get it from the self facet value, when it has a specific applied in the
  // future.
  //
  // In particular, this avoids a LookupImplWitness instruction in the eval
  // block of an impl declaration from doing impl lookup. Specifically the
  // lookup of the implicit .Self in `impl ... where .X`. If it does impl lookup
  // when the eval block is run, it finds the same `impl`, tries to build a
  // specific from it, which runs the eval block, creating a recursive loop that
  // crashes.
  if (facet_lookup_result.has_value()) {
    if (auto bind = context.insts().TryGetAs<SemIR::SymbolicBinding>(
            eval_query.query_self_inst_id)) {
      const auto& entity = context.entity_names().Get(bind->entity_name_id);
      if (entity.name_id == SemIR::NameId::PeriodSelf ||
          entity.name_id == SemIR::NameId::SelfType) {
        return facet_lookup_result;
      }
    }
  }