The GitHub Actions job "CI" on tvm-ffi.git/structural-error-context has failed.
Run started by GitHub user tqchen (triggered by tqchen).

Head commit for run:
549cfd3c23b1e91d11c24e8f6c15531b26bf96e8 / tqchen <[email protected]>
[EXTRA][FEAT] StructuralErrorContext for structural-context-aware error 
reporting

When code throws while recursively visiting an Object tree, the resulting
error message lacks position context — the user sees what went wrong but
not where in the tree. This change adds a typed payload to attach the
visit chain to Error and resolve it to a structured access path.

Recording is best-effort: callers are not required to instrument every
node along the visit path. Whatever frames happen to be wrapped with
BEGIN/END (or seeded by THROW) get recorded; FindAccessPaths then does
a best-effort match of that sparse breadcrumb against the live tree.
Missing intermediates are tolerated — sparse anchors still narrow the
match, and allow_prefix_match=true reports the deepest reached prefix
when the innermost frame is unreachable.

Expected usage

A visitor or checker instruments each visit level with BEGIN/END so each
recursion frame records its node on rethrow. At the root of the visit,
a try/catch retrieves the StructuralErrorContext and calls
FindAccessPaths to resolve the recorded chain into AccessPaths usable
for rich error reporting.

  void Visitor::Visit(const ObjectRef& node) {
    TVM_FFI_STRUCTURAL_VISIT_BEGIN();
    DispatchVisitFields(node);
    TVM_FFI_STRUCTURAL_VISIT_END(node);
  }

  void Check(const ObjectRef& root) {
    try {
      visitor.Visit(root);
    } catch (Error& err) {
      auto sc = StructuralErrorContext::TryGetFromError(err);
      if (sc) {
        auto paths = StructuralErrorContext::FindAccessPaths(root, sc.value());
        // paths describes WHERE in root the error fired, e.g.
        //   Root -> Attr("body") -> ArrayItem(2) -> Attr("cond") -> Attr("lhs")
        // Use it to enrich the message with structured position info.
      }
      throw;
    }
  }

TVM_FFI_STRUCTURAL_VISIT_THROW is the variant for cases where the bad
spot is somewhere the surrounding BEGIN/END does not already record —
typically a child field of the visited node, or a helper called from a
visit that has no BEGIN/END of its own. It seeds the context with the
given node as the innermost frame.

  void Visitor::VisitTPair(const ObjectRef& node) {
    TVM_FFI_STRUCTURAL_VISIT_BEGIN();
    if (auto pair = node.as<TPair>()) {
      if (!IsValid(pair.value()->lhs)) {
        // Throw site pinned at .lhs (not at node) so the AccessPath
        // ends at .lhs. The surrounding END appends `node` next.
        TVM_FFI_STRUCTURAL_VISIT_THROW(ValueError, pair.value()->lhs)
            << "invalid lhs";
      }
    }
    TVM_FFI_STRUCTURAL_VISIT_END(node);
  }

FindAccessPaths walks root via reflection, normalizes the recorded
pattern (drops nulls, collapses consecutive duplicates), and returns
one or more AccessPaths whose innermost step points at the throw site.

API

- StructuralErrorContext: typed payload in tvm/ffi/extra/, with a
  mutable List<ObjectRef> reverse_visit_pattern (innermost-first
  breadcrumb trail) and an optional prev_error_context (preserved
  when wrapping a pre-existing payload in extra_context).
- TVM_FFI_STRUCTURAL_VISIT_BEGIN / TVM_FFI_STRUCTURAL_VISIT_END(node):
  instrument visit dispatch. On rethrow, END appends node to the
  in-flight Error's StructuralErrorContext.
- TVM_FFI_STRUCTURAL_VISIT_THROW(kind, node) << "msg": throw an Error
  with the StructuralErrorContext pre-attached; use when END would not
  already record the throw site.
- StructuralErrorContext::FindAccessPaths(root, ctx, allow_prefix_match):
  walks root via reflection and returns Array<AccessPath> for matched
  positions. Best-effort match — does not require every visited node to
  be recorded. Strict full-match by default; allow_prefix_match=true
  reports the deepest prefix when the innermost frame is unreachable.
- StructuralErrorContext::TryGetFromError(err): inline helper to fetch
  the payload from an Error, NullOpt if absent.

ABI

No ABI changes. Reuses the existing Error::extra_context slot via
existing ObjectUnsafe patterns.

Tests cover macro-builds-chain for both BEGIN/END and THROW variants,
FindAccessPaths correctness (basic match, all access kinds, sparse
anchors demonstrating best-effort match with missing intermediates,
partial-chain prefix matching, edge cases including root-itself match,
records cleanup for null and dup-consecutive), and TryGetFromError
composition.

Report URL: https://github.com/apache/tvm-ffi/actions/runs/25880684968

With regards,
GitHub Actions via GitBox


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

Reply via email to