Repository: carbon-language/carbon-lang
File: toolchain/check/subst.h (C/C++)

Code before:
  // substitution may be needed into operands of the instruction.
  virtual auto Subst(SemIR::InstId& inst_id) const -> bool = 0;

  // Rebuilds the type of an instruction from the substituted type instruction.
  // By default this builds the unattached type described by the given type ID.
  virtual auto RebuildType(SemIR::TypeInstId type_inst_id) const
      -> SemIR::TypeId;

  // Rebuilds an instruction whose operands were changed by substitution.
  // `orig_inst_id` is the instruction prior to substitution, and `new_inst` is
  // the substituted instruction. Returns the new instruction ID to use to refer
  // to `new_inst`.
  virtual auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst) const
      -> SemIR::InstId = 0;

  // Performs any work needed when no substitutions were performed into an
  // instruction for which `Subst` returned `false`. Provides an opportunity to
  // perform any necessary updates to the instruction beyond updating its
  // operands. Returns the new instruction ID to use to refer to `orig_inst_id`.
  virtual auto ReuseUnchanged(SemIR::InstId orig_inst_id) const
      -> SemIR::InstId {
    return orig_inst_id;
  }

  // A helper for implementing `Rebuild` that constructs and returns an `InstId`
  // for the `new_inst`.
  auto RebuildNewInst(SemIR::LocId loc_id, SemIR::Inst new_inst) const
      -> SemIR::InstId;

 private:
  Context* context_;
};

// Performs substitution into `inst_id` and its operands recursively, using
// `callbacks` to process each instruction. For each instruction encountered,
// calls `Subst` to perform substitution on that instruction.
//
// If `Subst` returns false, the instruction is decomposed into its operands,
// which are substituted recursively, and if any of them change then `Rebuild`
// is used to build a new instruction with the substituted operands.
auto SubstInst(Context& context, SemIR::InstId inst_id,
               const SubstInstCallbacks& callbacks) -> SemIR::InstId;
auto SubstInst(Context& context, SemIR::TypeInstId inst_id,
               const SubstInstCallbacks& callbacks) -> SemIR::TypeInstId;

// A substitution that is being performed.
struct Substitution {
  // The index of a `BindSymbolicName` instruction that is being replaced.
  SemIR::CompileTimeBindIndex bind_id;
  // The replacement constant value to substitute.
  SemIR::ConstantId replacement_id;

Review comment (suggestion):
I find it's usually better to avoid starting a function comment by saying what the function is _for_, because it doesn't tell the reader anything about the contract. How about something like this?

```suggestion
  // Builds a new constant by evaluating `new_inst`, and returns its `InstId`.
```

Code after:
  // substitution may be needed into operands of the instruction.
  virtual auto Subst(SemIR::InstId& inst_id) const -> bool = 0;

  // Rebuilds the type of an instruction from the substituted type instruction.
  // By default this builds the unattached type described by the given type ID.
  virtual auto RebuildType(SemIR::TypeInstId type_inst_id) const
      -> SemIR::TypeId;

  // Rebuilds an instruction whose operands were changed by substitution.
  // `orig_inst_id` is the instruction prior to substitution, and `new_inst` is
  // the substituted instruction. Returns the new instruction ID to use to refer
  // to `new_inst`.
  virtual auto Rebuild(SemIR::InstId orig_inst_id, SemIR::Inst new_inst) const
      -> SemIR::InstId = 0;

  // Performs any work needed when no substitutions were performed into an
  // instruction for which `Subst` returned `false`. Provides an opportunity to
  // perform any necessary updates to the instruction beyond updating its
  // operands. Returns the new instruction ID to use to refer to `orig_inst_id`.
  virtual auto ReuseUnchanged(SemIR::InstId orig_inst_id) const
      -> SemIR::InstId {
    return orig_inst_id;
  }

  // Builds a new constant by evaluating `new_inst`, and returns its `InstId`.
  //
  // This can be used to implement `Rebuild` in straightforward cases.
  auto RebuildNewInst(SemIR::LocId loc_id, SemIR::Inst new_inst) const
      -> SemIR::InstId;

 private:
  Context* context_;
};

// Performs substitution into `inst_id` and its operands recursively, using
// `callbacks` to process each instruction. For each instruction encountered,
// calls `Subst` to perform substitution on that instruction.
//
// If `Subst` returns false, the instruction is decomposed into its operands,
// which are substituted recursively, and if any of them change then `Rebuild`
// is used to build a new instruction with the substituted operands.
auto SubstInst(Context& context, SemIR::InstId inst_id,
               const SubstInstCallbacks& callbacks) -> SemIR::InstId;
auto SubstInst(Context& context, SemIR::TypeInstId inst_id,
               const SubstInstCallbacks& callbacks) -> SemIR::TypeInstId;

// A substitution that is being performed.
struct Substitution {
  // The index of a `BindSymbolicName` instruction that is being replaced.
  SemIR::CompileTimeBindIndex bind_id;
  // The replacement constant value to substitute.