mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 14:51:03 +01:00
Restructure scrutinee type handling (#7216)
This change avoids situations where a variable might be either a pattern type or a scrutinee type, depending on the pattern matching state, and makes it clear that the state only affects which specific is selected.
This commit is contained in:
@@ -210,21 +210,15 @@ 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 by `VarParamPattern`, which needs to do the
|
||||
// pre-work of both a `VarPattern` and a `RefParamPattern`.
|
||||
auto DoVarPreWorkImpl(State state, SemIR::TypeId pattern_type_id,
|
||||
// Performs the core logic of matching a variable pattern whose scrutinee
|
||||
// type is `scrutinee_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 by `VarParamPattern`, which needs to do
|
||||
// the pre-work of both a `VarPattern` and a `RefParamPattern`.
|
||||
auto DoVarPreWorkImpl(State state, SemIR::TypeId scrutinee_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_;
|
||||
|
||||
@@ -415,34 +409,41 @@ static auto ParamKindFor(SemIR::Inst param_pattern) -> SemIR::InstKind {
|
||||
}
|
||||
}
|
||||
|
||||
auto MatchContext::GetSpecificPatternTypeId(State state,
|
||||
SemIR::InstId pattern_id,
|
||||
SemIR::TypeId param_pattern_type_id)
|
||||
-> SemIR::TypeId {
|
||||
// Returns the applicable specific for patterns handled in the given state.
|
||||
static auto GetSpecific(State state) -> SemIR::SpecificId {
|
||||
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));
|
||||
case CARBON_KIND(CallerState* caller_state): {
|
||||
return caller_state->callee_specific_id;
|
||||
}
|
||||
default: {
|
||||
return SemIR::SpecificId::None;
|
||||
}
|
||||
default:
|
||||
return param_pattern_type_id;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the scrutinee type of `pattern_id` in the specific determined by
|
||||
// `state`.
|
||||
static auto GetSpecificScrutineeTypeId(const Context& context, State state,
|
||||
SemIR::InstId pattern_id)
|
||||
-> SemIR::TypeId {
|
||||
const auto& sem_ir = context.sem_ir();
|
||||
return ExtractScrutineeType(
|
||||
sem_ir,
|
||||
SemIR::GetTypeOfInstInSpecific(sem_ir, GetSpecific(state), pattern_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);
|
||||
auto scrutinee_type_id =
|
||||
GetSpecificScrutineeTypeId(context_, state, entry.pattern_id);
|
||||
|
||||
// If `param_pattern` is a `VarParamPattern`, match it as a `VarPattern` here,
|
||||
// and then as a `RefParamPattern` below.
|
||||
if (param_pattern.kind == SemIR::VarParamPattern::Kind) {
|
||||
scrutinee_id =
|
||||
DoVarPreWorkImpl(state, pattern_type_id, scrutinee_id, entry);
|
||||
DoVarPreWorkImpl(state, scrutinee_type_id, scrutinee_id, entry);
|
||||
entry.allow_unmarked_ref = true;
|
||||
}
|
||||
|
||||
@@ -455,7 +456,7 @@ auto MatchContext::DoPreWork(State state, SemIR::AnyParamPattern param_pattern,
|
||||
caller_state->call_args.push_back(
|
||||
Convert(context_, SemIR::LocId(scrutinee_id), scrutinee_id,
|
||||
{.kind = ConversionKindFor(param_pattern, entry),
|
||||
.type_id = pattern_type_id}));
|
||||
.type_id = scrutinee_type_id}));
|
||||
}
|
||||
// Do not traverse farther or schedule PostWork, because the caller side
|
||||
// of the pattern ends here.
|
||||
@@ -574,10 +575,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 scrutinee_type_id =
|
||||
GetSpecificScrutineeTypeId(context_, state, entry.pattern_id);
|
||||
auto new_scrutinee_id =
|
||||
DoVarPreWorkImpl(state, pattern_type_id, scrutinee_id, entry);
|
||||
DoVarPreWorkImpl(state, scrutinee_type_id, scrutinee_id, entry);
|
||||
if (need_subpattern_results()) {
|
||||
AddAsPostWork(entry);
|
||||
}
|
||||
@@ -586,7 +587,8 @@ auto MatchContext::DoPreWork(State state, SemIR::VarPattern var_pattern,
|
||||
.allow_unmarked_ref = true});
|
||||
}
|
||||
|
||||
auto MatchContext::DoVarPreWorkImpl(State state, SemIR::TypeId pattern_type_id,
|
||||
auto MatchContext::DoVarPreWorkImpl(State state,
|
||||
SemIR::TypeId scrutinee_type_id,
|
||||
SemIR::InstId scrutinee_id,
|
||||
WorkItem entry) const -> SemIR::InstId {
|
||||
CARBON_KIND_SWITCH(state) {
|
||||
@@ -635,7 +637,7 @@ auto MatchContext::DoVarPreWorkImpl(State state, SemIR::TypeId pattern_type_id,
|
||||
PendingBlock storage_block(&context_);
|
||||
auto storage_id = storage_block.AddInstWithCleanup<SemIR::VarStorage>(
|
||||
SemIR::LocId(entry.pattern_id),
|
||||
{.type_id = pattern_type_id, .pattern_id = entry.pattern_id});
|
||||
{.type_id = scrutinee_type_id, .pattern_id = entry.pattern_id});
|
||||
auto init_result = Initialize(
|
||||
context_, SemIR::LocId(entry.pattern_id),
|
||||
// Disable broken lint that suggests a "fix" that doesn't compile.
|
||||
|
||||
Reference in New Issue
Block a user