consistently uses the caller's specific to get the callee's pattern type id (#7036)

`DoVarPreWorkImpl` was provided an incorrect pattern type while trying
to match `var` parameters, which caused the toolchain to crash in
`Convert`. This commit changes `DoVarPreWorkImpl`'s API so it derives
the pattern type from the work item's pattern ID, rather than relying on
an external source.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
This commit is contained in:
Christopher Di Bella
2026-04-13 17:41:54 +00:00
committed by GitHub
co-authored by Dana Jansens
parent 12d7574636
commit 3cdb159067
2 changed files with 183 additions and 15 deletions
+36 -15
View File
@@ -19,6 +19,7 @@
#include "toolchain/check/type.h"
#include "toolchain/diagnostics/format_providers.h"
#include "toolchain/sem_ir/expr_info.h"
#include "toolchain/sem_ir/inst_kind.h"
#include "toolchain/sem_ir/pattern.h"
namespace Carbon::Check {
@@ -180,15 +181,21 @@ class MatchContext {
return value_id;
}
// Performs the core logic of matching a variable pattern whose type is
// `pattern_type_id`, but returns the scrutinee that its subpattern should be
// matched with, rather than pushing it onto the worklist. This is factored
// out so it can be reused when handling a `FormBindingPattern` or
// `FormParamPattern` with an initializing form.
// Performs the core logic of matching a variable pattern, returning the
// scrutinee that its subpattern should be matched with, rather than pushing
// it onto the worklist. This is factored out so it can be reused when
// handling a `FormBindingPattern` or `FormParamPattern` with an initializing
// form.
auto DoVarPreWorkImpl(State state, SemIR::TypeId pattern_type_id,
SemIR::InstId scrutinee_id, WorkItem entry) const
-> SemIR::InstId;
// Returns the scrutinee type from `pattern_id` when passed a `CallerState`,
// and `param_pattern_type_id` otherwise.
auto GetSpecificPatternTypeId(State state, SemIR::InstId pattern_id,
SemIR::TypeId param_pattern_type_id)
-> SemIR::TypeId;
// The stack of work to be processed.
llvm::SmallVector<WorkItem> stack_;
@@ -444,10 +451,28 @@ static auto ParamKindFor(Context& context, SemIR::Inst param_pattern,
}
}
auto MatchContext::GetSpecificPatternTypeId(State state,
SemIR::InstId pattern_id,
SemIR::TypeId param_pattern_type_id)
-> SemIR::TypeId {
CARBON_KIND_SWITCH(state) {
case CARBON_KIND(CallerState* caller): {
auto& sem_ir = context_.sem_ir();
return ExtractScrutineeType(
sem_ir, SemIR::GetTypeOfInstInSpecific(
sem_ir, caller->callee_specific_id, pattern_id));
}
default:
return param_pattern_type_id;
}
}
auto MatchContext::DoPreWork(State state, SemIR::AnyParamPattern param_pattern,
SemIR::InstId scrutinee_id, WorkItem entry)
-> void {
AddAsPostWork(entry);
auto pattern_type_id =
GetSpecificPatternTypeId(state, entry.pattern_id, param_pattern.type_id);
// If `param_pattern` has initializing form, match it as a `VarPattern`
// before matching it as a parameter pattern.
@@ -463,7 +488,7 @@ auto MatchContext::DoPreWork(State state, SemIR::AnyParamPattern param_pattern,
}
case SemIR::VarParamPattern::Kind: {
scrutinee_id =
DoVarPreWorkImpl(state, param_pattern.type_id, scrutinee_id, entry);
DoVarPreWorkImpl(state, pattern_type_id, scrutinee_id, entry);
entry.allow_unmarked_ref = true;
break;
}
@@ -477,15 +502,10 @@ auto MatchContext::DoPreWork(State state, SemIR::AnyParamPattern param_pattern,
if (scrutinee_id == SemIR::ErrorInst::InstId) {
caller_state->call_args.push_back(SemIR::ErrorInst::InstId);
} else {
auto scrutinee_type_id = ExtractScrutineeType(
context_.sem_ir(),
SemIR::GetTypeOfInstInSpecific(context_.sem_ir(),
caller_state->callee_specific_id,
entry.pattern_id));
caller_state->call_args.push_back(
Convert(context_, SemIR::LocId(scrutinee_id), scrutinee_id,
{.kind = ConversionKindFor(context_, param_pattern, entry),
.type_id = scrutinee_type_id}));
.type_id = pattern_type_id}));
}
// Do not traverse farther or schedule PostWork, because the caller side
// of the pattern ends here.
@@ -603,8 +623,10 @@ auto MatchContext::DoPostWork(State state,
auto MatchContext::DoPreWork(State state, SemIR::VarPattern var_pattern,
SemIR::InstId scrutinee_id, WorkItem entry)
-> void {
auto pattern_type_id =
GetSpecificPatternTypeId(state, entry.pattern_id, var_pattern.type_id);
auto new_scrutinee_id =
DoVarPreWorkImpl(state, var_pattern.type_id, scrutinee_id, entry);
DoVarPreWorkImpl(state, pattern_type_id, scrutinee_id, entry);
if (need_subpattern_results()) {
AddAsPostWork(entry);
}
@@ -638,8 +660,7 @@ auto MatchContext::DoVarPreWorkImpl(State state, SemIR::TypeId pattern_type_id,
case CARBON_KIND(CallerState* _): {
storage_id = AddInst<SemIR::TemporaryStorage>(
context_, SemIR::LocId(entry.pattern_id),
{.type_id =
ExtractScrutineeType(context_.sem_ir(), pattern_type_id)});
{.type_id = pattern_type_id});
CARBON_CHECK(scrutinee_id.has_value());
break;
}