This is an automated email from the ASF dual-hosted git repository.
tlopex 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 e49f50b00d [RELAX] Improve well-formed checker error messages with
function names (#18791)
e49f50b00d is described below
commit e49f50b00de00f22bc3084fec85d6481dd30aeeb
Author: Guan-Ming (Wesley) Chiu <[email protected]>
AuthorDate: Wed Feb 18 05:20:30 2026 +0800
[RELAX] Improve well-formed checker error messages with function names
(#18791)
## Why
Error messages for duplicate variables across functions lacked context
about which functions were involved, making debugging difficult.
## How
- Add a function name map to resolve FunctionNode* to global variable
names
- Include both conflicting function names in duplicate parameter and
symbolic var errors
Signed-off-by: Guan-Ming Chiu <[email protected]>
---
src/relax/analysis/well_formed.cc | 28 +++++++++++++++++++++-------
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/src/relax/analysis/well_formed.cc
b/src/relax/analysis/well_formed.cc
index 0cfc9efad8..f18143cdd2 100644
--- a/src/relax/analysis/well_formed.cc
+++ b/src/relax/analysis/well_formed.cc
@@ -73,6 +73,8 @@
#include <tvm/relax/utils.h>
#include <tvm/tir/expr_functor.h>
+#include <string>
+#include <unordered_map>
#include <unordered_set>
namespace tvm {
@@ -95,6 +97,7 @@ class WellFormedChecker : public relax::ExprVisitor,
// visit relax.Function
if (auto* n = it.second.as<FunctionNode>()) {
Function func = ffi::GetRef<Function>(n);
+ well_formed_checker.func_name_map_[n] = it.first->name_hint;
well_formed_checker.CheckGlobalVarAndGsymbolConsistency(it.first,
func);
well_formed_checker.VisitExpr(func);
}
@@ -134,6 +137,15 @@ class WellFormedChecker : public relax::ExprVisitor,
LOG(WARNING) << "This IR is not well formed: " << diag->message;
}
+ /*! \brief Get the name of a function for use in error messages. */
+ std::string FuncName(const FunctionNode* func) const {
+ auto it = func_name_map_.find(func);
+ if (it != func_name_map_.end()) {
+ return "\"" + it->second + "\"";
+ }
+ return "(anonymous function)";
+ }
+
void CheckGlobalVarAndGsymbolConsistency(GlobalVar var, Function func) {
// the uniqueness of all global vars are ensured by
IRModule->global_var_map_, so do not need
// to check again
@@ -256,11 +268,12 @@ class WellFormedChecker : public relax::ExprVisitor,
for (Var param : op->params) {
this->VisitVarDef(param);
- if (param_var_func_map_.count(param) == 1) {
- // TODO(relax-team): Complete this error info after we integrate
printer
+ auto it = param_var_func_map_.find(param);
+ if (it != param_var_func_map_.end()) {
Malformed(Diagnostic::Error(param->span)
- << "Relax variable " << param
- << " is repeatedly used as parameters in function.");
+ << "Relax variable " << param << " is used as a parameter in
both function "
+ << FuncName(it->second) << " and function " <<
FuncName(cur_visited_func_)
+ << ".");
}
param_var_func_map_.insert({param, cur_visited_func_});
}
@@ -551,10 +564,9 @@ class WellFormedChecker : public relax::ExprVisitor,
// check across functions presence
auto it = symbolic_var_func_map_.find(var);
if (it != symbolic_var_func_map_.end() && it->second != cur_visited_func_)
{
- // TODO(relax-team): Complete this error info after we integrate printer
Malformed(Diagnostic::Error(var->span)
- << "Symbolic Var " << var
- << " presents in different functions in the same Module.");
+ << "Symbolic Var " << var << " is present in both function "
<< FuncName(it->second)
+ << " and function " << FuncName(cur_visited_func_) << " in the
same Module.");
}
symbolic_var_func_map_.insert({var, cur_visited_func_});
}
@@ -632,6 +644,8 @@ class WellFormedChecker : public relax::ExprVisitor,
bool is_dataflow_;
// Current visited function.
const FunctionNode* cur_visited_func_;
+ // Map from function pointer to its global name (for error messages).
+ std::unordered_map<const FunctionNode*, std::string> func_name_map_;
// Current visit mode.
VisitMode mode_ = VisitMode::kDefault;
// set of context variables.