Step through splices when checking for a bound method. (#7700)

`GetCallee` is sometimes called on a spliced instruction, and is
checking its exact inst operand to see if it's a `BoundMethod`. This
fails if the `BoundMethod` is wrapped in another instruction, such as a
splice. Normally our approach for such a situation would be to
constant-evaluate the operand, but that doesn't work here because the
`BoundMethod` will be non-constant if its bound `self` is. So instead we
now step through splice instructions manually when looking for the
`BoundMethod`.
This commit is contained in:
Richard Smith
2026-09-02 15:19:59 +00:00
committed by GitHub
parent 6724d506f3
commit 2209a3477e
9 changed files with 1080 additions and 80 deletions
+29 -1
View File
@@ -16,6 +16,33 @@
namespace Carbon::SemIR {
auto TryGetCalleeAsBoundMethod(const File& sem_ir, InstId callee_id,
SpecificId caller_specific_id)
-> std::optional<BoundMethod> {
// Step through splices before checking for a bound method. Unfortunately we
// can't just look at the constant value of callee_id here, because bound
// methods are non-constant if their `self` is, so we do a mini-eval here.
while (true) {
auto inst = sem_ir.insts().Get(callee_id);
if (auto splice_inst = inst.TryAs<SpliceInst>()) {
auto inst_value_id = GetConstantValueInSpecific(
sem_ir, caller_specific_id, splice_inst->inst_id);
if (!inst_value_id.is_concrete()) {
break;
}
callee_id = sem_ir.constant_values()
.GetInstAs<SemIR::InstValue>(inst_value_id)
.inst_id;
} else if (auto splice_block = inst.TryAs<SpliceBlock>()) {
callee_id = splice_block->result_id;
} else {
break;
}
}
return sem_ir.insts().TryGetAs<BoundMethod>(callee_id);
}
auto GetCallee(const File& sem_ir, InstId callee_id,
SpecificId caller_specific_id) -> Callee {
CalleeFunction fn = {.function_id = FunctionId::None,
@@ -23,7 +50,8 @@ auto GetCallee(const File& sem_ir, InstId callee_id,
.resolved_specific_id = SpecificId::None,
.self_type_id = InstId::None,
.self_id = InstId::None};
if (auto bound_method = sem_ir.insts().TryGetAs<BoundMethod>(callee_id)) {
if (auto bound_method =
TryGetCalleeAsBoundMethod(sem_ir, callee_id, caller_specific_id)) {
fn.self_id = bound_method->object_id;
callee_id = bound_method->function_decl_id;
}