mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 15:51:07 +01:00
Disallow compile time bindings where they aren't clearly supported. (#4338)
This is resolving a fuzz-discovered crash related to function suspends and compile time bind indices. Although the crash originally came from clearly invalid syntax (missing the `=` inside a `class` decl), the syntax with a value should also be valid but has the same crash. This approach disallows compile-time bindings in contexts that can create ambiguous results, particularly class declarations. These are an issue because a suspended function can have let declarations after it. I'm allowing them in function bodies and interface scopes. --------- Co-authored-by: Richard Smith <richard@metafoo.co.uk>
This commit is contained in:
co-authored by
Richard Smith
parent
49a8efbe1b
commit
87678cc374
@@ -32,6 +32,8 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
|
||||
inst_id.is_valid() && context.insts().Is<SemIR::InterfaceDecl>(inst_id);
|
||||
}
|
||||
|
||||
bool needs_compile_time_binding = is_generic && !is_associated_constant;
|
||||
|
||||
// Create the appropriate kind of binding for this pattern.
|
||||
auto make_bind_name = [&](SemIR::TypeId type_id,
|
||||
SemIR::InstId value_id) -> SemIR::LocIdAndInst {
|
||||
@@ -42,7 +44,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
|
||||
.parent_scope_id = context.scope_stack().PeekNameScopeId(),
|
||||
// TODO: Don't allocate a compile-time binding index for an associated
|
||||
// constant declaration.
|
||||
.bind_index = is_generic && !is_associated_constant
|
||||
.bind_index = needs_compile_time_binding
|
||||
? context.scope_stack().AddCompileTimeBinding()
|
||||
: SemIR::CompileTimeBindIndex::Invalid});
|
||||
if (is_generic) {
|
||||
@@ -63,7 +65,7 @@ static auto HandleAnyBindingPattern(Context& context, Parse::NodeId node_id,
|
||||
// stack.
|
||||
auto push_bind_name = [&](SemIR::InstId bind_id) {
|
||||
context.node_stack().Push(node_id, bind_id);
|
||||
if (is_generic && !is_associated_constant) {
|
||||
if (needs_compile_time_binding) {
|
||||
context.scope_stack().PushCompileTimeBinding(bind_id);
|
||||
}
|
||||
};
|
||||
@@ -200,7 +202,19 @@ auto HandleParseNode(Context& context, Parse::BindingPatternId node_id)
|
||||
|
||||
auto HandleParseNode(Context& context,
|
||||
Parse::CompileTimeBindingPatternId node_id) -> bool {
|
||||
return HandleAnyBindingPattern(context, node_id, /*is_generic=*/true);
|
||||
bool is_generic = true;
|
||||
if (context.decl_introducer_state_stack().innermost().kind ==
|
||||
Lex::TokenKind::Let) {
|
||||
auto scope_inst = context.insts().Get(context.scope_stack().PeekInstId());
|
||||
if (!scope_inst.Is<SemIR::InterfaceDecl>() &&
|
||||
!scope_inst.Is<SemIR::FunctionDecl>()) {
|
||||
context.TODO(node_id,
|
||||
"`let` compile time binding outside function or interface");
|
||||
is_generic = false;
|
||||
}
|
||||
}
|
||||
|
||||
return HandleAnyBindingPattern(context, node_id, is_generic);
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::AddrId node_id) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user