mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-04 10:51:05 +01:00
Model the return slot as an output parameter (#4432)
Also fix `Param` insts to have meaningful names in pretty-printing, to help clarify relationship with return slot.
This commit is contained in:
@@ -44,9 +44,15 @@ auto HandleParseNode(Context& context, Parse::ReturnTypeId node_id) -> bool {
|
||||
// Propagate the type expression.
|
||||
auto [type_node_id, type_inst_id] = context.node_stack().PopExprWithNodeId();
|
||||
auto type_id = ExprAsType(context, type_node_id, type_inst_id).type_id;
|
||||
// TODO: Use a dedicated instruction rather than VarStorage here.
|
||||
context.AddInstAndPush<SemIR::VarStorage>(
|
||||
node_id, {.type_id = type_id, .name_id = SemIR::NameId::ReturnSlot});
|
||||
auto return_slot_id = context.AddPatternInst<SemIR::ReturnSlotPattern>(
|
||||
node_id, {.type_id = type_id, .type_inst_id = type_inst_id});
|
||||
// TODO: Use a separate inst kind here and for the corresponding Param,
|
||||
// to capture the fact that the corresponding Param is not a value expression.
|
||||
auto param_pattern_id = context.AddPatternInst<SemIR::ParamPattern>(
|
||||
node_id, {.type_id = type_id,
|
||||
.subpattern_id = return_slot_id,
|
||||
.runtime_index = SemIR::RuntimeParamIndex::Unknown});
|
||||
context.node_stack().Push(node_id, param_pattern_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -97,7 +103,7 @@ static auto MergeFunctionRedecl(Context& context, SemIRLoc new_loc,
|
||||
// Track the signature from the definition, so that IDs in the body
|
||||
// match IDs in the signature.
|
||||
prev_function.MergeDefinition(new_function);
|
||||
prev_function.return_storage_id = new_function.return_storage_id;
|
||||
prev_function.return_slot_id = new_function.return_slot_id;
|
||||
}
|
||||
if ((prev_import_ir_id.is_valid() && !new_is_import)) {
|
||||
ReplacePrevInstForMerge(context, new_function.parent_scope_id,
|
||||
@@ -170,14 +176,14 @@ static auto BuildFunctionDecl(Context& context,
|
||||
Parse::AnyFunctionDeclId node_id,
|
||||
bool is_definition)
|
||||
-> std::pair<SemIR::FunctionId, SemIR::InstId> {
|
||||
auto return_storage_id = SemIR::InstId::Invalid;
|
||||
if (auto [return_node, maybe_return_storage_id] =
|
||||
auto return_slot_pattern_id = SemIR::InstId::Invalid;
|
||||
if (auto [return_node, maybe_return_slot_pattern_id] =
|
||||
context.node_stack().PopWithNodeIdIf<Parse::NodeKind::ReturnType>();
|
||||
maybe_return_storage_id) {
|
||||
return_storage_id = *maybe_return_storage_id;
|
||||
maybe_return_slot_pattern_id) {
|
||||
return_slot_pattern_id = *maybe_return_slot_pattern_id;
|
||||
}
|
||||
|
||||
auto name = PopNameComponent(context);
|
||||
auto name = PopNameComponent(context, return_slot_pattern_id);
|
||||
if (!name.params_id.is_valid()) {
|
||||
context.TODO(node_id, "function with positional parameters");
|
||||
name.params_id = SemIR::InstBlockId::Empty;
|
||||
@@ -232,7 +238,7 @@ static auto BuildFunctionDecl(Context& context,
|
||||
auto function_info =
|
||||
SemIR::Function{{name_context.MakeEntityWithParamsBase(
|
||||
name, decl_id, is_extern, introducer.extern_library)},
|
||||
{.return_storage_id = return_storage_id,
|
||||
{.return_slot_id = name.return_slot_id,
|
||||
.virtual_modifier = virtual_modifier}};
|
||||
if (is_definition) {
|
||||
function_info.definition_id = decl_id;
|
||||
@@ -332,7 +338,7 @@ static auto HandleFunctionDefinitionAfterSignature(
|
||||
context.AddCurrentCodeBlockToFunction();
|
||||
|
||||
// Check the return type is complete.
|
||||
CheckFunctionReturnType(context, function.return_storage_id, function,
|
||||
CheckFunctionReturnType(context, function.return_slot_id, function,
|
||||
SemIR::SpecificId::Invalid);
|
||||
|
||||
// Check the parameter types are complete.
|
||||
@@ -397,7 +403,7 @@ auto HandleParseNode(Context& context, Parse::FunctionDefinitionId node_id)
|
||||
// If the `}` of the function is reachable, reject if we need a return value
|
||||
// and otherwise add an implicit `return;`.
|
||||
if (context.is_current_position_reachable()) {
|
||||
if (context.functions().Get(function_id).return_storage_id.is_valid()) {
|
||||
if (context.functions().Get(function_id).return_slot_id.is_valid()) {
|
||||
CARBON_DIAGNOSTIC(
|
||||
MissingReturnStatement, Error,
|
||||
"missing `return` at end of function with declared return type");
|
||||
|
||||
Reference in New Issue
Block a user