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

Code before:
      Parse::NodeKind::IdentifierNameNotBeforeParams) {
    context.pattern_block_stack().Push();
    context.full_pattern_stack().PushFullPattern(
        FullPatternStack::Kind::ExplicitParamList);
  }

  auto return_slot_pattern_id = AddPatternInst<SemIR::ReturnSlotPattern>(
      context, node_id,
      {.type_id = as_type.type_id, .type_inst_id = as_type.inst_id});
  auto param_pattern_id = AddPatternInst<SemIR::OutParamPattern>(
      context, node_id,
      {.type_id = as_type.type_id,
       .subpattern_id = return_slot_pattern_id,
       .index = SemIR::CallParamIndex::None});
  context.node_stack().Push(node_id, param_pattern_id);
  return true;
}

// Returns the ID of the self parameter pattern, or None.
// TODO: Do this during initial traversal of implicit params.
static auto FindSelfPattern(Context& context,
                            SemIR::InstBlockId implicit_param_patterns_id)
    -> SemIR::InstId {
  auto implicit_param_patterns =
      context.inst_blocks().GetOrEmpty(implicit_param_patterns_id);
  return FindIfOrDefault(
      implicit_param_patterns,
      [&](auto implicit_param_id) {
        return SemIR::IsSelfPattern(context.sem_ir(), implicit_param_id);
      },
      SemIR::InstId::None);
}

// Diagnoses issues with the modifiers, removing modifiers that shouldn't be
// present.
static auto DiagnoseModifiers(Context& context,
                              Parse::AnyFunctionDeclId node_id,
                              DeclIntroducerState& introducer,
                              bool is_definition,
                              SemIR::InstId parent_scope_inst_id,
                              std::optional<SemIR::Inst> parent_scope_inst,
                              SemIR::InstId self_param_id) -> void {
  CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);
  LimitModifiersOnDecl(context, introducer,
                       KeywordModifierSet::Access | KeywordModifierSet::Extern |
                           KeywordModifierSet::Method |
                           KeywordModifierSet::Interface);
  RestrictExternModifierOnDecl(context, introducer, parent_scope_inst,
                               is_definition);
  CheckMethodModifiersOnFunction(context, introducer, parent_scope_inst_id,
                                 parent_scope_inst);

Review comment (suggestion):
I wonder how often we'd use a `FindIfOrNone` variant that returns `value_type::None` if not found.

Code after:
      Parse::NodeKind::IdentifierNameNotBeforeParams) {
    context.pattern_block_stack().Push();
    context.full_pattern_stack().PushFullPattern(
        FullPatternStack::Kind::ExplicitParamList);
  }

  auto return_slot_pattern_id = AddPatternInst<SemIR::ReturnSlotPattern>(
      context, node_id,
      {.type_id = as_type.type_id, .type_inst_id = as_type.inst_id});
  auto param_pattern_id = AddPatternInst<SemIR::OutParamPattern>(
      context, node_id,
      {.type_id = as_type.type_id,
       .subpattern_id = return_slot_pattern_id,
       .index = SemIR::CallParamIndex::None});
  context.node_stack().Push(node_id, param_pattern_id);
  return true;
}

// Returns the ID of the self parameter pattern, or None.
// TODO: Do this during initial traversal of implicit params.
static auto FindSelfPattern(Context& context,
                            SemIR::InstBlockId implicit_param_patterns_id)
    -> SemIR::InstId {
  auto implicit_param_patterns =
      context.inst_blocks().GetOrEmpty(implicit_param_patterns_id);
  return FindIfOrNone(implicit_param_patterns, [&](auto implicit_param_id) {
    return SemIR::IsSelfPattern(context.sem_ir(), implicit_param_id);
  });
}

// Diagnoses issues with the modifiers, removing modifiers that shouldn't be
// present.
static auto DiagnoseModifiers(Context& context,
                              Parse::AnyFunctionDeclId node_id,
                              DeclIntroducerState& introducer,
                              bool is_definition,
                              SemIR::InstId parent_scope_inst_id,
                              std::optional<SemIR::Inst> parent_scope_inst,
                              SemIR::InstId self_param_id) -> void {
  CheckAccessModifiersOnDecl(context, introducer, parent_scope_inst);
  LimitModifiersOnDecl(context, introducer,
                       KeywordModifierSet::Access | KeywordModifierSet::Extern |
                           KeywordModifierSet::Method |
                           KeywordModifierSet::Interface);
  RestrictExternModifierOnDecl(context, introducer, parent_scope_inst,
                               is_definition);
  CheckMethodModifiersOnFunction(context, introducer, parent_scope_inst_id,
                                 parent_scope_inst);
  RequireDefaultFinalOnlyInInterfaces(context, introducer, parent_scope_inst);

  if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Interface)) {