mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-25 09:20:12 +01:00
Add support for deferring initialization as a template action, and performing the deferred initialization during template instantiation. This is substantially more complex than other conversion actions, for two primary reasons: * The initializer in the generic may have storage arguments as inputs. We model an initializing expression as having a "slot" where initialization writes the location that should be initialized by that initializing expression, and that needs to be an output of the initialization action. * Initialization from a tuple or struct literal needs to recurse into that literal, and the literal will have been spelled in the generic, meaning we don't have an `InstId` that can be used to name the specific version of the initializer as input for nested conversions. These issues are addressed by introducing two new features to the action machinery: In addition to `InstAction`, we now have `MultiInstAction`, which is an action that produces a tuple of instruction values instead of a single instruction value. Initialization actions produce one instruction for the final result, which is spliced at the point of initialization, plus one instruction for each storage argument, which are spliced into the storage argument slots in the original generic. During initialization, if we find one of those splices in the storage argument of an initializing expression, we return the new storage argument back to the initialization action to be included in the specific, instead of overwriting the storage argument in the generic. Actions whose `PerforrmAction` takes a `SpecificId` as input no longer perform automatic refinement of their operands to specific instructions. Instead, the action is given control over when and where it performs that refinement. In `InitializeAction`, we use this freedom to form a `SpecificInst` for the initializer in the primary output block, and form a `SpecificInst` for the target in the target block. When detecting whether we are initializing from a tuple or struct literal, we step over the `SpecificInst` and track its `SpecificId`, and if necessary create a new `SpecificInst` wrapping the sub-initializer when we recurse into the nested element conversion. Assisted-by: Claude and Gemini via Antigravity