-
Notifications
You must be signed in to change notification settings - Fork 340
Description
Background
We want to keep python-3.8 compatibility for a while. One major blocker is the new type hinting for containers like list[str] since python 3.9. We try to use from __future__ import annotations to enable that feature in 3.8.
Detail background of from __future__ import annotations
from __future__ import annotations enables lazy evaluation of type annotation, and makes all annotations to be string.
from __future__ import annotations will be deprecated and removed in the future (not before 3.13 EOL).
Even after python 3.14 with annotationlib.get_annotations, string annotations from from __future__ import annotations could not be resolved as expected.
https://docs.python.org/3/howto/annotations.html#manually-un-stringizing-stringized-annotations
Issue
Ideally, when variables used in type annotations (e.g. M in X: T.Tensor((M, ))) is used in the inner function, it will be captured in closure of inner function, and can be resolved later.
But when it's not, the type annotation could not be solved and remain string.
This issue is blocking #963 . Note if M is accessed in the prim_func, e.g. T.Kernel(M, threads=128), the problem disappear. I'm still investigating, but based on the description, it seems that when the function body do not access variable from outer scope, they'll not be included in function closure and therefore the typing annotation string cannot be resolved at runtime.
https://docs.python.org/3/reference/compound_stmts.html#annotations
If the future statement from future import annotations is present, all annotations are instead stored as strings:
One possible workaround is to create T.Tensor before defining T.prim_func.
from __future__ import annotations
import tilelang
import tilelang.language as T
@tilelang.jit(out_idx=[-1])
def kernek_main(M):
@T.prim_func
def k(
X: T.Tensor((M, )),
):
with T.Kernel(128 * 128, threads=128) as (bx, ):
pass
return k
def main(M=8192):
kernel = kernek_main(M)
print(kernel.get_kernel_source())
if __name__ == "__main__":
main()
Traceback
$ python test.py
2025-10-20 17:56:08 [TileLang:tilelang.env:WARNING]: Loading tilelang libs from dev root: /home/yyc/repo/tilelang/build
error: Mismatched type on argument #1 when calling: `script.ir_builder.tir.Arg(0: ffi.String, 1: ffi.Object) -> ffi.Object`. Expected `ffi.Object` but got `const char*`
--> /home/yyc/repo/tilelang/test.py:11:5
|
11 | def k(
| ^^^^^^
note: run with `TVM_BACKTRACE=1` environment variable to display a backtrace.Possible solution
-
Disallow all use of
from __future__ import annotations
Pros:- This statement is not encouraged and is planned to be removed
Cons
- Need some other way to maintain/test 3.8 support
- We don't have control of user code
-
Manually access variable to bound to closure
Pros:- Minimal changes to framework
Cons:
- Need to manually add a useless statement, might be hard to be aware of
-
When creating
prim_func, manually read stack to read locals of upper frame, and add them in annotation resolving
Pros:- Seems to works perfectly in simple cases
Cons:
- Hard to maintain
- edge case?