Check and lowering support for for loops. (#5698)

Add check support for `for` loops following #1885. This also adds a
basic `Optional` type to the prelude, as that's necessary to support the
new `Iterate` interface.

Depends on #5688, #5697. Those PRs aren't stacked here, but this change
will crash until they land.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
Richard Smith
2025-06-25 23:45:14 +00:00
committed by GitHub
co-authored by Jon Ross-Perkins
parent a556cf41fc
commit 866794b82a
24 changed files with 1640 additions and 77 deletions
+39
View File
@@ -4,7 +4,9 @@
#include "toolchain/check/pattern.h"
#include "toolchain/check/control_flow.h"
#include "toolchain/check/inst.h"
#include "toolchain/check/return.h"
#include "toolchain/check/type.h"
namespace Carbon::Check {
@@ -94,4 +96,41 @@ auto AddBindingPattern(Context& context, SemIR::LocId name_loc,
return {.pattern_id = binding_pattern_id, .bind_id = bind_id};
}
// Returns a VarStorage inst for the given `var` pattern. If the pattern
// is the body of a returned var, this reuses the return slot, and otherwise it
// adds a new inst.
static auto GetOrAddVarStorage(Context& context, SemIR::InstId var_pattern_id,
bool is_returned_var) -> SemIR::InstId {
if (is_returned_var) {
auto& function = GetCurrentFunctionForReturn(context);
auto return_info =
SemIR::ReturnTypeInfo::ForFunction(context.sem_ir(), function);
if (return_info.has_return_slot()) {
return GetCurrentReturnSlot(context);
}
}
auto pattern = context.insts().GetWithLocId(var_pattern_id);
return AddInstWithCleanup(
context, pattern.loc_id,
SemIR::VarStorage{.type_id = ExtractScrutineeType(context.sem_ir(),
pattern.inst.type_id()),
.pattern_id = var_pattern_id});
}
auto AddPatternVarStorage(Context& context, SemIR::InstBlockId pattern_block_id,
bool is_returned_var) -> void {
// We need to emit the VarStorage insts early, because they may be output
// arguments for the initializer. However, we can't emit them when we emit
// the corresponding `VarPattern`s because they're part of the pattern match,
// not part of the pattern.
// TODO: Find a way to do this without walking the whole pattern block.
for (auto inst_id : context.inst_blocks().Get(pattern_block_id)) {
if (context.insts().Is<SemIR::VarPattern>(inst_id)) {
context.var_storage_map().Insert(
inst_id, GetOrAddVarStorage(context, inst_id, is_returned_var));
}
}
}
} // namespace Carbon::Check