From 8004c2d5f6b943c072c262fbfd7d629dcb2f3b1b Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Tue, 23 Sep 2025 10:51:31 -0700 Subject: [PATCH] CalleeFunction -> Callee name adjustments (#6117) --- toolchain/check/call.cpp | 33 ++++++------- toolchain/check/cpp/thunk.cpp | 3 +- toolchain/check/eval.cpp | 9 ++-- toolchain/check/eval_inst.cpp | 2 +- toolchain/check/member_access.cpp | 15 +++--- toolchain/check/thunk.cpp | 2 +- toolchain/lower/handle_call.cpp | 15 +++--- toolchain/sem_ir/function.cpp | 64 +++++++------------------ toolchain/sem_ir/function.h | 80 +++++++++++++++---------------- toolchain/sem_ir/inst_namer.cpp | 5 +- toolchain/sem_ir/stringify.cpp | 8 ++-- 11 files changed, 100 insertions(+), 136 deletions(-) diff --git a/toolchain/check/call.cpp b/toolchain/check/call.cpp index fa88728a6dbb..ca751a4213da 100644 --- a/toolchain/check/call.cpp +++ b/toolchain/check/call.cpp @@ -202,10 +202,11 @@ static auto CheckCalleeFunctionReturnType(Context& context, SemIR::LocId loc_id, } // Performs a call where the callee is a function. -static auto PerformCallToFunction( - Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id, - const SemIR::CalleeFunction::Function& callee_function, - llvm::ArrayRef arg_ids) -> SemIR::InstId { +static auto PerformCallToFunction(Context& context, SemIR::LocId loc_id, + SemIR::InstId callee_id, + const SemIR::CalleeFunction& callee_function, + llvm::ArrayRef arg_ids) + -> SemIR::InstId { // If the callee is a generic function, determine the generic argument values // for the call. auto callee_specific_id = ResolveCalleeInCall( @@ -323,37 +324,37 @@ static auto PerformCallToNonFunction(Context& context, SemIR::LocId loc_id, auto PerformCall(Context& context, SemIR::LocId loc_id, SemIR::InstId callee_id, llvm::ArrayRef arg_ids) -> SemIR::InstId { // Try treating the callee as a function first. - auto callee_function = GetCalleeFunction(context.sem_ir(), callee_id); - CARBON_KIND_SWITCH(callee_function.info) { - case CARBON_KIND(SemIR::CalleeFunction::Error _): { + auto callee = GetCallee(context.sem_ir(), callee_id); + CARBON_KIND_SWITCH(callee) { + case CARBON_KIND(SemIR::CalleeError _): { return SemIR::ErrorInst::InstId; } - case CARBON_KIND(SemIR::CalleeFunction::Function fn): { + case CARBON_KIND(SemIR::CalleeFunction fn): { return PerformCallToFunction(context, loc_id, callee_id, fn, arg_ids); } - case CARBON_KIND(SemIR::CalleeFunction::NonFunction _): { + case CARBON_KIND(SemIR::CalleeNonFunction _): { return PerformCallToNonFunction(context, loc_id, callee_id, arg_ids); } - case CARBON_KIND(SemIR::CalleeFunction::CppOverloadSet overload): { + case CARBON_KIND(SemIR::CalleeCppOverloadSet overload): { callee_id = PerformCppOverloadResolution(context, loc_id, overload.cpp_overload_set_id, overload.self_id, arg_ids); - auto overload_result = GetCalleeFunction(context.sem_ir(), callee_id); - CARBON_KIND_SWITCH(overload_result.info) { - case CARBON_KIND(SemIR::CalleeFunction::Error _): { + auto overload_result = GetCallee(context.sem_ir(), callee_id); + CARBON_KIND_SWITCH(overload_result) { + case CARBON_KIND(SemIR::CalleeError _): { return SemIR::ErrorInst::InstId; } - case CARBON_KIND(SemIR::CalleeFunction::Function fn): { + case CARBON_KIND(SemIR::CalleeFunction fn): { // Preserve the `self` argument from the original callee. CARBON_CHECK(!fn.self_id.has_value()); fn.self_id = overload.self_id; return PerformCallToFunction(context, loc_id, callee_id, fn, arg_ids); } - case CARBON_KIND(SemIR::CalleeFunction::CppOverloadSet _): { + case CARBON_KIND(SemIR::CalleeCppOverloadSet _): { CARBON_FATAL("overloads can't be recursive"); } - case CARBON_KIND(SemIR::CalleeFunction::NonFunction _): { + case CARBON_KIND(SemIR::CalleeNonFunction _): { CARBON_FATAL("overloads should produce functions"); } } diff --git a/toolchain/check/cpp/thunk.cpp b/toolchain/check/cpp/thunk.cpp index 8d17332abe9c..ac0b4d2f919a 100644 --- a/toolchain/check/cpp/thunk.cpp +++ b/toolchain/check/cpp/thunk.cpp @@ -553,8 +553,7 @@ auto PerformCppThunkCall(Context& context, SemIR::LocId loc_id, auto callee_function_params = context.inst_blocks().Get(callee_function.call_params_id); - auto thunk_callee = - GetCalleeFunctionAsFunction(context.sem_ir(), thunk_callee_id); + auto thunk_callee = GetCalleeAsFunction(context.sem_ir(), thunk_callee_id); auto& thunk_function = context.functions().Get(thunk_callee.function_id); auto thunk_function_params = context.inst_blocks().Get(thunk_function.call_params_id); diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 6e27d8698dbd..467c83a28252 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -1939,11 +1939,9 @@ static auto MakeConstantForCall(EvalContext& eval_context, bool has_constant_callee = ReplaceFieldWithConstantValue( eval_context, &call, &SemIR::Call::callee_id, &phase); - auto callee_function = - SemIR::GetCalleeFunction(eval_context.sem_ir(), call.callee_id); + auto callee = SemIR::GetCallee(eval_context.sem_ir(), call.callee_id); auto builtin_kind = SemIR::BuiltinFunctionKind::None; - if (auto* fn = - std::get_if(&callee_function.info)) { + if (auto* fn = std::get_if(&callee)) { // Calls to builtins might be constant. builtin_kind = eval_context.functions().Get(fn->function_id).builtin_function_kind(); @@ -1978,8 +1976,7 @@ static auto MakeConstantForCall(EvalContext& eval_context, CARBON_DIAGNOSTIC(CompTimeOnlyFunctionHere, Note, "compile-time-only function declared here"); const auto& function = eval_context.functions().Get( - std::get(callee_function.info) - .function_id); + std::get(callee).function_id); eval_context.emitter() .Build(inst_id, NonConstantCallToCompTimeOnlyFunction) .Note(function.latest_decl_id(), CompTimeOnlyFunctionHere) diff --git a/toolchain/check/eval_inst.cpp b/toolchain/check/eval_inst.cpp index f4d1d79638aa..e74dcca51241 100644 --- a/toolchain/check/eval_inst.cpp +++ b/toolchain/check/eval_inst.cpp @@ -501,7 +501,7 @@ auto EvalConstantInst(Context& context, SemIR::InstId inst_id, auto EvalConstantInst(Context& context, SemIR::InstId inst_id, SemIR::SpecificFunction inst) -> ConstantEvalResult { auto callee_function = - SemIR::GetCalleeFunctionAsFunction(context.sem_ir(), inst.callee_id); + SemIR::GetCalleeAsFunction(context.sem_ir(), inst.callee_id); const auto& fn = context.functions().Get(callee_function.function_id); if (!callee_function.self_type_id.has_value() && fn.builtin_function_kind() != SemIR::BuiltinFunctionKind::NoOp && diff --git a/toolchain/check/member_access.cpp b/toolchain/check/member_access.cpp index 264c9d6d1014..03ac4619ae53 100644 --- a/toolchain/check/member_access.cpp +++ b/toolchain/check/member_access.cpp @@ -58,16 +58,16 @@ static auto IsInstanceMethod(const SemIR::File& sem_ir, // instance method or because it's a C++ overload set that might contain an // instance method. static auto GetSelfIfInstanceMethod(const SemIR::File& sem_ir, - const SemIR::CalleeFunction& callee) + const SemIR::Callee& callee) -> std::optional { - CARBON_KIND_SWITCH(callee.info) { - case CARBON_KIND(SemIR::CalleeFunction::Function fn): { + CARBON_KIND_SWITCH(callee) { + case CARBON_KIND(SemIR::CalleeFunction fn): { if (IsInstanceMethod(sem_ir, fn.function_id)) { return fn.self_id; } return std::nullopt; } - case CARBON_KIND(SemIR::CalleeFunction::CppOverloadSet overload): { + case CARBON_KIND(SemIR::CalleeCppOverloadSet overload): { // For now, treat all C++ overload sets as potentially containing instance // methods. Overload resolution will handle the case where we actually // found a static method. @@ -77,10 +77,10 @@ static auto GetSelfIfInstanceMethod(const SemIR::File& sem_ir, return overload.self_id; } - case CARBON_KIND(SemIR::CalleeFunction::Error _): { + case CARBON_KIND(SemIR::CalleeError _): { return std::nullopt; } - case CARBON_KIND(SemIR::CalleeFunction::NonFunction _): { + case CARBON_KIND(SemIR::CalleeNonFunction _): { return std::nullopt; } } @@ -405,8 +405,7 @@ static auto PerformInstanceBinding(Context& context, SemIR::LocId loc_id, SemIR::InstId member_id) -> SemIR::InstId { // If the member is a function, check whether it's an instance method. if (auto self_id = GetSelfIfInstanceMethod( - context.sem_ir(), - SemIR::GetCalleeFunction(context.sem_ir(), member_id))) { + context.sem_ir(), SemIR::GetCallee(context.sem_ir(), member_id))) { if (self_id->has_value()) { // Found an already-bound method. return member_id; diff --git a/toolchain/check/thunk.cpp b/toolchain/check/thunk.cpp index 7b73d06b420f..6fab82dcd928 100644 --- a/toolchain/check/thunk.cpp +++ b/toolchain/check/thunk.cpp @@ -227,7 +227,7 @@ static auto HasDeclaredReturnType(Context& context, auto BuildThunk(Context& context, SemIR::FunctionId signature_id, SemIR::SpecificId signature_specific_id, SemIR::InstId callee_id) -> SemIR::InstId { - auto callee = SemIR::GetCalleeFunctionAsFunction(context.sem_ir(), callee_id); + auto callee = SemIR::GetCalleeAsFunction(context.sem_ir(), callee_id); // Check whether we can use the given function without a thunk. // TODO: For virtual functions, we want different rules for checking `self`. diff --git a/toolchain/lower/handle_call.cpp b/toolchain/lower/handle_call.cpp index 7a5d397c6cee..dd9ef828d4c4 100644 --- a/toolchain/lower/handle_call.cpp +++ b/toolchain/lower/handle_call.cpp @@ -477,10 +477,12 @@ static auto HandleBuiltinCall(FunctionContext& context, SemIR::InstId inst_id, CARBON_FATAL("Unsupported builtin call."); } -static auto HandleVirtualCall( - FunctionContext& context, llvm::ArrayRef args, - const SemIR::File* callee_file, const SemIR::Function& function, - const SemIR::CalleeFunction::Function& callee_function) -> llvm::CallInst* { +static auto HandleVirtualCall(FunctionContext& context, + llvm::ArrayRef args, + const SemIR::File* callee_file, + const SemIR::Function& function, + const SemIR::CalleeFunction& callee_function) + -> llvm::CallInst* { CARBON_CHECK(!args.empty(), "Virtual functions must have at least one parameter"); auto* ptr_type = @@ -534,7 +536,7 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, llvm::ArrayRef arg_ids = context.sem_ir().inst_blocks().Get(inst.args_id); - // TODO: This duplicates the SpecificId handling in `GetCalleeFunction`. + // TODO: This duplicates the SpecificId handling in `GetCallee`. // TODO: Should the `bound_method` be removed when forming the `call` // instruction? The `self` parameter is transferred into the call argument @@ -557,8 +559,7 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id, CARBON_CHECK(callee_id.has_value()); } - auto callee_function = - SemIR::GetCalleeFunctionAsFunction(*callee_file, callee_id); + auto callee_function = SemIR::GetCalleeAsFunction(*callee_file, callee_id); const SemIR::Function& function = callee_file->functions().Get(callee_function.function_id); diff --git a/toolchain/sem_ir/function.cpp b/toolchain/sem_ir/function.cpp index 3712fbd7d33b..0a38d24aebbb 100644 --- a/toolchain/sem_ir/function.cpp +++ b/toolchain/sem_ir/function.cpp @@ -14,41 +14,13 @@ namespace Carbon::SemIR { -auto CalleeFunction::Print(llvm::raw_ostream& out) const -> void { - out << "{"; - CARBON_KIND_SWITCH(info) { - case CARBON_KIND(SemIR::CalleeFunction::Function fn): { - out << "Function{function_id: " << fn.function_id - << ", enclosing_specific_id: " << fn.enclosing_specific_id - << ", resolved_specific_id: " << fn.resolved_specific_id - << ", self_type_id: " << fn.self_type_id - << ", self_id: " << fn.self_id << "}"; - break; - } - case CARBON_KIND(SemIR::CalleeFunction::CppOverloadSet overload): { - out << "CppOverload{cpp_overload_set_id: " << overload.cpp_overload_set_id - << ", self_id: " << overload.self_id << "}"; - break; - } - case CARBON_KIND(SemIR::CalleeFunction::Error _): { - out << "Error{}"; - break; - } - case CARBON_KIND(SemIR::CalleeFunction::NonFunction _): { - out << "Other{}"; - break; - } - } - out << "}"; -} - -auto GetCalleeFunction(const File& sem_ir, InstId callee_id, - SpecificId specific_id) -> CalleeFunction { - CalleeFunction::Function fn = {.function_id = FunctionId::None, - .enclosing_specific_id = SpecificId::None, - .resolved_specific_id = SpecificId::None, - .self_type_id = InstId::None, - .self_id = InstId::None}; +auto GetCallee(const File& sem_ir, InstId callee_id, SpecificId specific_id) + -> Callee { + CalleeFunction fn = {.function_id = FunctionId::None, + .enclosing_specific_id = SpecificId::None, + .resolved_specific_id = SpecificId::None, + .self_type_id = InstId::None, + .self_id = InstId::None}; if (auto bound_method = sem_ir.insts().TryGetAs(callee_id)) { fn.self_id = bound_method->object_id; callee_id = bound_method->function_decl_id; @@ -70,7 +42,7 @@ auto GetCalleeFunction(const File& sem_ir, InstId callee_id, // Identify the function we're calling by its type. auto val_id = sem_ir.constant_values().GetConstantInstId(callee_id); if (!val_id.has_value()) { - return {.info = CalleeFunction::NonFunction()}; + return CalleeNonFunction(); } auto fn_type_inst = sem_ir.types().GetAsInst(sem_ir.insts().Get(val_id).type_id()); @@ -78,9 +50,9 @@ auto GetCalleeFunction(const File& sem_ir, InstId callee_id, if (auto cpp_overload_set_type = fn_type_inst.TryAs()) { CARBON_CHECK(!fn.resolved_specific_id.has_value(), "Only `SpecificFunction` will be resolved, not C++ overloads"); - return {.info = CalleeFunction::CppOverloadSet{ - .cpp_overload_set_id = cpp_overload_set_type->overload_set_id, - .self_id = fn.self_id}}; + return CalleeCppOverloadSet{ + .cpp_overload_set_id = cpp_overload_set_type->overload_set_id, + .self_id = fn.self_id}; } if (auto impl_fn_type = fn_type_inst.TryAs()) { @@ -93,21 +65,19 @@ auto GetCalleeFunction(const File& sem_ir, InstId callee_id, auto fn_type = fn_type_inst.TryAs(); if (!fn_type) { if (fn_type_inst.Is()) { - return {.info = CalleeFunction::Error()}; + return CalleeError(); } - return {.info = CalleeFunction::NonFunction()}; + return CalleeNonFunction(); } fn.function_id = fn_type->function_id; fn.enclosing_specific_id = fn_type->specific_id; - return {.info = fn}; + return fn; } -auto GetCalleeFunctionAsFunction(const File& sem_ir, InstId callee_id, - SpecificId specific_id) - -> CalleeFunction::Function { - return std::get( - GetCalleeFunction(sem_ir, callee_id, specific_id).info); +auto GetCalleeAsFunction(const File& sem_ir, InstId callee_id, + SpecificId specific_id) -> CalleeFunction { + return std::get(GetCallee(sem_ir, callee_id, specific_id)); } auto DecomposeVirtualFunction(const File& sem_ir, InstId fn_decl_id, diff --git a/toolchain/sem_ir/function.h b/toolchain/sem_ir/function.h index 05eb2d629271..6610e53f5bf0 100644 --- a/toolchain/sem_ir/function.h +++ b/toolchain/sem_ir/function.h @@ -185,50 +185,48 @@ using FunctionStore = ValueStore; class File; -struct CalleeFunction : public Printable { - // This is a C++ overload set. - struct CppOverloadSet { - // The overload set. - CppOverloadSetId cpp_overload_set_id; - // The bound `self` parameter. `None` if not a method. - InstId self_id; - }; - - // An error instruction was found. - struct Error {}; - - // This is a function. - struct Function { - // The function. - FunctionId function_id; - // The specific that contains the function. - SpecificId enclosing_specific_id; - // The specific for the callee itself, in a resolved call. - SpecificId resolved_specific_id; - // The bound `Self` type or facet value. `None` if not a bound interface - // member. - InstId self_type_id; - // The bound `self` parameter. `None` if not a method. - InstId self_id; - }; - - // This may be a generic type, or could be an invalid callee. - struct NonFunction {}; - - std::variant info; - - auto Print(llvm::raw_ostream& out) const -> void; +// Information about a callee that's a C++ overload set. +struct CalleeCppOverloadSet { + // The overload set. + CppOverloadSetId cpp_overload_set_id; + // The bound `self` parameter. `None` if not a method. + InstId self_id; }; -// Returns information for the function corresponding to callee_id. -auto GetCalleeFunction(const File& sem_ir, InstId callee_id, - SpecificId specific_id = SpecificId::None) - -> CalleeFunction; +// Information about a callee that's `ErrorInst`. +struct CalleeError {}; -// Like `GetCalleeFunction`, but restricts to the `Function` callee kind. -auto GetCalleeFunctionAsFunction(const File& sem_ir, InstId callee_id, - SpecificId specific_id = SpecificId::None) - -> CalleeFunction::Function; +// Information about a callee that's a function. +struct CalleeFunction { + // The function. + FunctionId function_id; + // The specific that contains the function. + SpecificId enclosing_specific_id; + // The specific for the callee itself, in a resolved call. + SpecificId resolved_specific_id; + // The bound `Self` type or facet value. `None` if not a bound interface + // member. + InstId self_type_id; + // The bound `self` parameter. `None` if not a method. + InstId self_id; +}; + +// Information about a callee that may be a generic type, or could be an +// invalid callee. +struct CalleeNonFunction {}; + +// A variant combining the callee forms. +using Callee = std::variant; + +// Returns information for the function corresponding to callee_id. +auto GetCallee(const File& sem_ir, InstId callee_id, + SpecificId specific_id = SpecificId::None) -> Callee; + +// Like `GetCallee`, but restricts to the `Function` callee kind. +auto GetCalleeAsFunction(const File& sem_ir, InstId callee_id, + SpecificId specific_id = SpecificId::None) + -> CalleeFunction; struct DecomposedVirtualFunction { // The canonical instruction from the `fn_decl_const_id`. diff --git a/toolchain/sem_ir/inst_namer.cpp b/toolchain/sem_ir/inst_namer.cpp index cc3c7cebbfb0..8679f80a7c00 100644 --- a/toolchain/sem_ir/inst_namer.cpp +++ b/toolchain/sem_ir/inst_namer.cpp @@ -759,9 +759,8 @@ auto InstNamer::NamingContext::NameInst() -> void { return; } case CARBON_KIND(Call inst): { - auto callee_function = GetCalleeFunction(sem_ir(), inst.callee_id); - if (auto* fn = - std::get_if(&callee_function.info)) { + auto callee = GetCallee(sem_ir(), inst.callee_id); + if (auto* fn = std::get_if(&callee)) { AddEntityNameAndMaybePush(fn->function_id, ".call"); return; } diff --git a/toolchain/sem_ir/stringify.cpp b/toolchain/sem_ir/stringify.cpp index 7f274b265d0e..699ab784f373 100644 --- a/toolchain/sem_ir/stringify.cpp +++ b/toolchain/sem_ir/stringify.cpp @@ -569,8 +569,8 @@ class Stringifier { } auto StringifyInst(InstId /*inst_id*/, SpecificFunction inst) -> void { - auto callee = GetCalleeFunction(*sem_ir_, inst.callee_id); - if (auto* fn = std::get_if(&callee.info)) { + auto callee = GetCallee(*sem_ir_, inst.callee_id); + if (auto* fn = std::get_if(&callee)) { step_stack_->PushEntityName(sem_ir_->functions().Get(fn->function_id), inst.specific_id); return; @@ -579,8 +579,8 @@ class Stringifier { } auto StringifyInst(InstId /*inst_id*/, SpecificImplFunction inst) -> void { - auto callee = GetCalleeFunction(*sem_ir_, inst.callee_id); - if (auto* fn = std::get_if(&callee.info)) { + auto callee = GetCallee(*sem_ir_, inst.callee_id); + if (auto* fn = std::get_if(&callee)) { // TODO: The specific_id here is for the interface member, but the // entity we're passing is the impl member. This might result in // strange output once we render specific arguments properly.