[Mlir-commits] [mlir] [MLIR] Move SFINAE from return type to template argument in OpImplementation.h (NFC) (PR #188039)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Mar 23 06:31:22 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-core

@llvm/pr-subscribers-mlir

Author: Mehdi Amini (joker-eph)

<details>
<summary>Changes</summary>

Migrate all template methods that used `std::enable_if_t<cond, ReturnType>` return-type SFINAE to the `typename = std::enable_if_t<cond>` default template parameter style. This makes the actual return type visible at a glance and the constraint readable as part of the template signature.

Complementary overload pairs that require the `* = nullptr` non-type parameter trick to remain structurally distinct (parseCustomAttributeWithFallback, parseCustomTypeWithFallback) are left unchanged.

Addressing post-merge comment on #<!-- -->186192


Assisted-by: Claude Code

---
Full diff: https://github.com/llvm/llvm-project/pull/188039.diff


1 Files Affected:

- (modified) mlir/include/mlir/IR/OpImplementation.h (+67-64) 


``````````diff
diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h
index 59323bc350ce7..7f6b0a464f529 100644
--- a/mlir/include/mlir/IR/OpImplementation.h
+++ b/mlir/include/mlir/IR/OpImplementation.h
@@ -149,8 +149,9 @@ class AsmPrinter {
 
   /// Print the given integer value. This is useful to force a uint8_t/int8_t to
   /// be printed as an integer instead of a char.
-  template <typename IntT>
-  std::enable_if_t<std::is_integral_v<IntT>, void> printInteger(IntT value) {
+  template <typename IntT,
+            typename = std::enable_if_t<std::is_integral_v<IntT>>>
+  void printInteger(IntT value) {
     // Handle int8_t/uint8_t specially to avoid printing as char
     if constexpr (std::is_same_v<IntT, int8_t> ||
                   std::is_same_v<IntT, uint8_t>) {
@@ -350,39 +351,39 @@ class AsmPrinter {
   Impl *impl{nullptr};
 };
 
-template <typename AsmPrinterT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, Type type) {
+template <typename AsmPrinterT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, Type type) {
   p.printType(type);
   return p;
 }
 
-template <typename AsmPrinterT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, Attribute attr) {
+template <typename AsmPrinterT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, Attribute attr) {
   p.printAttribute(attr);
   return p;
 }
 
-template <typename AsmPrinterT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, const APFloat &value) {
+template <typename AsmPrinterT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, const APFloat &value) {
   p.printFloat(value);
   return p;
 }
-template <typename AsmPrinterT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, float value) {
+template <typename AsmPrinterT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, float value) {
   return p << APFloat(value);
 }
-template <typename AsmPrinterT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, double value) {
+template <typename AsmPrinterT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, double value) {
   return p << APFloat(value);
 }
 
@@ -396,33 +397,34 @@ template <typename AsmPrinterT, typename T,
                                !std::is_convertible<T &, ValueRange>::value &&
                                !std::is_convertible<T &, APFloat &>::value &&
                                !llvm::is_one_of<T, bool, float, double>::value,
-                           T> * = nullptr>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, const T &other) {
+                           T> * = nullptr,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, const T &other) {
   p.getStream() << other;
   return p;
 }
 
-template <typename AsmPrinterT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, bool value) {
+template <typename AsmPrinterT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, bool value) {
   return p << (value ? StringRef("true") : "false");
 }
 
-template <typename AsmPrinterT, typename ValueRangeT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, const ValueTypeRange<ValueRangeT> &types) {
+template <typename AsmPrinterT, typename ValueRangeT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p,
+                               const ValueTypeRange<ValueRangeT> &types) {
   llvm::interleaveComma(types, p);
   return p;
 }
 
-template <typename AsmPrinterT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, const TypeRange &types) {
+template <typename AsmPrinterT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, const TypeRange &types) {
   llvm::interleaveComma(types, p);
   return p;
 }
