This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new 4b60b1ef [DOC] Clarify UnchangedOr replacement and identity semantics 
(#797)
4b60b1ef is described below

commit 4b60b1efca46e1c5722f2855f847ad81f9fc71b1
Author: Tianqi Chen <[email protected]>
AuthorDate: Wed Sep 16 13:48:06 2026 -0400

    [DOC] Clarify UnchangedOr replacement and identity semantics (#797)
    
    Clarify that `UnchangedOr` records whether to retain the original or
    supply a replacement, including replacements with the same identity.
    Explain why in-place updates can satisfy `UnchangedOrSameAs` despite
    structural changes, and align constructors, predicates, accessor
    preconditions, and ownership-example comments with that contract.
---
 include/tvm/ffi/extra/structural_mutate.h | 34 ++++++++++++++++++++-----------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/include/tvm/ffi/extra/structural_mutate.h 
b/include/tvm/ffi/extra/structural_mutate.h
index d3e59514..e0ae09a1 100644
--- a/include/tvm/ffi/extra/structural_mutate.h
+++ b/include/tvm/ffi/extra/structural_mutate.h
@@ -177,7 +177,7 @@ template <typename T>
 inline constexpr bool is_unchanged_or_v<UnchangedOr<T>> = true;
 }  // namespace details
 
-/*! \brief Tag for a mutation result that produced no new value. */
+/*! \brief Tag indicating that the caller should retain the original value. */
 struct Unchanged {
   /*!
    * \brief Copy this tag to its raw marker representation.
@@ -206,16 +206,24 @@ struct Unchanged {
 };
 
 /*!
- * \brief A structural-mutation result containing a replacement or no new 
value.
+ * \brief A structural-mutation result containing a replacement or an 
instruction
+ *        to retain the original value.
+ *
+ * An Unchanged result indicates that no replacement is needed.
+ * A stored replacement may also refer to the original object.
  *
  * \tparam T The replacement value type.
+ * \note In-place updates retain the input's identity, so
+ *       ``UnchangedOrSameAs`` may return true despite structural changes.
+ *       If structural change detection is needed, track changes separately
+ *       or disable in-place mutation.
  * \note ``UnchangedOr`` is deliberately designed to only have 
rvalue-qualified value accessors,
  *       so the compiler forces a value to leave the container exactly once, 
via a move.
  *
  * \code{.cpp}
- * // resolves to the original when the descent reported unchanged
+ * // resolves to the original when descent returned the Unchanged marker
  * copy->a = std::move(a).ValueOrUnchanged(std::move(copy->a));
- * // already known to be changed, so no original is needed
+ * // already known to contain a replacement, so no original is needed
  * copy->b = std::move(b).ValueUnchecked();
  * \endcode
  */
@@ -233,14 +241,14 @@ class UnchangedOr {
   TVM_FFI_INLINE UnchangedOr(Unchanged unchanged) noexcept : 
data_(static_cast<Any>(unchanged)) {}
 
   /*!
-   * \brief Construct a changed result from a replacement value.
+   * \brief Construct a result containing a replacement value.
    * \param value The replacement value.
    */
   // NOLINTNEXTLINE(google-explicit-constructor,runtime/explicit)
   TVM_FFI_INLINE UnchangedOr(T value) : data_(Any(std::move(value))) {}
 
   /*!
-   * \brief Construct a changed result from an implicitly convertible 
replacement value.
+   * \brief Construct a result containing an implicitly convertible 
replacement value.
    * \tparam U Source value type, implicitly convertible to T.
    * \param value The replacement value to copy or move.
    */
@@ -284,17 +292,19 @@ class UnchangedOr {
   TVM_FFI_INLINE UnchangedOr& operator=(UnchangedOr&&) noexcept = default;
 
   /*!
-   * \brief Whether this result asks the caller to preserve the original value.
-   * \return Whether the result is unchanged.
+   * \brief Whether this result holds the Unchanged marker, retaining the 
original value.
+   * \return Whether the result holds the Unchanged marker.
    */
   TVM_FFI_INLINE bool IsUnchanged() const& noexcept {
     return data_.type_index() == TypeIndex::kTVMFFIUnchanged;
   }
 
   /*!
-   * \brief Whether this result is unchanged or contains the original object 
identity.
+   * \brief Whether this result holds the Unchanged marker or a value that 
compares
+   *        ``same_as`` to \p original.
    * \param original The original value.
-   * \return Whether the original identity may be reused.
+   * \return Whether the original value may be retained without replacement.
+   * \note For objects, this checks identity, not contents or subtree changes.
    */
   TVM_FFI_INLINE bool UnchangedOrSameAs(const T& original) const& noexcept {
     return IsUnchanged() || data_.same_as(original);
@@ -337,9 +347,9 @@ class UnchangedOr {
   }
 
   /*!
-   * \brief Move the known-changed replacement without checking its state.
+   * \brief Move the stored replacement value without checking its state.
    * \return The replacement value.
-   * \pre The result is not unchanged.
+   * \pre ``!IsUnchanged()``.
    */
   TVM_FFI_INLINE T ValueUnchecked() && {
     return details::AnyUnsafe::MoveFromAnyAfterCheck<T>(std::move(data_));

Reply via email to