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

Code before:
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "toolchain/check/context.h"
#include "toolchain/check/decl_introducer_state.h"
#include "toolchain/check/generic.h"
#include "toolchain/check/handle.h"
#include "toolchain/check/inst.h"
#include "toolchain/check/modifiers.h"
#include "toolchain/check/name_component.h"
#include "toolchain/check/name_lookup.h"
#include "toolchain/check/type.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst.h"
#include "toolchain/sem_ir/name_scope.h"
#include "toolchain/sem_ir/typed_insts.h"

namespace Carbon::Check {

auto HandleParseNode(Context& context, Parse::NamespaceStartId /*node_id*/)
    -> bool {
  // Optional modifiers and the name follow.
  context.decl_introducer_state_stack().Push<Lex::TokenKind::Namespace>();
  context.decl_name_stack().PushScopeAndStartName();
  // Namespaces can't be generic, but we might have parsed a generic parameter
  // in their name, so enter a generic scope just in case.
  StartGenericDecl(context);
  return true;
}

static auto IsNamespaceScope(Context& context, SemIR::NameScopeId name_scope_id)
    -> bool {
  auto [_, inst] = context.name_scopes().GetInstIfValid(name_scope_id);
  return inst && inst->Is<SemIR::Namespace>();
}

auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool {
  auto name_context = context.decl_name_stack().FinishName(
      PopNameComponentWithoutParams(context, Lex::TokenKind::Namespace));

  DiscardGenericDecl(context);

  auto introducer =
      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Namespace>();
  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::None);

  auto namespace_inst =
      SemIR::Namespace{GetSingletonType(context, SemIR::NamespaceType::InstId),
                       SemIR::NameScopeId::None, SemIR::InstId::None};
  auto namespace_id = AddPlaceholderInst(context, node_id, namespace_inst);

  SemIR::ScopeLookupResult lookup_result =

Review comment (suggestion):
Minor, but it feels weird to me how the push and pop is in a different order, versus having `StartGenericDecl` called before `PushScope` (in all of these)

Code after:
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "toolchain/check/context.h"
#include "toolchain/check/decl_introducer_state.h"
#include "toolchain/check/generic.h"
#include "toolchain/check/handle.h"
#include "toolchain/check/inst.h"
#include "toolchain/check/modifiers.h"
#include "toolchain/check/name_component.h"
#include "toolchain/check/name_lookup.h"
#include "toolchain/check/type.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst.h"
#include "toolchain/sem_ir/name_scope.h"
#include "toolchain/sem_ir/typed_insts.h"

namespace Carbon::Check {

auto HandleParseNode(Context& context, Parse::NamespaceStartId /*node_id*/)
    -> bool {
  // Namespaces can't be generic, but we might have parsed a generic parameter
  // in their name, so enter a generic scope just in case.
  StartGenericDecl(context);
  // Optional modifiers and the name follow.
  context.decl_introducer_state_stack().Push<Lex::TokenKind::Namespace>();
  context.decl_name_stack().PushScopeAndStartName();
  return true;
}

static auto IsNamespaceScope(Context& context, SemIR::NameScopeId name_scope_id)
    -> bool {
  auto [_, inst] = context.name_scopes().GetInstIfValid(name_scope_id);
  return inst && inst->Is<SemIR::Namespace>();
}

auto HandleParseNode(Context& context, Parse::NamespaceId node_id) -> bool {
  auto name_context = context.decl_name_stack().FinishName(
      PopNameComponentWithoutParams(context, Lex::TokenKind::Namespace));

  DiscardGenericDecl(context);

  auto introducer =
      context.decl_introducer_state_stack().Pop<Lex::TokenKind::Namespace>();
  LimitModifiersOnDecl(context, introducer, KeywordModifierSet::None);

  auto namespace_inst =
      SemIR::Namespace{GetSingletonType(context, SemIR::NamespaceType::InstId),
                       SemIR::NameScopeId::None, SemIR::InstId::None};
  auto namespace_id = AddPlaceholderInst(context, node_id, namespace_inst);

  SemIR::ScopeLookupResult lookup_result =