Add basic caller-side support for default values in check (#7800)

Modifies the arity check to include a lower-bound for arguments.
Adds logic to pattern matching to supply default arguments for
missing parameters.
This commit is contained in:
Lucile Rose Nihlen
2026-09-22 22:07:35 +00:00
committed by GitHub
parent 795729bb4a
commit 53b7cfbaba
8 changed files with 508 additions and 159 deletions
+38 -8
View File
@@ -119,7 +119,9 @@ using State =
class MatchContext {
public:
struct PreWork : Printable<PreWork> {
// `None` when processing the callee side.
// `None` when processing the callee side, or when processing the caller
// side and no value was supplied, in expectation of using a default value
// from the corresponding callee pattern.
SemIR::InstId scrutinee_id;
auto Print(llvm::raw_ostream& out) const -> void {
@@ -936,13 +938,31 @@ auto MatchContext::DoPreWork(State state,
SemIR::DefaultValuePattern default_value_pattern,
SemIR::InstId scrutinee_id, WorkItem entry)
-> void {
if (!std::holds_alternative<CalleeState*>(state)) {
CARBON_FATAL("Unhandled state kind in DefaultValuePattern pre-work");
CARBON_KIND_SWITCH(state) {
case CARBON_KIND(CallerState* _): {
// If there's no scrutinee supplied, supply the default value instead.
if (!scrutinee_id.has_value()) {
const auto& default_value = context_.default_values().Get(
default_value_pattern.default_value_id);
CARBON_CHECK(default_value.value_id.has_value());
auto [inst_id, _] = WrapInstForSpecific(
context_, SemIR::LocId(default_value.value_id),
default_value.value_id, specific_id_stack_.back());
scrutinee_id = inst_id;
}
break;
}
case CARBON_KIND(CalleeState* _): {
// We will need to check the type of the parameter to make sure it
// matches the provided default, so add ourselves to the post-work list.
results_stack_.PushArray();
AddAsPostWork(entry);
break;
}
default: {
CARBON_FATAL("Unhandled state kind in DefaultValuePattern pre-work");
}
}
// We will need to check the type of the parameter to make sure it
// matches the provided default, so add ourselves to the post-work list.
results_stack_.PushArray();
AddAsPostWork(entry);
// Process the subpattern for the default.
AddWork({.pattern_id = default_value_pattern.subpattern_id,
@@ -1226,9 +1246,19 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
CARBON_CHECK(self_pattern_id.has_value());
}
for (const auto& [arg_id, param_pattern_id] : llvm::zip_equal(
// `arg_refs` may have a smaller arity than `param_patterns_id` due to the
// possible presence of default values for some parameters. We use
// `zip_longest` here to allow for that size disparity. But we presume we
// always have a parameter pattern, so test that presumption here.
CARBON_CHECK(self_arg_refs.size() + arg_refs.size() <=
context.inst_blocks().GetOrEmpty(param_patterns_id).size());
for (const auto& [maybe_arg_id, maybe_param_pattern_id] : llvm::zip_longest(
llvm::concat<const SemIR::InstId>(self_arg_refs, arg_refs),
context.inst_blocks().GetOrEmpty(param_patterns_id))) {
CARBON_CHECK(maybe_param_pattern_id.has_value());
const auto& param_pattern_id = *maybe_param_pattern_id;
const auto& arg_id =
maybe_arg_id.has_value() ? *maybe_arg_id : SemIR::InstId::None;
match.Match(&state,
{.pattern_id = param_pattern_id,
.work = MatchContext::PreWork{.scrutinee_id = arg_id},