Skip to content

Class-decorator form of prim_func_pass broken with tvm-ffi >= 0.1.10 (__slots__ on Object) #571

@oraluben

Description

@oraluben

Summary

Starting with apache-tvm-ffi >= 0.1.10, the class-decorator form of tvm.tir.transform.prim_func_pass raises AttributeError: '...' object has no attribute '_inst'.

Reproducer

from tvm.tir.transform import prim_func_pass
from tvm.ir import IRModule
from tvm import tir

@prim_func_pass(opt_level=0, name="MyPass")
class MyPass:
    def transform_function(self, func: tir.PrimFunc, mod: IRModule, ctx) -> tir.PrimFunc:
        return func

p = MyPass()  # AttributeError: 'MyPass' object has no attribute '_inst'

Works with apache-tvm-ffi == 0.1.7, fails with >= 0.1.8.

Root Cause

In tvm/tir/transform/function_pass.py, _wrap_class_function_pass creates PyFunctionPass(PrimFuncPass) and sets self._inst = inst in __init__ (line 53).

With tvm-ffi < 0.1.8 (ctypes backend), Object has no __slots__, so __dict__ exists and arbitrary attributes can be set.

With tvm-ffi >= 0.1.8, tvm_ffi.core.Object and CObject define __slots__ = (). The entire MRO (Object → Pass → PrimFuncPass → PyFunctionPass) has empty __slots__ and no __dict__, so setting _inst raises AttributeError.

# tvm-ffi 0.1.7
Object.__slots__ → not set (has __dict__)

# tvm-ffi 0.1.10
Object.__slots__ = ()      # no __dict__
CObject.__slots__ = ()     # no __dict__

Impact

Any code using the class-decorator form of prim_func_pass:

@prim_func_pass(opt_level=0)
class MyPass:
    def transform_function(self, func, mod, ctx):
        ...

The function-decorator form is unaffected:

def my_pass(func, mod, ctx):
    ...
prim_func_pass(my_pass, opt_level=0)

This pattern is documented in TVM's own docstring (function_pass.py line 112-120) and works on tvm-ffi < 0.1.8.

Possible Fixes

  1. Add __slots__ = ("_inst",) to PyFunctionPass in function_pass.py
  2. Or ensure Object allows __dict__ in derived classes (e.g. by not setting __slots__ on Object, or by including __dict__ in the slots)

Workaround

Use the function-form instead of class-form:

def _my_pass(func, mod, ctx):
    ...

MyPass = prim_func_pass(_my_pass, opt_level=0, name="MyPass")

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions