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

tqchen pushed a commit to branch revert-18117-ffi-for-each-2
in repository https://gitbox.apache.org/repos/asf/tvm.git

commit 94969340f5525dc29c56895ac232fbdb4830a859
Author: Tianqi Chen <[email protected]>
AuthorDate: Mon Jul 7 07:31:54 2025 -0400

    Revert "[FFI] Replace `Arg2Str` with a more powerful `for_each` (#18117)"
    
    This reverts commit 49b139be8b76aef69e537c44b22a8f370cb72901.
---
 ffi/include/tvm/ffi/base_details.h     | 21 +--------------------
 ffi/include/tvm/ffi/function_details.h | 27 +++++++++++++++++++--------
 2 files changed, 20 insertions(+), 28 deletions(-)

diff --git a/ffi/include/tvm/ffi/base_details.h 
b/ffi/include/tvm/ffi/base_details.h
index d078a5963a..fb7be1a955 100644
--- a/ffi/include/tvm/ffi/base_details.h
+++ b/ffi/include/tvm/ffi/base_details.h
@@ -29,7 +29,6 @@
 #include <tvm/ffi/endian.h>
 
 #include <cstddef>
-#include <type_traits>
 #include <utility>
 
 #if defined(_MSC_VER)
@@ -136,32 +135,14 @@ namespace tvm {
 namespace ffi {
 namespace details {
 
-// a dependent-name version of false, for static_assert
-template <typename>
-inline constexpr bool always_false = false;
-
 // for each iterator
 struct for_each_dispatcher {
   template <typename F, typename... Args, size_t... I>
   static void run(std::index_sequence<I...>, const F& f, Args&&... args) {  // 
NOLINT(*)
-    if constexpr (std::conjunction_v<
-                      std::is_invocable<F, std::integral_constant<size_t, I>, 
Args>...>) {
-      (f(std::integral_constant<size_t, I>{}, std::forward<Args>(args)), ...);
-    } else if constexpr (std::conjunction_v<std::is_invocable<F, size_t, 
Args>...>) {
-      (f(I, std::forward<Args>(args)), ...);
-    } else if constexpr (std::conjunction_v<std::is_invocable<F, Args>...>) {
-      (f(std::forward<Args>(args)), ...);
-    } else {
-      static_assert(always_false<F>, "The function is not invocable with the 
provided arguments");
-    }
+    (f(I, std::forward<Args>(args)), ...);
   }
 };
 
-// Three kinds of function F are acceptable in `for_each`:
-// 1. F(size_t, Arg): argument with its index
-// 2. F(Arg): just the argument
-// 3. F(std::integral_constant<size_t, I>, Arg): argument with its constexpr 
index
-// The third one can make the index available in template arguments and `if 
constexpr`.
 template <typename F, typename... Args>
 void for_each(const F& f, Args&&... args) {  // NOLINT(*)
   for_each_dispatcher::run(std::index_sequence_for<Args...>{}, f, 
std::forward<Args>(args)...);
diff --git a/ffi/include/tvm/ffi/function_details.h 
b/ffi/include/tvm/ffi/function_details.h
index 34e9979d5d..d029c19dd1 100644
--- a/ffi/include/tvm/ffi/function_details.h
+++ b/ffi/include/tvm/ffi/function_details.h
@@ -36,6 +36,23 @@ namespace tvm {
 namespace ffi {
 namespace details {
 
+template <typename ArgType>
+struct Arg2Str {
+  template <size_t i>
+  TVM_FFI_INLINE static void Apply(std::ostream& os) {
+    using Arg = std::tuple_element_t<i, ArgType>;
+    if constexpr (i != 0) {
+      os << ", ";
+    }
+    os << i << ": " << Type2Str<Arg>::v();
+  }
+  template <size_t... I>
+  TVM_FFI_INLINE static void Run(std::ostream& os, std::index_sequence<I...>) {
+    using TExpander = int[];
+    (void)TExpander{0, (Apply<I>(os), 0)...};
+  }
+};
+
 template <typename T>
 static constexpr bool ArgSupported =
     (std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, Any> ||
@@ -61,16 +78,10 @@ struct FuncFunctorImpl {
 #endif
 
   TVM_FFI_INLINE static std::string Sig() {
+    using IdxSeq = std::make_index_sequence<sizeof...(Args)>;
     std::ostringstream ss;
     ss << "(";
-    for_each(
-        [&ss](auto i, const auto& v) {
-          if constexpr (i() != 0) {
-            ss << ", ";
-          }
-          ss << i() << ": " << v;
-        },
-        Type2Str<Args>::v()...);
+    Arg2Str<std::tuple<Args...>>::Run(ss, IdxSeq{});
     ss << ") -> " << Type2Str<R>::v();
     return ss.str();
   }

Reply via email to