Add support for field initializers (#7238)

In handle_let_and_var.cpp, field initializers are now handled like
regular `var` initializers, by calling `LocalPatternMatch`.

In pattern_match.cpp, `FieldDecl`s with initializers are handled by
storing a value in `SemIR::File::field_initializers()`. This is a new
map where the keys are `FieldDecl` `InstId`s and the map values are
`InstId`s representing the initializer value.

In convert.cpp, `ConvertStructToStructOrClass` now has a `get_default`
function parameter that callers can use to provide a field default.
`ConvertStructToClass` uses this to provide a default from field
initializers.
This commit is contained in:
Nicholas Bishop
2026-05-22 02:48:07 +00:00
committed by GitHub
parent 862b1c91f8
commit e6b1679552
19 changed files with 541 additions and 122 deletions
+30
View File
@@ -16,6 +16,7 @@
#include "toolchain/check/context.h"
#include "toolchain/check/control_flow.h"
#include "toolchain/check/convert.h"
#include "toolchain/check/eval.h"
#include "toolchain/check/pattern.h"
#include "toolchain/check/type.h"
#include "toolchain/diagnostics/format_providers.h"
@@ -177,6 +178,8 @@ class MatchContext {
SemIR::InstId scrutinee_id, WorkItem entry) -> void;
auto DoPreWork(State state, SemIR::ExprPattern expr_pattern,
SemIR::InstId scrutinee_id, WorkItem entry) -> void;
auto DoPreWork(State state, SemIR::FieldDecl field_decl,
SemIR::InstId scrutinee_id, WorkItem entry) -> void;
auto DoPreWork(State state, SemIR::ReturnSlotPattern return_slot_pattern,
SemIR::InstId scrutinee_id, WorkItem entry) -> void;
auto DoPreWork(State state, SemIR::VarPattern var_pattern,
@@ -537,6 +540,29 @@ auto MatchContext::DoPostWork(State /*state*/,
SemIR::ExprPattern /*expr_pattern*/,
WorkItem /*entry*/) -> void {}
auto MatchContext::DoPreWork(State /*state*/, SemIR::FieldDecl field_decl,
SemIR::InstId scrutinee_id, WorkItem entry)
-> void {
if (!scrutinee_id.has_value()) {
return;
}
// Get the field initializer.
auto unbound_element_type = context_.insts().GetAs<SemIR::UnboundElementType>(
context_.types().GetTypeInstId(field_decl.type_id));
auto element_type = context_.types().GetTypeIdForTypeInstId(
unbound_element_type.element_type_inst_id);
auto converted_id = ConvertToValueOfType(context_, SemIR::LocId(scrutinee_id),
scrutinee_id, element_type,
/*diagnose=*/true);
if (converted_id == SemIR::ErrorInst::InstId) {
return;
}
// Store a mapping to the field's initializer.
context_.field_initializers().Insert(entry.pattern_id, converted_id);
}
auto MatchContext::DoPreWork(State state,
SemIR::ReturnSlotPattern return_slot_pattern,
SemIR::InstId scrutinee_id, WorkItem entry)
@@ -838,6 +864,10 @@ auto MatchContext::Dispatch(State state, WorkItem entry) -> void {
DoPreWork(state, expr_pattern, work.scrutinee_id, entry);
break;
}
case CARBON_KIND(SemIR::FieldDecl field_decl): {
DoPreWork(state, field_decl, work.scrutinee_id, entry);
break;
}
case CARBON_KIND(SemIR::ReturnSlotPattern return_slot_pattern): {
DoPreWork(state, return_slot_pattern, work.scrutinee_id, entry);
break;