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.git


The following commit(s) were added to refs/heads/main by this push:
     new c6f2f7e29c [REFACTOR][PYTHON] Let FFI normalize wrapped type arguments 
(#20730)
c6f2f7e29c is described below

commit c6f2f7e29ca19113041520c871ba9cae1f0f7091
Author: Tianqi Chen <[email protected]>
AuthorDate: Wed Oct 14 15:48:27 2026 -0400

    [REFACTOR][PYTHON] Let FFI normalize wrapped type arguments (#20730)
    
    Native call construction already normalizes wrapper objects, so Relax
    helpers only need to evaluate type factories. Remove redundant eager
    conversion from the type-argument helpers and keep object protocol
    coverage in the existing suites.
---
 python/tvm/relax/op/base.py                        |  17 +--
 python/tvm/relax/script/ir_builder/op.py           |  11 +-
 .../python/runtime/test_runtime_object_protocol.py | 132 ---------------------
 3 files changed, 3 insertions(+), 157 deletions(-)

diff --git a/python/tvm/relax/op/base.py b/python/tvm/relax/op/base.py
index 8f0125c7cd..3297e5442b 100644
--- a/python/tvm/relax/op/base.py
+++ b/python/tvm/relax/op/base.py
@@ -354,11 +354,7 @@ def call_builtin_with_ctx(
 
     if ty_args is not None:
         ty_args = [
-            value()
-            if callable(value) and not isinstance(value, Type)
-            else value.__tvm_ffi_object__()
-            if hasattr(value, "__tvm_ffi_object__")
-            else value
+            value() if callable(value) and not isinstance(value, Type) else 
value
             for value in ty_args
         ]
     return Call(
@@ -775,16 +771,7 @@ def call_pure_packed(
     elif not isinstance(ty_args, list):
         ty_args = [ty_args]
 
-    ty_args = [
-        (
-            ty()
-            if callable(ty) and not isinstance(ty, Type)
-            else ty.__tvm_ffi_object__()
-            if hasattr(ty, "__tvm_ffi_object__")
-            else ty
-        )
-        for ty in ty_args
-    ]
+    ty_args = [ty() if callable(ty) and not isinstance(ty, Type) else ty for 
ty in ty_args]
 
     # note: if we need attributes, we can also take them here
 
diff --git a/python/tvm/relax/script/ir_builder/op.py 
b/python/tvm/relax/script/ir_builder/op.py
index b2fcae0a0c..6c3b94f326 100644
--- a/python/tvm/relax/script/ir_builder/op.py
+++ b/python/tvm/relax/script/ir_builder/op.py
@@ -310,16 +310,7 @@ def call_packed(
     elif not isinstance(ty_args, list):
         ty_args = [ty_args]
 
-    ty_args = [
-        (
-            ty()
-            if callable(ty) and not isinstance(ty, _ir.Type)
-            else ty.__tvm_ffi_object__()
-            if hasattr(ty, "__tvm_ffi_object__")
-            else ty
-        )
-        for ty in ty_args
-    ]
+    ty_args = [ty() if callable(ty) and not isinstance(ty, _ir.Type) else ty 
for ty in ty_args]
 
     is_default = False
     if "attrs_type_key" in kwargs:
diff --git a/tests/python/runtime/test_runtime_object_protocol.py 
b/tests/python/runtime/test_runtime_object_protocol.py
deleted file mode 100644
index 1f07859b4a..0000000000
--- a/tests/python/runtime/test_runtime_object_protocol.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-"""Native FFI object conversion for TVM wrappers and script helpers."""
-
-import pytest
-import tvm_ffi
-
-import tvm
-import tvm.testing
-from tvm import ir, relax, te, tirx
-from tvm.relax.script.ir_builder import op as relax_op
-from tvm.script.ir_builder.stmt import _as_expr
-from tvm.tirx.script.ir_builder import op as tir_op
-from tvm.tirx.tile.instruction import _expr
-
-
-class ObjectWrapper:
-    def __init__(self, value):
-        self.value = value
-
-    def __tvm_ffi_object__(self) -> tvm_ffi.Object:
-        return self.value
-
-
-def test_object_protocol_identity():
-    value = ir.Var("x", "int32")
-    wrapped = ObjectWrapper(value)
-    assert tvm_ffi.convert(wrapped) is value
-    echo = tvm_ffi.convert_func(lambda x: x)
-    assert echo(wrapped).same_as(value)
-    assert tvm_ffi.convert([wrapped])[0].same_as(value)
-    assert tvm_ffi.convert({"value": [wrapped]})["value"][0].same_as(value)
-    assert _as_expr(wrapped) is value
-    assert _expr(wrapped) is value
-
-
[email protected]("unequal", [False, True])
-def test_deferred_comparison_protocol(unequal):
-    x, y = ir.Var("x", "int32"), ir.Var("y", "int32")
-    comparison = x != y if unequal else x == y
-    assert bool(comparison) is unequal
-    assert bool(x != x if unequal else x == x) is not unequal
-    result = tvm_ffi.convert(comparison)
-    assert isinstance(result, tirx.NE if unequal else tirx.EQ)
-    assert result.a.same_as(x)
-    assert result.b.same_as(y)
-    echo = tvm_ffi.convert_func(lambda x: x)
-    tvm.ir.assert_structural_equal(echo(comparison), result)
-    tvm.ir.assert_structural_equal(tvm_ffi.convert([comparison])[0], result)
-    assert isinstance(tir_op.logical_not(comparison), tirx.Not)
-    assert isinstance(tir_op.logical_and(comparison, True), tirx.And)
-    assert isinstance(tir_op.logical_or(comparison, False), tirx.Or)
-    tvm.ir.assert_structural_equal(_as_expr(comparison), result)
-    tvm.ir.assert_structural_equal(_expr(comparison), result)
-
-
-def test_tensor_slice_protocol():
-    tensor = te.placeholder((2, 3), name="A")
-    sliced = tensor[0][1]
-    result = tvm_ffi.convert(sliced)
-    assert result.op.same_as(ir.Op.get("te.tensor_load"))
-    assert result.args[0].same_as(tensor)
-    assert list(result.args[1:]) == [0, 1]
-    echo = tvm_ffi.convert_func(lambda x: x)
-    tvm.ir.assert_structural_equal(echo(sliced), result)
-    tvm.ir.assert_structural_equal(tvm_ffi.convert([sliced])[0], result)
-
-
-def test_enum_protocol():
-    enum = tirx.CallEffectKind.Pure
-    result = tvm_ffi.convert(enum)
-    assert isinstance(result, tirx.IntImm)
-    assert result.value == 1
-    assert result.ty == ir.PrimType("int32")
-    echo = tvm_ffi.convert_func(lambda x: x)
-    tvm.ir.assert_structural_equal(echo(enum), result)
-    tvm.ir.assert_structural_equal(tvm_ffi.convert([enum])[0], result)
-
-
-def test_builder_protocol_preserves_host_values():
-    host = object()
-    assert tir_op.select(True, host, None) is host
-    assert relax_op.if_then_else_(True, host, None) is host
-    assert tir_op.logical_and(True, host) is host
-    assert tir_op.logical_or(False, host) is host
-    x = ir.Var("x", "int32")
-    condition = ObjectWrapper(tvm_ffi.convert(x == 0))
-    true_value = ObjectWrapper(x)
-    tvm.ir.assert_structural_equal(
-        tir_op.select(condition, true_value, 0), 
tir_op.select(condition.value, x, 0)
-    )
-    tvm.ir.assert_structural_equal(
-        relax_op.if_then_else_(condition, true_value, 0),
-        relax_op.if_then_else_(condition.value, x, 0),
-    )
-
-
[email protected](
-    "make_call", [relax.op.call_builtin_with_ctx, relax.op.call_pure_packed, 
relax_op.call_packed]
-)
-def test_wrapped_type_arguments(make_call):
-    ty = ir.PrimType("int32")
-    call = make_call("custom", (), ty_args=[ObjectWrapper(ty)])
-    assert call.ty_args[0].same_as(ty)
-    call = make_call("custom", (), ty_args=[lambda: ty])
-    assert call.ty_args[0].same_as(ty)
-
-
-def test_invalid_object_protocol_result():
-    echo = tvm_ffi.convert_func(lambda x: x)
-    with pytest.raises(TypeError):
-        echo(ObjectWrapper(1))
-    with pytest.raises(TypeError):
-        tvm_ffi.convert([ObjectWrapper(1)])
-
-
-if __name__ == "__main__":
-    tvm.testing.main()

Reply via email to