The ValueRange printing behaviour of OpAsmPrinter and AsmPrinter is different, as reported here
static void testPrint(AsmPrinter &p, Operation *op, ValueRange operands) { p << '(' << operands << ')'; }
Although the base AsmPrinter is passed as the first parameter (and not OpAsmPrinter), the code compiles fine. However, instead of the SSA values, the types for the operands will be printed. This is a violation of the Liskov Substitution Principle.
The desired behaviour would be that the above code does not compile. The reason it compiles, is that for the above code, the TypeRange version will be selected for the << operator, since ValueRange is implicitly converted to TypeRange:
template <typename AsmPrinterT> inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value, AsmPrinterT &> operator<<(AsmPrinterT &p, const TypeRange &types) { llvm::interleaveComma(types, p); return p; }