18
18
#include " toolchain/diagnostics/diagnostic_emitter.h"
19
19
#include " toolchain/diagnostics/format_providers.h"
20
20
#include " toolchain/lex/token_kind.h"
21
+ #include " toolchain/parse/node_ids.h"
21
22
#include " toolchain/parse/node_kind.h"
22
23
#include " toolchain/parse/typed_nodes.h"
23
24
#include " toolchain/sem_ir/ids.h"
29
30
30
31
namespace Carbon ::Check {
31
32
32
- // Handles the start of a declaration of an associated constant.
33
- static auto StartAssociatedConstant (Context& context) -> void {
34
- // An associated constant is always generic.
35
- StartGenericDecl (context);
36
- // Collect the declarations nested in the associated constant in a decl
37
- // block. This is popped by FinishAssociatedConstantDecl.
38
- context.inst_block_stack ().Push ();
39
- }
40
-
41
33
// Handles the end of the declaration region of an associated constant. This is
42
34
// called at the `=` or the `;` of the declaration, whichever comes first.
43
35
static auto EndAssociatedConstantDeclRegion (Context& context,
@@ -95,10 +87,16 @@ static auto HandleIntroducer(Context& context, Parse::NodeId node_id) -> bool {
95
87
}
96
88
97
89
auto HandleParseNode (Context& context, Parse::LetIntroducerId node_id) -> bool {
98
- if (context.scope_stack ().GetCurrentScopeAs <SemIR::InterfaceDecl>()) {
99
- StartAssociatedConstant (context);
100
- }
90
+ return HandleIntroducer<Lex::TokenKind::Let>(context, node_id);
91
+ }
101
92
93
+ auto HandleParseNode (Context& context,
94
+ Parse::AssociatedConstantIntroducerId node_id) -> bool {
95
+ // An associated constant is always generic.
96
+ StartGenericDecl (context);
97
+ // Collect the declarations nested in the associated constant in a decl
98
+ // block. This is popped by FinishAssociatedConstantDecl.
99
+ context.inst_block_stack ().Push ();
102
100
return HandleIntroducer<Lex::TokenKind::Let>(context, node_id);
103
101
}
104
102
@@ -177,14 +175,18 @@ static auto HandleInitializer(Context& context, Parse::NodeId node_id) -> bool {
177
175
178
176
auto HandleParseNode (Context& context, Parse::LetInitializerId node_id)
179
177
-> bool {
180
- if (auto interface_decl =
181
- context.scope_stack ().GetCurrentScopeAs <SemIR::InterfaceDecl>()) {
182
- auto generic_id =
183
- EndAssociatedConstantDeclRegion (context, interface_decl->interface_id );
178
+ return HandleInitializer (context, node_id);
179
+ }
184
180
185
- // Start building the definition region of the constant.
186
- StartGenericDefinition (context, generic_id);
187
- }
181
+ auto HandleParseNode (Context& context,
182
+ Parse::AssociatedConstantInitializerId node_id) -> bool {
183
+ auto interface_decl =
184
+ context.scope_stack ().GetCurrentScopeAs <SemIR::InterfaceDecl>();
185
+ auto generic_id =
186
+ EndAssociatedConstantDeclRegion (context, interface_decl->interface_id );
187
+
188
+ // Start building the definition region of the constant.
189
+ StartGenericDefinition (context, generic_id);
188
190
189
191
return HandleInitializer (context, node_id);
190
192
}
@@ -232,11 +234,10 @@ static auto HandleDecl(Context& context) -> DeclInfo {
232
234
} else {
233
235
// For an associated constant declaration, handle the completed declaration
234
236
// now. We will have done this at the `=` if there was an initializer.
235
- if (IntroducerTokenKind == Lex::TokenKind::Let) {
236
- if (auto interface_decl =
237
- context.scope_stack ().GetCurrentScopeAs <SemIR::InterfaceDecl>()) {
238
- EndAssociatedConstantDeclRegion (context, interface_decl->interface_id );
239
- }
237
+ if (IntroducerNodeKind == Parse::NodeKind::AssociatedConstantIntroducer) {
238
+ auto interface_decl =
239
+ context.scope_stack ().GetCurrentScopeAs <SemIR::InterfaceDecl>();
240
+ EndAssociatedConstantDeclRegion (context, interface_decl->interface_id );
240
241
}
241
242
242
243
EndFullPattern (context);
@@ -261,23 +262,59 @@ static auto HandleDecl(Context& context) -> DeclInfo {
261
262
return decl_info;
262
263
}
263
264
264
- // Finishes an associated constant declaration. This is called at the `;` to
265
- // perform any final steps. The `AssociatedConstantDecl` instruction and the
266
- // corresponding `AssociatedConstant` entity are built as part of handling the
267
- // binding pattern, but we still need to finish building the `Generic` object
268
- // and attach the default value, if any is specified.
269
- static auto FinishAssociatedConstant (Context& context, Parse::LetDeclId node_id,
270
- SemIR::InterfaceId interface_id,
271
- DeclInfo& decl_info) -> void {
265
+ auto HandleParseNode (Context& context, Parse::LetDeclId node_id) -> bool {
266
+ auto decl_info =
267
+ HandleDecl<Lex::TokenKind::Let, Parse::NodeKind::LetIntroducer,
268
+ Parse::NodeKind::LetInitializer>(context);
269
+
270
+ LimitModifiersOnDecl (
271
+ context, decl_info.introducer ,
272
+ KeywordModifierSet::Access | KeywordModifierSet::Interface);
273
+
274
+ // Diagnose interface modifiers given that we're not building an associated
275
+ // constant. We use this rather than `LimitModifiersOnDecl` to get a more
276
+ // specific error.
277
+ RequireDefaultFinalOnlyInInterfaces (context, decl_info.introducer ,
278
+ std::nullopt );
279
+
280
+ if (decl_info.init_id .has_value ()) {
281
+ LocalPatternMatch (context, decl_info.pattern_id , decl_info.init_id );
282
+ } else {
283
+ CARBON_DIAGNOSTIC (
284
+ ExpectedInitializerAfterLet, Error,
285
+ " expected `=`; `let` declaration must have an initializer" );
286
+ context.emitter ().Emit (LocIdForDiagnostics::TokenOnly (node_id),
287
+ ExpectedInitializerAfterLet);
288
+ }
289
+ return true ;
290
+ }
291
+
292
+ auto HandleParseNode (Context& context, Parse::AssociatedConstantDeclId node_id)
293
+ -> bool {
294
+ auto decl_info =
295
+ HandleDecl<Lex::TokenKind::Let,
296
+ Parse::NodeKind::AssociatedConstantIntroducer,
297
+ Parse::NodeKind::AssociatedConstantInitializer>(context);
298
+
299
+ LimitModifiersOnDecl (
300
+ context, decl_info.introducer ,
301
+ KeywordModifierSet::Access | KeywordModifierSet::Interface);
302
+
303
+ auto interface_scope =
304
+ context.scope_stack ().GetCurrentScopeAs <SemIR::InterfaceDecl>();
305
+ // The `AssociatedConstantDecl` instruction and the
306
+ // corresponding `AssociatedConstant` entity are built as part of handling the
307
+ // binding pattern, but we still need to finish building the `Generic` object
308
+ // and attach the default value, if any is specified.
272
309
if (decl_info.pattern_id == SemIR::ErrorInst::InstId) {
273
310
context.name_scopes ()
274
- .Get (context.interfaces ().Get (interface_id).scope_id )
311
+ .Get (context.interfaces ().Get (interface_scope-> interface_id ).scope_id )
275
312
.set_has_error ();
276
313
if (decl_info.init_id .has_value ()) {
277
314
DiscardGenericDecl (context);
278
315
}
279
316
context.inst_block_stack ().Pop ();
280
- return ;
317
+ return true ;
281
318
}
282
319
auto decl = context.insts ().GetAs <SemIR::AssociatedConstantDecl>(
283
320
decl_info.pattern_id );
@@ -306,41 +343,6 @@ static auto FinishAssociatedConstant(Context& context, Parse::LetDeclId node_id,
306
343
ReplaceInstPreservingConstantValue (context, decl_info.pattern_id , decl);
307
344
308
345
context.inst_block_stack ().AddInstId (decl_info.pattern_id );
309
- }
310
-
311
- auto HandleParseNode (Context& context, Parse::LetDeclId node_id) -> bool {
312
- auto decl_info =
313
- HandleDecl<Lex::TokenKind::Let, Parse::NodeKind::LetIntroducer,
314
- Parse::NodeKind::LetInitializer>(context);
315
-
316
- LimitModifiersOnDecl (
317
- context, decl_info.introducer ,
318
- KeywordModifierSet::Access | KeywordModifierSet::Interface);
319
-
320
- // At interface scope, we are forming an associated constant, which has
321
- // different rules.
322
- if (auto interface_scope =
323
- context.scope_stack ().GetCurrentScopeAs <SemIR::InterfaceDecl>()) {
324
- FinishAssociatedConstant (context, node_id, interface_scope->interface_id ,
325
- decl_info);
326
- return true ;
327
- }
328
-
329
- // Diagnose interface modifiers given that we're not building an associated
330
- // constant. We use this rather than `LimitModifiersOnDecl` to get a more
331
- // specific error.
332
- RequireDefaultFinalOnlyInInterfaces (context, decl_info.introducer ,
333
- std::nullopt );
334
-
335
- if (decl_info.init_id .has_value ()) {
336
- LocalPatternMatch (context, decl_info.pattern_id , decl_info.init_id );
337
- } else {
338
- CARBON_DIAGNOSTIC (
339
- ExpectedInitializerAfterLet, Error,
340
- " expected `=`; `let` declaration must have an initializer" );
341
- context.emitter ().Emit (LocIdForDiagnostics::TokenOnly (node_id),
342
- ExpectedInitializerAfterLet);
343
- }
344
346
return true ;
345
347
}
346
348
0 commit comments