@@ -30,40 +30,31 @@ auto HandleParseNode(Context& context, Parse::UnderscoreNameId node_id)
3030
3131// TODO: make this function shorter by factoring pieces out.
3232static auto HandleAnyBindingPattern (Context& context, Parse::NodeId node_id,
33+ Parse::NodeId name_node,
34+ SemIR::EntityNameId entity_name_id,
35+ Parse::NodeId type_node,
36+ SemIR::InstId parsed_type_inst_id,
3337 Parse::NodeKind node_kind) -> bool {
3438 // TODO: split this into smaller, more focused functions.
35- auto [type_node, parsed_type_id] = context.node_stack ().PopExprWithNodeId ();
3639 auto [cast_type_inst_id, cast_type_id] =
37- ExprAsType (context, type_node, parsed_type_id );
40+ ExprAsType (context, type_node, parsed_type_inst_id );
3841
3942 SemIR::ExprRegionId type_expr_region_id =
4043 EndSubpatternAsExpr (context, cast_type_inst_id);
4144
42- // The name in a template binding may be wrapped in `template`.
43- bool is_generic = node_kind == Parse::NodeKind::CompileTimeBindingPattern;
44- auto is_template =
45- context.node_stack ()
46- .PopAndDiscardSoloNodeIdIf <Parse::NodeKind::TemplateBindingName>();
47- // A non-generic template binding is diagnosed by the parser.
48- is_template &= is_generic;
49-
50- auto [name_node, name_id] = context.node_stack ().PopNameWithNodeId ();
45+ const auto & entity_name = context.entity_names ().Get (entity_name_id);
46+ auto name_id = entity_name.name_id ;
47+ CARBON_CHECK ((node_kind == Parse::NodeKind::CompileTimeBindingPattern) ==
48+ entity_name.bind_index ().has_value ());
5149
5250 const DeclIntroducerState& introducer =
5351 context.decl_introducer_state_stack ().innermost ();
5452
5553 auto make_binding_pattern = [&]() -> SemIR::InstId {
5654 // TODO: Eventually the name will need to support associations with other
5755 // scopes, but right now we don't support qualified names here.
58- auto binding =
59- AddBindingPattern (context, name_node, name_id, cast_type_id,
60- type_expr_region_id, is_generic, is_template);
61-
62- // TODO: If `is_generic`, then `binding.bind_id is a BindSymbolicName. Subst
63- // the `.Self` of type `type` in the `cast_type_id` type (a `FacetType`)
64- // with the `binding.bind_id` itself, and build a new pattern with that.
65- // This is kind of cyclical. So we need to reuse the EntityNameId, which
66- // will also reuse the CompileTimeBinding for the new BindSymbolicName.
56+ auto binding = AddBindingPatternWithEntityName (
57+ context, name_node, entity_name_id, cast_type_id, type_expr_region_id);
6758
6859 if (name_id != SemIR::NameId::Underscore) {
6960 // Add name to lookup immediately, so it can be used in the rest of the
@@ -100,7 +91,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
10091 case Lex::TokenKind::Fn: {
10192 if (context.full_pattern_stack ().CurrentKind () ==
10293 FullPatternStack::Kind::ImplicitParamList &&
103- !(is_generic || name_id == SemIR::NameId::SelfValue)) {
94+ (node_kind != Parse::NodeKind::CompileTimeBindingPattern &&
95+ name_id != SemIR::NameId::SelfValue)) {
10496 CARBON_DIAGNOSTIC (
10597 ImplictParamMustBeConstant, Error,
10698 " implicit parameters of functions must be constant or `self`" );
@@ -130,7 +122,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
130122 " `self` parameter only allowed on functions" );
131123 context.emitter ().Emit (node_id, SelfParameterNotAllowed);
132124 had_error = true ;
133- } else if (!is_generic ) {
125+ } else if (node_kind != Parse::NodeKind::CompileTimeBindingPattern ) {
134126 CARBON_DIAGNOSTIC (GenericParamMustBeConstant, Error,
135127 " parameters of generic types must be constant" );
136128 context.emitter ().Emit (node_id, GenericParamMustBeConstant);
@@ -149,6 +141,12 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
149141 // Replace the parameter with `ErrorInst` so that we don't try
150142 // constructing a generic based on it.
151143 result_inst_id = SemIR::ErrorInst::InstId;
144+ if (node_kind == Parse::NodeKind::CompileTimeBindingPattern) {
145+ // Push an error for the EntityName's binding index, since we're not
146+ // constructing an entity with make_binding_pattern().
147+ context.scope_stack ().PushCompileTimeBinding (
148+ SemIR::ErrorInst::InstId);
149+ }
152150 } else {
153151 result_inst_id = make_binding_pattern ();
154152 if (node_kind == Parse::NodeKind::LetBindingPattern) {
@@ -193,8 +191,6 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
193191 }
194192 auto binding_pattern_id = make_binding_pattern ();
195193 if (node_kind == Parse::NodeKind::VarBindingPattern) {
196- CARBON_CHECK (!is_generic);
197-
198194 if (introducer.modifier_set .HasAnyOf (KeywordModifierSet::Returned)) {
199195 // TODO: Should we check this for the `var` as a whole, rather than
200196 // for the name binding?
@@ -216,23 +212,93 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
216212
217213auto HandleParseNode (Context& context, Parse::LetBindingPatternId node_id)
218214 -> bool {
219- return HandleAnyBindingPattern (context, node_id,
215+ auto [type_node, type_inst_id] = context.node_stack ().PopExprWithNodeId ();
216+
217+ // `template` is incorrect here, but is diagnosed in parse.
218+ context.node_stack ()
219+ .PopAndDiscardSoloNodeIdIf <Parse::NodeKind::TemplateBindingName>();
220+
221+ auto [name_node, name_id] = context.node_stack ().PopNameWithNodeId ();
222+ auto entity_name_id = context.entity_names ().Add (
223+ {.name_id = name_id,
224+ .parent_scope_id = context.scope_stack ().PeekNameScopeId ()});
225+
226+ return HandleAnyBindingPattern (context, node_id, name_node, entity_name_id,
227+ type_node, type_inst_id,
220228 Parse::NodeKind::LetBindingPattern);
221229}
222230
223231auto HandleParseNode (Context& context, Parse::VarBindingPatternId node_id)
224232 -> bool {
225- return HandleAnyBindingPattern (context, node_id,
233+ auto [type_node, type_inst_id] = context.node_stack ().PopExprWithNodeId ();
234+
235+ // `template` is incorrect here, but is diagnosed in parse.
236+ context.node_stack ()
237+ .PopAndDiscardSoloNodeIdIf <Parse::NodeKind::TemplateBindingName>();
238+
239+ auto [name_node, name_id] = context.node_stack ().PopNameWithNodeId ();
240+ auto entity_name_id = context.entity_names ().Add (
241+ {.name_id = name_id,
242+ .parent_scope_id = context.scope_stack ().PeekNameScopeId ()});
243+
244+ return HandleAnyBindingPattern (context, node_id, name_node, entity_name_id,
245+ type_node, type_inst_id,
226246 Parse::NodeKind::VarBindingPattern);
227247}
228248
229249auto HandleParseNode (Context& context,
230250 Parse::CompileTimeBindingPatternStartId node_id) -> bool {
231- // Make a scope to contain the `.Self` facet value for use in the type of the
232- // compile time binding. This is popped when handling the
233- // CompileTimeBindingPatternId.
234- context.scope_stack ().PushForSameRegion ();
251+ auto is_template =
252+ context.node_stack ()
253+ .PopAndDiscardSoloNodeIdIf <Parse::NodeKind::TemplateBindingName>();
254+
255+ auto name_id = context.node_stack ().PeekNameId ();
256+ auto entity_name_id = SemIR::EntityNameId::None;
257+
258+ const DeclIntroducerState& introducer =
259+ context.decl_introducer_state_stack ().innermost ();
260+ if (introducer.kind == Lex::TokenKind::Let) {
261+ // Disallow `let` outside of function and interface definitions.
262+ // TODO: Find a less brittle way of doing this. A `scope_inst_id` of `None`
263+ // can represent a block scope, but is also used for other kinds of scopes
264+ // that aren't necessarily part of a function decl.
265+ // We don't need to check if the scope is an interface here as this is
266+ // already caught in the parse phase by the separated associated constant
267+ // logic.
268+ auto scope_inst_id = context.scope_stack ().PeekInstId ();
269+ if (scope_inst_id.has_value ()) {
270+ auto scope_inst = context.insts ().Get (scope_inst_id);
271+ if (!scope_inst.Is <SemIR::FunctionDecl>()) {
272+ context.TODO (
273+ node_id,
274+ " `let` compile time binding outside function or interface" );
275+ entity_name_id = context.entity_names ().Add (
276+ {.name_id = name_id,
277+ .parent_scope_id = context.scope_stack ().PeekNameScopeId ()});
278+ }
279+ }
280+ }
281+
282+ // This compile time binding is added but not pushed because we don't have the
283+ // BindSymbolicName for it until we get to the CompileTimeBindingPatternId
284+ // node. This leaves the CompileTimeBinding stack in a fragile state while the
285+ // binding's facet type is checked, but only the index is used during type
286+ // checking. The instruction wouldn't be needed until building a generic,
287+ // which we don't do in this scope.
288+ //
289+ // We avoid making a CompileTimeBinding in the case where a compile-time
290+ // binding is disallowed. In that case, we already constructed an
291+ // `entity_name_id` above.
292+ if (!entity_name_id.has_value ()) {
293+ auto bind_index = context.scope_stack ().AddCompileTimeBinding ();
294+ entity_name_id = context.entity_names ().AddSymbolicBindingName (
295+ name_id, context.scope_stack ().PeekNameScopeId (), bind_index,
296+ is_template);
297+ }
235298
299+ // TODO: Construct a SymbolicBindingType for `entity_name_id` instead of a
300+ // BindSymbolicName for a `PeriodSelf` EntityName.
301+ //
236302 // The `.Self` must have a type of `FacetType`, so that it gets wrapped in
237303 // `FacetAccessType` when used in a type position, such as in `U:! I(.Self)`.
238304 // This allows substitution with other facet values without requiring an
@@ -244,7 +310,13 @@ auto HandleParseNode(Context& context,
244310 {.type_id = SemIR::TypeType::TypeId, .facet_type_id = facet_type_id});
245311 auto type_id = context.types ().GetTypeIdForTypeConstantId (const_id);
246312
313+ // Make a scope to contain the `.Self` facet value for use in the type of the
314+ // compile time binding. This is popped when handling the
315+ // CompileTimeBindingPatternId.
316+ context.scope_stack ().PushForSameRegion ();
247317 MakePeriodSelfFacetValue (context, type_id);
318+
319+ context.node_stack ().Push (node_id, entity_name_id);
248320 return true ;
249321}
250322
@@ -254,30 +326,29 @@ auto HandleParseNode(Context& context,
254326 // CompileTimeBindingPatternStart.
255327 context.scope_stack ().Pop ();
256328
329+ auto [type_node, type_inst_id] = context.node_stack ().PopExprWithNodeId ();
330+
331+ auto entity_name_id =
332+ context.node_stack ()
333+ .Pop <Parse::NodeKind::CompileTimeBindingPatternStart>();
334+
335+ // The NameId was already used to construct the `entity_name_id`.
336+ auto [name_node, _] = context.node_stack ().PopNameWithNodeId ();
337+
257338 auto node_kind = Parse::NodeKind::CompileTimeBindingPattern;
258- const DeclIntroducerState& introducer =
259- context.decl_introducer_state_stack ().innermost ();
260- if (introducer.kind == Lex::TokenKind::Let) {
261- // Disallow `let` outside of function and interface definitions.
262- // TODO: Find a less brittle way of doing this. A `scope_inst_id` of `None`
263- // can represent a block scope, but is also used for other kinds of scopes
264- // that aren't necessarily part of a function decl.
265- // We don't need to check if the scope is an interface here as this is
266- // already caught in the parse phase by the separated associated constant
267- // logic.
268- auto scope_inst_id = context.scope_stack ().PeekInstId ();
269- if (scope_inst_id.has_value ()) {
270- auto scope_inst = context.insts ().Get (scope_inst_id);
271- if (!scope_inst.Is <SemIR::FunctionDecl>()) {
272- context.TODO (
273- node_id,
274- " `let` compile time binding outside function or interface" );
275- node_kind = Parse::NodeKind::LetBindingPattern;
276- }
277- }
339+ if (!context.entity_names ().Get (entity_name_id).bind_index ().has_value ()) {
340+ // This indicates that CompileTimeBindingPatternStartId found a `let` in an
341+ // incorrect scope. We treat them as runtime bindings instead of compile
342+ // time bindings, since we avoided introducing a CompileTimeBindingIndex
343+ // that won't be used.
344+ node_kind = Parse::NodeKind::LetBindingPattern;
278345 }
279346
280- return HandleAnyBindingPattern (context, node_id, node_kind);
347+ auto success =
348+ HandleAnyBindingPattern (context, node_id, name_node, entity_name_id,
349+ type_node, type_inst_id, node_kind);
350+
351+ return success;
281352}
282353
283354auto HandleParseNode (Context& context,
0 commit comments