|
|
@@ -4,6 +4,7 @@
|
|
|
|
|
|
#include "toolchain/check/context.h"
|
|
|
#include "toolchain/check/convert.h"
|
|
|
+#include "toolchain/check/decl_name_stack.h"
|
|
|
#include "toolchain/check/modifiers.h"
|
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
#include "toolchain/sem_ir/typed_insts.h"
|
|
|
@@ -17,15 +18,15 @@ auto HandleImplIntroducer(Context& context, Parse::ImplIntroducerId parse_node)
|
|
|
context.inst_block_stack().Push();
|
|
|
|
|
|
// Push the bracketing node.
|
|
|
- context.node_stack().Push(parse_node,
|
|
|
- context.scope_stack().PeekNameScopeId());
|
|
|
+ context.node_stack().Push(parse_node);
|
|
|
|
|
|
// Optional modifiers follow.
|
|
|
context.decl_state_stack().Push(DeclState::Impl);
|
|
|
|
|
|
- // Create a scope for implicit parameters. We may not use it, but it's simpler
|
|
|
- // to create it unconditionally than to track whether it exists.
|
|
|
- context.scope_stack().Push();
|
|
|
+ // An impl doesn't have a name per se, but it makes the processing more
|
|
|
+ // consistent to imagine that it does. This also gives us a scope for implicit
|
|
|
+ // parameters.
|
|
|
+ context.decl_name_stack().PushScopeAndStartName();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
@@ -68,8 +69,7 @@ auto HandleDefaultSelfImplAs(Context& context,
|
|
|
// TODO: Do this without modifying the node stack.
|
|
|
auto implicit_param_list =
|
|
|
context.node_stack().PopWithParseNodeIf<Parse::NodeKind::ImplForall>();
|
|
|
- auto enclosing_scope_id =
|
|
|
- context.node_stack().Peek<Parse::NodeKind::ImplIntroducer>();
|
|
|
+ auto enclosing_scope_id = context.decl_name_stack().PeekTargetScope();
|
|
|
if (implicit_param_list) {
|
|
|
context.node_stack().Push(implicit_param_list->first,
|
|
|
implicit_param_list->second);
|
|
|
@@ -90,8 +90,9 @@ auto HandleDefaultSelfImplAs(Context& context,
|
|
|
// Process an `extend impl` declaration by extending the impl scope with the
|
|
|
// `impl`'s scope.
|
|
|
static auto ExtendImpl(Context& context, Parse::AnyImplDeclId parse_node,
|
|
|
- SemIR::TypeId constraint_id,
|
|
|
- SemIR::NameScopeId enclosing_scope_id) -> void {
|
|
|
+ SemIR::TypeId constraint_id) -> void {
|
|
|
+ auto enclosing_scope_id = context.decl_name_stack().PeekTargetScope();
|
|
|
+
|
|
|
// TODO: This is also valid in a mixin.
|
|
|
if (!TryAsClassScope(context, enclosing_scope_id)) {
|
|
|
CARBON_DIAGNOSTIC(ExtendImplOutsideClass, Error,
|
|
|
@@ -120,26 +121,17 @@ static auto ExtendImpl(Context& context, Parse::AnyImplDeclId parse_node,
|
|
|
enclosing_scope.extended_scopes.push_back(interface.scope_id);
|
|
|
}
|
|
|
|
|
|
-namespace {
|
|
|
-struct BuildImplDeclResult {
|
|
|
- SemIR::ImplId impl_id;
|
|
|
- SemIR::InstId impl_decl_id;
|
|
|
- SemIR::NameScopeId enclosing_scope_id;
|
|
|
-};
|
|
|
-} // namespace
|
|
|
-
|
|
|
// Build an ImplDecl describing the signature of an impl. This handles the
|
|
|
// common logic shared by impl forward declarations and impl definitions.
|
|
|
static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId parse_node)
|
|
|
- -> BuildImplDeclResult {
|
|
|
+ -> std::pair<SemIR::ImplId, SemIR::InstId> {
|
|
|
auto [constraint_node, constraint_id] =
|
|
|
context.node_stack().PopExprWithParseNode();
|
|
|
auto self_type_id = context.node_stack().Pop<Parse::NodeCategory::ImplAs>();
|
|
|
|
|
|
auto params_id = context.node_stack().PopIf<Parse::NodeKind::ImplForall>();
|
|
|
auto decl_block_id = context.inst_block_stack().Pop();
|
|
|
- auto enclosing_scope_id =
|
|
|
- context.node_stack().Pop<Parse::NodeKind::ImplIntroducer>();
|
|
|
+ context.node_stack().PopForSoloParseNode<Parse::NodeKind::ImplIntroducer>();
|
|
|
|
|
|
// Convert the constraint expression to a type.
|
|
|
// TODO: Check that its constant value is a constraint.
|
|
|
@@ -151,6 +143,11 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId parse_node)
|
|
|
LimitModifiersOnDecl(context, KeywordModifierSet::ImplDecl,
|
|
|
Lex::TokenKind::Impl);
|
|
|
|
|
|
+ // Finish processing the name, which should be empty, but might have
|
|
|
+ // parameters.
|
|
|
+ auto name_context = context.decl_name_stack().FinishImplName();
|
|
|
+ CARBON_CHECK(name_context.state == DeclNameStack::NameContext::State::Empty);
|
|
|
+
|
|
|
// Add the impl declaration.
|
|
|
auto impl_decl = SemIR::ImplDecl{SemIR::ImplId::Invalid, decl_block_id};
|
|
|
auto impl_decl_id = context.AddPlaceholderInst({parse_node, impl_decl});
|
|
|
@@ -172,25 +169,24 @@ static auto BuildImplDecl(Context& context, Parse::AnyImplDeclId parse_node)
|
|
|
KeywordModifierSet::Extend)) {
|
|
|
// TODO: Diagnose combining `extend` with `forall`.
|
|
|
// TODO: Diagnose combining `extend` with an explicit self type.
|
|
|
- ExtendImpl(context, parse_node, constraint_type_id, enclosing_scope_id);
|
|
|
+ ExtendImpl(context, parse_node, constraint_type_id);
|
|
|
}
|
|
|
|
|
|
context.decl_state_stack().Pop(DeclState::Impl);
|
|
|
|
|
|
- return {impl_decl.impl_id, impl_decl_id, enclosing_scope_id};
|
|
|
+ return {impl_decl.impl_id, impl_decl_id};
|
|
|
}
|
|
|
|
|
|
auto HandleImplDecl(Context& context, Parse::ImplDeclId parse_node) -> bool {
|
|
|
BuildImplDecl(context, parse_node);
|
|
|
- context.scope_stack().Pop();
|
|
|
+ context.decl_name_stack().PopScope();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
auto HandleImplDefinitionStart(Context& context,
|
|
|
Parse::ImplDefinitionStartId parse_node)
|
|
|
-> bool {
|
|
|
- auto [impl_id, impl_decl_id, enclosing_scope_id] =
|
|
|
- BuildImplDecl(context, parse_node);
|
|
|
+ auto [impl_id, impl_decl_id] = BuildImplDecl(context, parse_node);
|
|
|
auto& impl_info = context.impls().Get(impl_id);
|
|
|
|
|
|
if (impl_info.definition_id.is_valid()) {
|
|
|
@@ -207,8 +203,9 @@ auto HandleImplDefinitionStart(Context& context,
|
|
|
.Emit();
|
|
|
} else {
|
|
|
impl_info.definition_id = impl_decl_id;
|
|
|
- impl_info.scope_id = context.name_scopes().Add(
|
|
|
- impl_decl_id, SemIR::NameId::Invalid, enclosing_scope_id);
|
|
|
+ impl_info.scope_id =
|
|
|
+ context.name_scopes().Add(impl_decl_id, SemIR::NameId::Invalid,
|
|
|
+ context.decl_name_stack().PeekTargetScope());
|
|
|
}
|
|
|
|
|
|
context.scope_stack().Push(impl_decl_id, impl_info.scope_id);
|
|
|
@@ -234,9 +231,7 @@ auto HandleImplDefinition(Context& context,
|
|
|
auto impl_id =
|
|
|
context.node_stack().Pop<Parse::NodeKind::ImplDefinitionStart>();
|
|
|
context.inst_block_stack().Pop();
|
|
|
- // Pop the impl body scope and the parameter scope.
|
|
|
- context.scope_stack().Pop();
|
|
|
- context.scope_stack().Pop();
|
|
|
+ context.decl_name_stack().PopScope();
|
|
|
|
|
|
// The impl is now fully defined.
|
|
|
context.impls().Get(impl_id).defined = true;
|