@@ -432,16 +434,16 @@ operator<<(AsmPrinterT &p, const TypeRange &types) {
 // ValueRange printing behaviour does not change from printing
 // the SSA values to printing the types for the operands when
 // using AsmPrinter instead of OpAsmPrinter.
-template <typename AsmPrinterT, typename T>
-inline std::enable_if_t<std::is_same<AsmPrinter, AsmPrinterT>::value &&
-                            std::is_convertible<T &, ValueRange>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, const T &other) = delete;
-
-template <typename AsmPrinterT, typename ElementT>
-inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
-                        AsmPrinterT &>
-operator<<(AsmPrinterT &p, ArrayRef<ElementT> types) {
+template <
+    typename AsmPrinterT, typename T,
+    typename = std::enable_if_t<std::is_same<AsmPrinter, AsmPrinterT>::value &&
+                                std::is_convertible<T &, ValueRange>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, const T &other) = delete;
+
+template <typename AsmPrinterT, typename ElementT,
+          typename =
+              std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value>>
+inline AsmPrinterT &operator<<(AsmPrinterT &p, ArrayRef<ElementT> types) {
   llvm::interleaveComma(types, p);
   return p;
 }
@@ -879,9 +881,9 @@ class AsmParser {
     /// Case that invokes the provided functor when true. The parameters passed
     /// to the functor are the keyword, and the location of the keyword (in case
     /// any errors need to be emitted).
-    template <typename FnT>
-    std::enable_if_t<!std::is_convertible<FnT, ResultT>::value, KeywordSwitch &>
-    Case(StringLiteral str, FnT &&fn) {
+    template <typename FnT, typename = std::enable_if_t<
+                                !std::is_convertible<FnT, ResultT>::value>>
+    KeywordSwitch &Case(StringLiteral str, FnT &&fn) {
       if (result)
         return *this;
 
@@ -892,9 +894,9 @@ class AsmParser {
         result.emplace(std::move(fn(keyword, loc)));
       return *this;
     }
-    template <typename FnT>
-    std::enable_if_t<!std::is_convertible<FnT, ResultT>::value, KeywordSwitch &>
-    Default(FnT &&fn) {
+    template <typename FnT, typename = std::enable_if_t<
+                                !std::is_convertible<FnT, ResultT>::value>>
+    KeywordSwitch &Default(FnT &&fn) {
       if (!result)
         result.emplace(fn(keyword, loc));
       return *this;
@@ -1146,11 +1148,11 @@ class AsmParser {
   /// handles concrete attribute types (e.g. FloatAttr) that are not covered by
   /// a dedicated virtual overload. It parses any attribute and then validates
   /// that the result is of the expected type, emitting an error if not.
-  template <typename AttrType>
-  std::enable_if_t<!llvm::is_one_of<AttrType, Attribute, ArrayAttr, StringAttr,
-                                    SymbolRefAttr>::value,
-                   OptionalParseResult>
-  parseOptionalAttribute(AttrType &result, Type type = {}) {
+  template <
+      typename AttrType,
+      typename = std::enable_if_t<!llvm::is_one_of<
+          AttrType, Attribute, ArrayAttr, StringAttr, SymbolRefAttr>::value>>
+  OptionalParseResult parseOptionalAttribute(AttrType &result, Type type = {}) {
     Attribute attr;
     OptionalParseResult parseResult = parseOptionalAttribute(attr, type);
     if (!parseResult.has_value() || failed(*parseResult))
@@ -1669,11 +1671,12 @@ class OpAsmParser : public AsmParser {
   /// Resolve a list of operands and a list of operand types to SSA values,
   /// emitting an error and returning failure, or appending the results
   /// to the list on success.
-  template <typename Operands = ArrayRef<UnresolvedOperand>,
-            typename Types = ArrayRef<Type>>
-  std::enable_if_t<!std::is_convertible<Types, Type>::value, ParseResult>
-  resolveOperands(Operands &&operands, Types &&types, SMLoc loc,
-                  SmallVectorImpl<Value> &result) {
+  template <
+      typename Operands = ArrayRef<UnresolvedOperand>,
+      typename Types = ArrayRef<Type>,
+      typename = std::enable_if_t<!std::is_convertible<Types, Type>::value>>
+  ParseResult resolveOperands(Operands &&operands, Types &&types, SMLoc loc,
+                              SmallVectorImpl<Value> &result) {
     size_t operandSize = llvm::range_size(operands);
     size_t typeSize = llvm::range_size(types);
     if (operandSize != typeSize) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/188039


More information about the Mlir-commits mailing list