Skip to content

[FFI] Add ref-qualified strict ObjectRef casts#639

Merged
tqchen merged 1 commit into
apache:mainfrom
tqchen:tvm-ffi-refactor-objectref-as-to-use-checkstrict-and-add-as-or-throw-t-on-objectref-and-any
Jun 21, 2026
Merged

[FFI] Add ref-qualified strict ObjectRef casts#639
tqchen merged 1 commit into
apache:mainfrom
tqchen:tvm-ffi-refactor-objectref-as-to-use-checkstrict-and-add-as-or-throw-t-on-objectref-and-any

Conversation

@tqchen

@tqchen tqchen commented Jun 20, 2026

Copy link
Copy Markdown
Member

This PR refactors strict ObjectRef casting to use the Any TypeTraits strict-check path and adds strict throwing APIs.

Main benefit:

  • Any and ObjectRef now have consistent strict as / as_or_throw APIs: both rely on the same TypeTraits strict-check semantics, both return optional values for probe-style as<T>(), and both provide throwing as_or_throw<T>() variants for required casts.
  • ObjectRef casts can now support richer compatibility checks through TypeTraits<ObjectRefType>::CheckAnyStrict, instead of being limited to the target ref's canonical ContainerType instance check.
  • ObjectRefType::ContainerType now has an explicit _type_container_is_exact invariant. Ordinary refs inherit true from ObjectRef, while richer parameterized refs such as Array<T>, Map<K,V>, Tuple<...>, and object-backed Variant<...> opt out because their accepted values are determined by TypeTraits, not only by the backing container. GetRef is guarded to only work for exact-container refs.

API behavior:

  • ObjectRef::as<ObjectRefType>() const& returns std::optional<ObjectRefType>. For a non-null source, it succeeds only when TypeTraits<ObjectRefType>::CheckAnyStrict accepts the object through a compact temporary TVMFFIAny view. On success, it returns a ref that shares the original object pointer. On type mismatch, it returns std::nullopt.
  • ObjectRef::as<ObjectRefType>() && has the same strict-check and std::nullopt behavior, but moves the object pointer into the returned ref on success and clears the source ref.
  • For null ObjectRef sources, ObjectRef::as<ObjectRefType>() returns a successful null ref when the target ref type is nullable, and returns std::nullopt for non-nullable target refs. The null path is explicit and is not treated as a globally cold failure path.
  • ObjectRef::as_or_throw<ObjectRefType>() const& and && are the throwing forms of the same strict ObjectRef cast. They return ObjectRefType on success, preserve/move the object pointer according to the receiver qualifier, return a null ref for nullable null targets, and throw TypeError for non-nullable null or type-mismatch cases.
  • Any::as_or_throw<T>() const& and && are strict reinterpretation helpers for Any. They call the corresponding strict as<T>() path, return T on success, and throw TypeError on mismatch. They do not run fallback conversions; use cast<T>() when conversion is intended.
  • Optional-returning as APIs intentionally do not use success/failure prediction annotations because std::nullopt can be a normal probe result. Throwing APIs mark only the final failure/throw path as cold, and ObjectRef::as_or_throw marks the strict-check success path as likely because mismatch throws.

Implementation notes:

  • ObjectRef::as<T>() no longer relies on T::ContainerType as the complete runtime compatibility test. It piggy-backs on Any TypeTraits strict checks, so ref types with richer strict compatibility rules work consistently with Any.
  • The temporary TVMFFIAny setup is deliberately kept inline in the non-null ObjectRef paths. This preserves explicit null behavior and lets as_or_throw call TypeTraits<T>::GetMismatchTypeInfo for richer diagnostics instead of reducing to as<T>() and losing the synthesized Any view.
  • The compact temporary Any view is expected to optimize away on hot paths; GCC/Clang assembly probes confirmed direct object-header loads/type-index comparisons for the checked ObjectRef paths.

Changes:

  • Add ref-qualified ObjectRef::as<T>() and ObjectRef::as_or_throw<T>() overloads for const and rvalue receivers.
  • Add Any::as_or_throw<T>() const/rvalue helpers.
  • Keep ObjectRef null handling explicit while using temporary TVMFFIAny views for rich TypeTraits checks and mismatch messages.
  • Add _type_container_is_exact and guard GetRef so it is only used for refs whose ContainerType is an exact acceptance predicate.
  • Add focused tests for const and move variants of as<T>() and as_or_throw<T>(), plus compile-time coverage for exact/non-exact container-ref flags.
  • Update TVM_FFI_UNSAFE_ASSUME lowering to be more robust for GCC.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces as_or_throw() methods for both Any and ObjectRef classes to strictly reinterpret types or throw a TypeError upon failure. It also updates ObjectRef::as() to support rvalue and lvalue overloads with strict type checking, and refines the TVM_FFI_UNSAFE_ASSUME macro for GCC to use __builtin_unreachable(). The reviewer suggests simplifying the ObjectRef::as_or_throw() implementations by delegating directly to as() to eliminate duplicated low-level logic and improve maintainability.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread include/tvm/ffi/any.h
@tqchen tqchen force-pushed the tvm-ffi-refactor-objectref-as-to-use-checkstrict-and-add-as-or-throw-t-on-objectref-and-any branch 6 times, most recently from 5d556f1 to f5bdcc8 Compare June 20, 2026 23:30
Refactor ObjectRef::as<T>() and as_or_throw<T>() to support const and rvalue ObjectRef paths. Reuse Any TypeTraits checks through inline TVMFFIAny views for richer ObjectRef compatibility checks and mismatch messages, while keeping null handling explicit.

Add focused tests for const and move variants of as<T>() and as_or_throw<T>().
@tqchen tqchen force-pushed the tvm-ffi-refactor-objectref-as-to-use-checkstrict-and-add-as-or-throw-t-on-objectref-and-any branch from f5bdcc8 to 39bd5e2 Compare June 20, 2026 23:35
@tqchen tqchen merged commit fbb2b5c into apache:main Jun 21, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants