Clean up handling of Call params (#5061)

- Explicitly document that `*Param` and `*ParamPattern` insts represent
`Call` parameters.
- Stop wrapping compile-time parameter patterns in `ValueParamPattern`
insts (because they aren't `Call` parameters).
- Document how `MatchContext::results_` relates to the `Call`
parameters, and be more consistent about when it's written to.
- Remove `RuntimeParamIndex::Unknown`: we no longer need to distinguish
"this `Param`'s runtime index is unknown" from "this `Param` isn't a
runtime param", because we no longer use `Param`s at all in the latter
case.
- Rename `RuntimeParamIndex` to `CallParamIndex`.

As a side effect of removing the `ValueParamPattern` insts, this fixes a
minor diagnostic bug where `NoteInitializingParam` didn't identify the
specific parameter that led to a deduction failure, because it expects
generic parameters to only be represented by `SymbolicBindingPattern`s,
but before this change they could be wrapped in `ValueParamPattern`s.
This commit is contained in:
Geoff Romer
2025-03-04 21:01:59 +00:00
committed by GitHub
parent 4e21c0c1fc
commit d264f14027
148 changed files with 1424 additions and 2410 deletions
+45 -51
View File
@@ -80,7 +80,7 @@ class MatchContext {
private:
// Allocates the next unallocated RuntimeParamIndex, starting from 0.
auto NextRuntimeIndex() -> SemIR::RuntimeParamIndex {
auto NextRuntimeIndex() -> SemIR::CallParamIndex {
auto result = next_index_;
++next_index_.index;
return result;
@@ -125,9 +125,13 @@ class MatchContext {
llvm::SmallVector<WorkItem> stack_;
// The next index to be allocated by `NextRuntimeIndex`.
SemIR::RuntimeParamIndex next_index_;
SemIR::CallParamIndex next_index_;
// The pending results that will be returned by the current `DoWork` call.
// It represents the contents of the `Call` arguments block when kind_
// is Caller, or the `Call` parameters block when kind_ is Callee
// (it is empty when kind_ is Local). Consequently, it is populated
// only by DoEmitPatternMatch for *ParamPattern insts.
llvm::SmallVector<SemIR::InstId> results_;
// The kind of pattern match being performed.
@@ -200,6 +204,11 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
SemIR::AnyBindingPattern binding_pattern,
SemIR::LocId /*pattern_loc_id*/,
MatchContext::WorkItem entry) -> void {
if (kind_ == MatchKind::Caller) {
CARBON_CHECK(binding_pattern.kind == SemIR::SymbolicBindingPattern::Kind,
"Found runtime binding pattern during caller pattern match");
return;
}
// We're logically consuming this map entry, so we invalidate it in order
// to avoid accidentally consuming it twice.
auto [bind_name_id, type_expr_region_id] =
@@ -207,24 +216,13 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
{.bind_name_id = SemIR::InstId::None,
.type_expr_region_id = SemIR::ExprRegionId::None});
InsertHere(context, type_expr_region_id);
auto value_id = entry.scrutinee_id;
switch (kind_) {
case MatchKind::Local: {
value_id = ConvertToValueOrRefOfType(
context, context.insts().GetLocId(entry.scrutinee_id),
entry.scrutinee_id, binding_pattern.type_id);
break;
}
case MatchKind::Callee: {
if (context.insts()
.GetAs<SemIR::AnyParam>(value_id)
.runtime_index.has_value()) {
results_.push_back(value_id);
}
break;
}
case MatchKind::Caller:
CARBON_FATAL("Found binding pattern during caller pattern match");
auto value_id = SemIR::InstId::None;
if (kind_ == MatchKind::Local) {
value_id = ConvertToValueOrRefOfType(
context, context.insts().GetLocId(entry.scrutinee_id),
entry.scrutinee_id, binding_pattern.type_id);
} else {
value_id = entry.scrutinee_id;
}
auto bind_name = context.insts().GetAs<SemIR::AnyBindName>(bind_name_id);
CARBON_CHECK(!bind_name.value_id.has_value());
@@ -259,8 +257,10 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
context.emitter().Emit(
TokenOnly(context.insts().GetLocId(entry.scrutinee_id)),
AddrSelfIsNonRef);
results_.push_back(SemIR::ErrorInst::SingletonInstId);
return;
// Add fake reference expression to preserve invariants.
auto scrutinee = context.insts().GetWithLocId(entry.scrutinee_id);
scrutinee_ref_id = AddInst<SemIR::TemporaryStorage>(
context, scrutinee.loc_id, {.type_id = scrutinee.inst.type_id()});
}
auto scrutinee_ref = context.insts().Get(scrutinee_ref_id);
auto new_scrutinee = AddInst<SemIR::AddrOf>(
@@ -274,11 +274,11 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
SemIR::ValueParamPattern param_pattern,
SemIR::LocId pattern_loc_id,
WorkItem entry) -> void {
CARBON_CHECK(param_pattern.runtime_index.index < 0 ||
static_cast<size_t>(param_pattern.runtime_index.index) ==
results_.size(),
"Parameters out of order; expecting {0} but got {1}",
results_.size(), param_pattern.runtime_index.index);
CARBON_CHECK(
param_pattern.index.index < 0 ||
static_cast<size_t>(param_pattern.index.index) == results_.size(),
"Parameters out of order; expecting {0} but got {1}", results_.size(),
param_pattern.index.index);
switch (kind_) {
case MatchKind::Caller: {
CARBON_CHECK(entry.scrutinee_id.has_value());
@@ -296,16 +296,18 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
break;
}
case MatchKind::Callee: {
if (param_pattern.runtime_index == SemIR::RuntimeParamIndex::Unknown) {
param_pattern.runtime_index = NextRuntimeIndex();
if (!param_pattern.index.has_value()) {
param_pattern.index = NextRuntimeIndex();
ReplaceInstBeforeConstantUse(context, entry.pattern_id, param_pattern);
}
auto param_id = AddInst<SemIR::ValueParam>(
context, pattern_loc_id,
{.type_id = param_pattern.type_id,
.index = param_pattern.index,
.pretty_name_id = GetPrettyName(context, param_pattern)});
AddWork({.pattern_id = param_pattern.subpattern_id,
.scrutinee_id = AddInst<SemIR::ValueParam>(
context, pattern_loc_id,
{.type_id = param_pattern.type_id,
.runtime_index = param_pattern.runtime_index,
.pretty_name_id = GetPrettyName(context, param_pattern)})});
.scrutinee_id = param_id});
results_.push_back(param_id);
break;
}
case MatchKind::Local: {
@@ -333,16 +335,18 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
case MatchKind::Callee: {
// TODO: Consider ways to address near-duplication with the
// ValueParamPattern case.
if (param_pattern.runtime_index == SemIR::RuntimeParamIndex::Unknown) {
param_pattern.runtime_index = NextRuntimeIndex();
if (!param_pattern.index.has_value()) {
param_pattern.index = NextRuntimeIndex();
ReplaceInstBeforeConstantUse(context, entry.pattern_id, param_pattern);
}
auto param_id = AddInst<SemIR::OutParam>(
context, pattern_loc_id,
{.type_id = param_pattern.type_id,
.index = param_pattern.index,
.pretty_name_id = GetPrettyName(context, param_pattern)});
AddWork({.pattern_id = param_pattern.subpattern_id,
.scrutinee_id = AddInst<SemIR::OutParam>(
context, pattern_loc_id,
{.type_id = param_pattern.type_id,
.runtime_index = param_pattern.runtime_index,
.pretty_name_id = GetPrettyName(context, param_pattern)})});
.scrutinee_id = param_id});
results_.push_back(param_id);
break;
}
case MatchKind::Local: {
@@ -365,7 +369,6 @@ auto MatchContext::DoEmitPatternMatch(
.LookupOrAddName(SemIR::NameId::ReturnSlot, return_slot_id)
.has_value();
CARBON_CHECK(!already_in_lookup);
results_.push_back(entry.scrutinee_id);
}
auto MatchContext::DoEmitPatternMatch(Context& context,
@@ -459,7 +462,6 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
auto MatchContext::EmitPatternMatch(Context& context,
MatchContext::WorkItem entry) -> void {
if (entry.pattern_id == SemIR::ErrorInst::SingletonInstId) {
results_.push_back(SemIR::ErrorInst::SingletonInstId);
return;
}
DiagnosticAnnotationScope annotate_diagnostics(
@@ -566,14 +568,6 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
// Check type conversions per-element.
for (auto [arg_id, param_pattern_id] : llvm::reverse(llvm::zip_equal(
arg_refs, context.inst_blocks().GetOrEmpty(param_patterns_id)))) {
auto runtime_index = SemIR::Function::GetParamPatternInfoFromPatternId(
context.sem_ir(), param_pattern_id)
.inst.runtime_index;
if (!runtime_index.has_value()) {
// Not a runtime parameter: we don't pass an argument.
continue;
}
match.AddWork({.pattern_id = param_pattern_id, .scrutinee_id = arg_id});
}