Seven-Streams opened a new pull request, #711:
URL: https://github.com/apache/tvm-ffi/pull/711

   ## Summary
   
   This PR completes the Rust structural traversal API by giving all four 
structural operations a
   typed callback and `#[dispatch(...)]` frontend while preserving the 
distinction between
   engine-driven and user-driven recursion.
   
   | API | Recursion owner | Callback state model | Generated dispatch |
   |---|---|---|---|
   | `structural_walk` | Engine | `FnMut` capture / walker fields | 
`#[dispatch(walk)]` |
   | `structural_map` | Engine | `FnMut` capture / mapper fields | 
`#[dispatch(map)]` |
   | `structural_visit` | Callback or visitor | `VisitCallbacks<State, ...>` + 
`VisitContext<State>` | `#[dispatch(visit)]` |
   | `structural_mutate` | Callback or mutator | `MutateCallbacks<State, ...>` 
+ `MutateContext<State>` | `#[dispatch(mutate)]` |
   
   The callback-backed visit and mutate paths implement `StructuralVisitor` and
   `StructuralMutator` directly. As a result, callbacks, generated dispatch 
types, and hand-written
   visitors/mutators now share the same mutable runtime protocol and registered 
structural hooks.
   
   ## Motivation
   
   Before this PR, the Rust walk/map layers already accepted typed callbacks, 
but user-driven visit
   and mutate required hand-written trait implementations. In addition, 
`#[dispatch(visit)]` named
   the engine-driven walk dispatcher rather than the `StructuralVisitor` layer, 
leaving the four APIs
   asymmetric.
   
   This PR aligns the names and entry points with their recursion model, adds 
lightweight callback
   frontends for one-off user-driven traversals, and retains a fully 
borrow-checked state model for
   callbacks that recursively re-enter themselves.
   
   ## Changes
   
   ### Extend `#[dispatch]` to four explicit modes
   
   - Add `dispatch(walk)` for engine-driven observers using `walk_*` handlers.
   - Keep `dispatch(map)` for engine-driven replacements using `map_*` handlers.
   - Make `dispatch(visit)` generate `StructuralVisitor` from user-driven 
`visit_*` handlers.
   - Add `dispatch(mutate)` to generate `StructuralMutator` from user-driven 
`mutate_*` handlers.
   - Preserve source-order, first-match dispatch over owned FFI values, 
borrowed object nodes, and
     catch-all `VisitValue`/`MapValue` handlers.
   - Forward an optional trailing `DefRegionKind` argument in every mode.
   - Use mode-specific fallback behavior: `Advance` for walk, no replacement 
for map, default child
     traversal for visit, and the appropriate copy/in-place default for mutate.
   
   ### Add callback-driven structural visitors
   
   - Allow `structural_visit` to accept either `&mut StructuralVisitor`, one 
typed callback, or a
     nested callback tuple.
   - Add `VisitCallbacks<State, ...>` for reusable callback chains with 
ordinary mutable state.
   - Add `VisitContext<State>` with access to state, the current value and 
definition region,
     selected-child recursion, and default child traversal.
   - A matched callback owns traversal of its value; unmatched values use 
default child traversal.
   - Support `()`, `Result<()>`, `Option<VisitInterrupt>`, and
     `Result<Option<VisitInterrupt>>` callback outcomes.
   
   ### Add callback-driven structural mutators
   
   - Allow `structural_mutate` to accept either `&mut StructuralMutator`, one 
typed callback, or a
     nested callback tuple.
   - Add `MutateCallbacks<State, ...>` for reusable callback chains with 
ordinary mutable state.
   - Add `MutateContext<State>` with access to state, the current value and 
definition region,
     borrowed-child mutation, owned-child maybe-in-place mutation, default 
mutation, and
     invocation-local variable remapping.
   - A matched callback supplies the final value; unmatched values retain the 
engine's current
     copy/maybe-in-place permission and use default mutation.
   - Keep `MutateContext::default_mutate()` on the copy path because the 
callback may still hold a
     shared borrow of the current value. Owned children can explicitly use
     `maybe_inplace_mutate()` when reuse is safe.
   
   ### Make recursive callback state borrow-checked
   
   - Visit and mutate callbacks remain `Fn`, allowing the same callback to be 
recursively
     re-entered.
   - Callback code is stored independently behind `Rc`, while mutable state and 
the active driver
     remain in the callback wrapper.
   - Recursive context methods require `&mut self`, so Rust rejects a state 
borrow that remains live
     across recursive visit/mutate calls instead of relying on external 
`Cell`/`RefCell` state.
   - Direct callbacks are wrapped in a temporary `VisitCallbacks<(), ...>` or
     `MutateCallbacks<(), ...>`; users opt into state by constructing the 
wrapper explicitly.
   
   ### Preserve structural runtime semantics
   
   - Registered `__s_visit__`, `__s_mutate__`, and `__s_maybe_inplace_mutate__` 
hooks continue to
     receive the active Rust-backed visitor/mutator and can re-enter Rust 
through the shared ABI.
   - Definition-region propagation, reflected-field fallback, interrupt/error 
context, panic
     resumption, and nested traversal state restoration continue to work across 
callback paths.
   - Mutation keeps invocation-local `FreeVar`/`DAGNode` remapping and rechecks 
uniqueness before an
     in-place write.
   - No C or C++ ABI changes are introduced.
   
   ## Compatibility note
   
   The former walk-layer naming is intentionally changed:
   
   - `#[dispatch(visit)]` with `visit_*` observer methods becomes 
`#[dispatch(walk)]` with `walk_*`
     methods.
   - `VisitDispatch` becomes `WalkDispatch`.
   - `DispatchVisitor` becomes `DispatchWalker`.
   
   `#[dispatch(visit)]` now denotes the user-driven visitor layer and generates
   `StructuralVisitor`. Existing hand-written `StructuralVisitor` and 
`StructuralMutator` call sites
   remain valid.
   
   ## Tests
   
   - `cargo test --workspace`
   - `cargo test --workspace --release`
   - `cargo test --workspace --all-features`
   - `RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps`
   - `uv run --group docs sphinx-build -W --keep-going -b html docs 
docs/_build/html`
   - Pre-commit hooks on all changed files
   
   The expanded regression coverage includes callback first-match behavior, 
nested tuples,
   definition regions, selected-child recursion, stateful recursive re-entry, 
interrupts, registered
   hooks, reflection, nested traversals, panic/error propagation, 
copy-on-write/in-place behavior,
   and invocation-local identity remapping.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to