[Mlir-commits] [mlir] [mlir][tblgen] Error on unsubstituted $_self in op trait predicates (PR #227263)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat Oct 31 02:43:49 PDT 2026


https://github.com/LiRvs-Miria updated https://github.com/llvm/llvm-project/pull/227263

>From bd00c2fafc28b1afe79d92f270158ff737a8b69e Mon Sep 17 00:00:00 2001
From: LiRvs-Miria <1753531985 at qq.com>
Date: Tue, 29 Sep 2026 18:22:59 +0800
Subject: [PATCH] [mlir][tblgen] Error on unsubstituted $_self in op trait
 predicates

PredOpTrait predicates are expanded against the whole operation, so
$_self is not bound in that context. If an ODS definition uses $_self
in a trait predicate, tblgen silently emits C++ containing
$_self<no-subst-found>, which later fails to compile with a confusing
error pointing into the generated .inc file.

Detect the unsubstituted placeholder while formatting the predicate and
report a fatal error at the ODS definition site instead, naming the
operation and the trait, and pointing to the two remedies: use $_op to
refer to the operation, or pre-substitute $_self with !subst as the
AllTypesMatch / TypesMatchWith primitives do.

A new ERROR18 case in op-error.td covers the diagnostic; the check runs
while generating the op definitions (-gen-op-defs).
---
 mlir/test/mlir-tblgen/op-error.td           | 14 ++++++++++++++
 mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp | 14 ++++++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/mlir/test/mlir-tblgen/op-error.td b/mlir/test/mlir-tblgen/op-error.td
index ec90891034fbef..1337e793dd15a2 100644
--- a/mlir/test/mlir-tblgen/op-error.td
+++ b/mlir/test/mlir-tblgen/op-error.td
@@ -15,6 +15,8 @@
 // RUN: not mlir-tblgen -gen-op-decls -I %S/../../include -DERROR15 %s 2>&1 | FileCheck --check-prefix=ERROR15 %s
 // RUN: not mlir-tblgen -gen-op-decls -I %S/../../include -DERROR16 %s 2>&1 | FileCheck --check-prefix=ERROR16 %s
 // RUN: not mlir-tblgen -gen-op-decls -I %S/../../include -DERROR17 %s 2>&1 | FileCheck --check-prefix=ERROR17 %s
+// This error is caught while generating the op verifier.
+// RUN: not mlir-tblgen -gen-op-defs -I %S/../../include -DERROR18 %s 2>&1 | FileCheck --check-prefix=ERROR18 %s
 
 include "mlir/IR/OpBase.td"
 
@@ -166,3 +168,15 @@ def OpWithLegacyResultSegmentProperty
   let results = (outs Variadic<AnyType>:$lhs, Variadic<AnyType>:$rhs);
 }
 #endif
+
+#ifdef ERROR18
+// ERROR18: error: trait 'lhs and rhs must have the same type' on operation 'test_dialect.unsubstituted_self' uses $_self in its predicate, but $_self is not bound in trait context
+def UnsubstitutedSelfOp
+    : Op<Test_Dialect, "unsubstituted_self",
+        [PredOpTrait<"lhs and rhs must have the same type",
+                CPred<"$_self.getType() == $_op.getOperand(0).getType()">
+              >
+        ]> {
+  let arguments = (ins AnyType:$a, AnyType:$b);
+}
+#endif
diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
index 48158b6b148aab..d1f9a4f5d8a818 100644
--- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp
@@ -3764,10 +3764,20 @@ void OpEmitter::genVerifier() {
 
   for (auto &trait : op.getTraits()) {
     if (auto *t = dyn_cast<tblgen::PredTrait>(&trait)) {
+      // Trait predicates expand against the whole operation, so $_self is not
+      // substituted here; catch it and report at the ODS level instead
+      std::string pred = tgfmt(t->getPredTemplate(), &verifyCtx);
+      if (StringRef(pred).contains("<no-subst-found>"))
+        PrintFatalError(op.getLoc(),
+                        "trait '" + t->getSummary() + "' on operation '" +
+                            op.getOperationName() +
+                            "' uses $_self in its predicate, but $_self is "
+                            "not bound in trait context; use $_op to refer "
+                            "to the operation, or pre-substitute $_self with "
+                            "!subst");
       implBody << tgfmt("  if (!($0))\n    "
                         "return emitOpError(\"failed to verify that $1\");\n",
-                        &verifyCtx, tgfmt(t->getPredTemplate(), &verifyCtx),
-                        t->getSummary());
+                        &verifyCtx, pred, t->getSummary());
     }
   }
 



More information about the Mlir-commits mailing list