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

tqchen pushed a commit to branch tqchen/printer-refinement
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/tqchen/printer-refinement by 
this push:
     new 42170ee91c [FIX][Script] Preserve expression and parameter references
42170ee91c is described below

commit 42170ee91cbb10cdf56d3346afc2d0ce806681ee
Author: Tianqi Chen <[email protected]>
AuthorDate: Thu Oct 1 16:29:09 2026 +0000

    [FIX][Script] Preserve expression and parameter references
    
    Keep compact expressions free of deferred declarations, emit pending 
variables in encounter order, retain shared parameter identities and map 
parameter diagnostics to their visible components.
---
 src/script/printer/doc_translator.cc |  8 ++++----
 src/script/printer/printer.cc        | 30 ++++++++++++++++++------------
 src/tirx/script/printer/function.cc  | 22 +++++++++++++++++++---
 3 files changed, 41 insertions(+), 19 deletions(-)

diff --git a/src/script/printer/doc_translator.cc 
b/src/script/printer/doc_translator.cc
index a2fe6ce197..cdf9e0fa73 100644
--- a/src/script/printer/doc_translator.cc
+++ b/src/script/printer/doc_translator.cc
@@ -169,11 +169,12 @@ details::TranslationResult TranslateComplete(ffi::AnyView 
obj, TranslationEngine
   IdDoc metadata_id = engine->AllocId("metadata");
   IdDoc metadata_loader = engine->AllocId("tvm");
   engine->ExchangeExtraState("ir.metadata_id", metadata_id);
+  bool compact_expression = false;
   auto docs = engine->WithDocScope([&]() {
     ffi::Optional<ExprDoc> expression = engine->Translate(obj);
     if (expression.has_value()) {
-      if (!engine->GetExtraConfig<bool>("script.verbose_expr", true))
-        engine->CurrentScopeDocs().clear();
+      compact_expression = 
!engine->GetExtraConfig<bool>("script.verbose_expr", true);
+      if (compact_expression) engine->CurrentScopeDocs().clear();
       engine->Emit(ExprStmtDoc(expression.value()), obj.as<ffi::ObjectRef>());
     }
     if (!binding_names.empty() && !engine->CurrentScopeDocs().empty()) {
@@ -187,10 +188,9 @@ details::TranslationResult TranslateComplete(ffi::AnyView 
obj, TranslationEngine
     }
   });
   auto root_declarations = engine->WithDocScope([&]() {
+    if (compact_expression) return;
     auto pending = engine->GetImplicitDefs();
     std::vector<std::pair<Var, IdDoc>> remaining(pending.begin(), 
pending.end());
-    std::sort(remaining.begin(), remaining.end(),
-              [](const auto& a, const auto& b) { return a.second->name < 
b.second->name; });
     for (const auto& [var, _] : remaining) {
       if (!pending.count(var)) continue;
       if (auto rhs = engine->Translate(var, var)) {
diff --git a/src/script/printer/printer.cc b/src/script/printer/printer.cc
index dafae45eda..1c9b184df2 100644
--- a/src/script/printer/printer.cc
+++ b/src/script/printer/printer.cc
@@ -72,7 +72,7 @@ void RecoverDocPaths(
     ffi::AnyView value, const std::vector<AccessPath>& enclosing_ir_paths,
     const std::unordered_map<const ffi::Object*, ffi::ObjectRef>& origins,
     const std::unordered_map<const ffi::Object*, std::vector<AccessPath>>& 
ir_paths,
-    std::unordered_set<const ffi::Object*>* active) {
+    std::unordered_set<const ffi::Object*>* active, bool function_parameter = 
false) {
   const ffi::Object* object = value.as<ffi::Object>();
   if (!object || !active->insert(object).second) return;
   std::vector<AccessPath> context = enclosing_ir_paths;
@@ -90,10 +90,15 @@ void RecoverDocPaths(
           }
         }
         if (context.empty()) context = candidates->second;
-        for (const AccessPath& path : context) {
-          if (std::none_of(doc->source_paths.begin(), doc->source_paths.end(),
-                           [&](const AccessPath& existing) { return 
SamePath(existing, path); })) {
-            doc->source_paths.push_back(path);
+        // Parameter wrappers provide occurrence context; the name and type
+        // carry their own visible ranges.
+        if (!(function_parameter && value.as<AssignDocNode>())) {
+          for (const AccessPath& path : context) {
+            if (std::none_of(
+                    doc->source_paths.begin(), doc->source_paths.end(),
+                    [&](const AccessPath& existing) { return 
SamePath(existing, path); })) {
+              doc->source_paths.push_back(path);
+            }
           }
         }
       }
@@ -101,19 +106,20 @@ void RecoverDocPaths(
   }
   if (auto array = value.as<ffi::Array<ffi::Any>>()) {
     for (const auto& child : array.value()) {
-      RecoverDocPaths(child, context, origins, ir_paths, active);
+      RecoverDocPaths(child, context, origins, ir_paths, active, 
function_parameter);
     }
   } else if (auto map = value.as<ffi::Map<ffi::Any, ffi::Any>>()) {
     for (const auto& entry : map.value()) {
       RecoverDocPaths(entry.second, context, origins, ir_paths, active);
     }
   } else {
-    ffi::reflection::ForEachFieldInfo(TVMFFIGetTypeInfo(object->type_index()),
-                                      [&](const TVMFFIFieldInfo* field) {
-                                        if (ffi::String(field->name) == 
"source_paths") return;
-                                        
RecoverDocPaths(ffi::reflection::FieldGetter(field)(object),
-                                                        context, origins, 
ir_paths, active);
-                                      });
+    ffi::reflection::ForEachFieldInfo(
+        TVMFFIGetTypeInfo(object->type_index()), [&](const TVMFFIFieldInfo* 
field) {
+          if (ffi::String(field->name) == "source_paths") return;
+          RecoverDocPaths(ffi::reflection::FieldGetter(field)(object), 
context, origins, ir_paths,
+                          active,
+                          value.as<FunctionDocNode>() && 
ffi::String(field->name) == "args");
+        });
   }
   active->erase(object);
 }
diff --git a/src/tirx/script/printer/function.cc 
b/src/tirx/script/printer/function.cc
index 59bbd3c214..23fef1f784 100644
--- a/src/tirx/script/printer/function.cc
+++ b/src/tirx/script/printer/function.cc
@@ -27,6 +27,7 @@
 #include <algorithm>
 #include <optional>
 #include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -90,19 +91,34 @@ ffi::Optional<ExprDoc> 
PrimFuncDocTranslate(DocTranslatorObj* d, ffi::AnyView in
   FunctionDoc doc(ffi::UnsafeInit{});
   {
     ffi::Array<AssignDoc> args;
+    std::unordered_set<const VarNode*> signature_symbols;
+    for (const Var& var : func->params) {
+      ffi::StructuralWalk<ffi::WalkOrder::kPreOrder>(
+          var->ty, [&](const Var& symbol) -> ffi::Expected<ffi::WalkResult> {
+            signature_symbols.insert(symbol.get());
+            return ffi::WalkResult::Skip();
+          });
+    }
     ffi::Array<IdDoc> param_ids;
-    for (const Var& var : func->params) param_ids.push_back(VarDoc(d, var));
+    for (const Var& var : func->params) {
+      param_ids.push_back(VarDoc(d, var, !signature_symbols.count(var.get())));
+    }
     size_t param_index = 0;
     for (const Var& var : func->params) {
       IdDoc lhs = param_ids[param_index++];
-      ExprDoc annotation = d->Translate(var->ty).value();
-      d->RecordOrigin(annotation, var->ty);
+      // Reuse the captured scalar in dependent annotations instead of creating
+      // a new parameter identity after an earlier annotation has read it.
+      bool shared_symbol = signature_symbols.count(var.get());
+      ExprDoc annotation =
+          shared_symbol ? d->Translate(var).value() : 
d->Translate(var->ty).value();
+      d->RecordOrigin(annotation, shared_symbol ? ffi::ObjectRef(var) : 
ffi::ObjectRef(var->ty));
       AssignDoc argument(lhs, std::nullopt, annotation);
       d->RecordOrigin(argument, var);
       args.push_back(argument);
     }
 
     auto signature_candidates = CopyImplicitDefs(d);
+    for (const Var& var : func->params) signature_candidates.erase(var);
     std::unordered_map<const ffi::Object*, size_t> thread_counts;
     std::vector<tirx::IterVar> thread_vars;
     ffi::StructuralWalk<ffi::WalkOrder::kPreOrder>(

Reply via email to