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

Code before:
    // actually use all its generic bindings, and will never be matched. This
    // should be diagnossed to the user.
    bool has_error_in_implicit_pattern = false;
    if (name.implicit_param_patterns_id.has_value()) {
      for (auto inst_id :
           context.inst_blocks().Get(name.implicit_param_patterns_id)) {
        if (inst_id == SemIR::ErrorInst::InstId) {
          has_error_in_implicit_pattern = true;
          break;
        }
      }
    }

    if (!has_error_in_implicit_pattern) {
      DiagnoseUnusedGenericBinding(context, node_id, name, impl_decl.impl_id);
    }
  } else {
    auto& stored_impl_info = context.impls().Get(impl_decl.impl_id);
    FinishGenericRedecl(context, stored_impl_info.generic_id);
  }

  // Write the impl ID into the ImplDecl.
  ReplaceInstBeforeConstantUse(context, impl_decl_id, impl_decl);

  // For an `extend impl` declaration, mark the impl as extending this `impl`.
  if (self_type_inst_id != SemIR::ErrorInst::TypeInstId &&
      introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
    auto& stored_impl_info = context.impls().Get(impl_decl.impl_id);

    auto extend_node = introducer.modifier_node_id(ModifierOrder::Extend);
    if (stored_impl_info.generic_id.has_value()) {
      constraint_type_inst_id = AddTypeInst<SemIR::SpecificConstant>(
          context, SemIR::LocId(constraint_type_inst_id),
          {.type_id = SemIR::TypeType::TypeId,
           .inst_id = constraint_type_inst_id,
           .specific_id = context.generics().GetSelfSpecific(
               stored_impl_info.generic_id)});
    }
    if (!ExtendImpl(context, extend_node, node_id, impl_decl.impl_id,
                    self_type_node, stored_impl_info.self_id,
                    name.implicit_params_loc_id, constraint_type_inst_id,
                    constraint_type_id)) {
      // Don't allow the invalid impl to be used.
      FillImplWitnessWithErrors(context, stored_impl_info);
    }
  }

  // Impl definitions are required in the same file as the declaration. We skip
  // this requirement if we've already issued an invalid redeclaration error, or
  // there is an error that would prevent the impl from being legal to define.
  if (!is_definition) {

Review comment (suggestion):
I think still want to look at `GetTypeIdForTypeInstId(self_type_inst_id)` here, in order to handle the case where we have a `Self` type expression but it contains an error. (The `Self` could have an error nested within it without being an error instruction.) For example:
```carbon
interface I {}
impl nonexistent* as I {}
```

Code after:
    bool has_error_in_implicit_pattern = false;
    if (name.implicit_param_patterns_id.has_value()) {
      for (auto inst_id :
           context.inst_blocks().Get(name.implicit_param_patterns_id)) {
        if (inst_id == SemIR::ErrorInst::InstId) {
          has_error_in_implicit_pattern = true;
          break;
        }
      }
    }

    if (!has_error_in_implicit_pattern) {
      DiagnoseUnusedGenericBinding(context, node_id, name, impl_decl.impl_id);
    }
  } else {
    auto& stored_impl_info = context.impls().Get(impl_decl.impl_id);
    FinishGenericRedecl(context, stored_impl_info.generic_id);
  }

  // Write the impl ID into the ImplDecl.
  ReplaceInstBeforeConstantUse(context, impl_decl_id, impl_decl);

  // For an `extend impl` declaration, mark the impl as extending this `impl`.
  if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) {
    auto& stored_impl_info = context.impls().Get(impl_decl.impl_id);
    auto self_type_id =
        context.types().GetTypeIdForTypeInstId(stored_impl_info.self_id);
    if (self_type_id != SemIR::ErrorInst::TypeId) {
      auto extend_node = introducer.modifier_node_id(ModifierOrder::Extend);
      if (stored_impl_info.generic_id.has_value()) {
        constraint_type_inst_id = AddTypeInst<SemIR::SpecificConstant>(
            context, SemIR::LocId(constraint_type_inst_id),
            {.type_id = SemIR::TypeType::TypeId,
             .inst_id = constraint_type_inst_id,
             .specific_id = context.generics().GetSelfSpecific(
                 stored_impl_info.generic_id)});
      }
      if (!ExtendImpl(context, extend_node, node_id, impl_decl.impl_id,
                      self_type_node, self_type_id, name.implicit_params_loc_id,
                      constraint_type_inst_id, constraint_type_id)) {
        // Don't allow the invalid impl to be used.
        FillImplWitnessWithErrors(context, stored_impl_info);
      }
    }
  }

  // Impl definitions are required in the same file as the declaration. We skip
  // this requirement if we've already issued an invalid redeclaration error, or
  // there is an error that would prevent the impl from being legal to define.
  if (!is_definition) {
    auto& stored_impl_info = context.impls().Get(impl_decl.impl_id);