diff --git a/mlir/lib/Dialect/StandardOps/IR/Ops.cpp b/mlir/lib/Dialect/StandardOps/IR/Ops.cpp
--- a/mlir/lib/Dialect/StandardOps/IR/Ops.cpp
+++ b/mlir/lib/Dialect/StandardOps/IR/Ops.cpp
@@ -758,7 +758,9 @@
 
   for (unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i)
     if (op.getOperand(i).getType() != fnType.getInput(i))
-      return op.emitOpError("operand type mismatch");
+      return op.emitOpError("operand type mismatch: expected operand type ")
+             << fnType.getInput(i) << ", but provided "
+             << op.getOperand(i).getType() << " for operand number " << i;
 
   if (fnType.getNumResults() != op.getNumResults())
     return op.emitOpError("incorrect number of results for callee");
diff --git a/mlir/test/IR/operand.mlir b/mlir/test/IR/operand.mlir
--- a/mlir/test/IR/operand.mlir
+++ b/mlir/test/IR/operand.mlir
@@ -33,3 +33,15 @@
   "test.mixed_normal_variadic_operand"(%arg0, %arg0, %arg0, %arg1, %arg0) : (tensor<f32>, tensor<f32>, tensor<f32>, f32, tensor<f32>) -> ()
   return
 }
+
+// -----
+
+func @testfunc(%arg0: i32) {
+  return
+}
+func @invalid_call_operandtype() {
+  %0 = constant 0.0 : f32
+  // expected-error @+1 {{operand type mismatch: expected operand type 'i32', but provided 'f32' for operand number 0}}
+  call @testfunc(%0) : (f32) -> ()
+  return
+}