Revert "Fix #71 Do + DoAndReturn signature change error msg (#395)" (#413)

This reverts commit f9b4ad1fb635160fccabdd6afe566e4eee65bbb2.
diff --git a/gomock/call.go b/gomock/call.go
index 1a17798..7345f65 100644
--- a/gomock/call.go
+++ b/gomock/call.go
@@ -19,8 +19,6 @@
 	"reflect"
 	"strconv"
 	"strings"
-
-	"github.com/golang/mock/gomock/internal/validate"
 )
 
 // Call represents an expected call to a mock.
@@ -107,24 +105,10 @@
 // DoAndReturn declares the action to run when the call is matched.
 // The return values from this function are returned by the mocked function.
 // It takes an interface{} argument to support n-arity functions.
-// If the method signature of f is not compatible with the mocked function a
-// panic will be triggered. Both the arguments and return values of f are
-// validated.
 func (c *Call) DoAndReturn(f interface{}) *Call {
+	// TODO: Check arity and types here, rather than dying badly elsewhere.
 	v := reflect.ValueOf(f)
 
-	switch v.Kind() {
-	case reflect.Func:
-		mt := c.methodType
-
-		ft := v.Type()
-		if err := validate.InputAndOutputSig(ft, mt); err != nil {
-			panic(fmt.Sprintf("DoAndReturn: %s", err))
-		}
-	default:
-		panic("DoAndReturn: argument must be a function")
-	}
-
 	c.addAction(func(args []interface{}) []interface{} {
 		vargs := make([]reflect.Value, len(args))
 		ft := v.Type()
@@ -150,24 +134,10 @@
 // return values are ignored to retain backward compatibility. To use the
 // return values call DoAndReturn.
 // It takes an interface{} argument to support n-arity functions.
-// If the method signature of f is not compatible with the mocked function a
-// panic will be triggered. Only the arguments of f are validated; not the return
-// values.
 func (c *Call) Do(f interface{}) *Call {
+	// TODO: Check arity and types here, rather than dying badly elsewhere.
 	v := reflect.ValueOf(f)
 
-	switch v.Kind() {
-	case reflect.Func:
-		mt := c.methodType
-
-		ft := v.Type()
-		if err := validate.InputSig(ft, mt); err != nil {
-			panic(fmt.Sprintf("Do: %s", err))
-		}
-	default:
-		panic("Do: argument must be a function")
-	}
-
 	c.addAction(func(args []interface{}) []interface{} {
 		vargs := make([]reflect.Value, len(args))
 		ft := v.Type()
diff --git a/gomock/call_test.go b/gomock/call_test.go
index 7de3028..3a8315b 100644
--- a/gomock/call_test.go
+++ b/gomock/call_test.go
@@ -1,31 +1,9 @@
-// Copyright 2020 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
 package gomock
 
 import (
-	"fmt"
-	"reflect"
 	"testing"
 )
 
-type foo struct{}
-
-func (f foo) String() string {
-	return "meow"
-}
-
 type mockTestReporter struct {
 	errorCalls int
 	fatalCalls int
@@ -71,856 +49,3 @@
 		}
 	})
 }
-
-func TestCall_Do(t *testing.T) {
-	t.Run("Do function matches Call function", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function matches Call function and is a interface{}", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x interface{}) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function matches Call function and is a map[interface{}]interface{}", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x map[int]string) bool {
-			return true
-		}
-
-		callFunc := func(x map[interface{}]interface{}) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function matches Call function and is variadic", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x []int) bool {
-			return true
-		}
-
-		callFunc := func(x ...int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function matches Call function and is variadic interface{}", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x []int) bool {
-			return true
-		}
-
-		callFunc := func(x ...interface{}) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function matches Call function and is a non-empty interface", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x foo) bool {
-			return true
-		}
-
-		callFunc := func(x fmt.Stringer) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("argument to Do is not a function", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		callFunc := func(x int, y int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected Do to panic")
-			}
-		}()
-
-		c.Do("meow")
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("number of args for Do func don't match Call func", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x int, y int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected Do to panic")
-			}
-		}()
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("arg types for Do func don't match Call func", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x string) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected Do to panic")
-			}
-		}()
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function does not match Call function: want byte slice, got string", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x string) bool {
-			return true
-		}
-
-		callFunc := func(x []byte) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected Do to panic")
-			}
-		}()
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function does not match Call function and is a slice", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x []string) bool {
-			return true
-		}
-
-		callFunc := func(x []int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected Do to panic")
-			}
-		}()
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function does not match Call function and is a slice interface{}", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x []string) bool {
-			return true
-		}
-
-		callFunc := func(x []interface{}) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected Do to panic")
-			}
-		}()
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function does not match Call function and is a composite struct", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x b) bool {
-			return true
-		}
-
-		callFunc := func(x a) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected Do to panic")
-			}
-		}()
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("Do function does not match Call function and is a map", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x map[int]string) bool {
-			return true
-		}
-
-		callFunc := func(x map[interface{}]int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected Do to panic")
-			}
-		}()
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("number of return vals for Do func don't match Call func", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x int) (bool, error) {
-			return false, nil
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("return types for Do func don't match Call func", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x int) error {
-			return nil
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.Do(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-}
-
-func TestCall_DoAndReturn(t *testing.T) {
-	t.Run("DoAndReturn function matches Call function", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("DoAndReturn function matches Call function and is a interface{}", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x interface{}) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("DoAndReturn function matches Call function and is a map[interface{}]interface{}", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x map[int]string) bool {
-			return true
-		}
-
-		callFunc := func(x map[interface{}]interface{}) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("DoAndReturn function matches Call function and is variadic", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x []int) bool {
-			return true
-		}
-
-		callFunc := func(x ...int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("DoAndReturn function matches Call function and is variadic interface{}", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x []int) bool {
-			return true
-		}
-
-		callFunc := func(x ...interface{}) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("argument to DoAndReturn is not a function", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		callFunc := func(x int, y int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn("meow")
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("number of args for DoAndReturn func don't match Call func", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x int, y int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("arg types for DoAndReturn func don't match Call func", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x string) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("DoAndReturn function does not match Call function and is a slice", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x []string) bool {
-			return true
-		}
-
-		callFunc := func(x []int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("DoAndReturn function does not match Call function and is a slice interface{}", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x []string) bool {
-			return true
-		}
-
-		callFunc := func(x []interface{}) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("DoAndReturn function does not match Call function and is a composite struct", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x b) bool {
-			return true
-		}
-
-		callFunc := func(x a) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("DoAndReturn function does not match Call function and is a map", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x map[int]string) bool {
-			return true
-		}
-
-		callFunc := func(x map[interface{}]int) bool {
-			return false
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("number of return vals for DoAndReturn func don't match Call func", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x int) (bool, error) {
-			return false, nil
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-
-	t.Run("return types for DoAndReturn func don't match Call func", func(t *testing.T) {
-		tr := &mockTestReporter{}
-
-		doFunc := func(x int) bool {
-			if x < 20 {
-				return false
-			}
-
-			return true
-		}
-
-		callFunc := func(x int) error {
-			return nil
-		}
-
-		c := &Call{
-			t:          tr,
-			methodType: reflect.TypeOf(callFunc),
-		}
-
-		defer func() {
-			if r := recover(); r == nil {
-				t.Error("expected DoAndReturn to panic")
-			}
-		}()
-
-		c.DoAndReturn(doFunc)
-
-		if len(c.actions) != 1 {
-			t.Errorf("expected %d actions but got %d", 1, len(c.actions))
-		}
-	})
-}
-
-type a struct {
-	name string
-}
-
-func (testObj a) Name() string {
-	return testObj.name
-}
-
-type b struct {
-	a
-	foo string
-}
-
-func (testObj b) Foo() string {
-	return testObj.foo
-}
diff --git a/gomock/controller_test.go b/gomock/controller_test.go
index 1f6b09d..c22908b 100644
--- a/gomock/controller_test.go
+++ b/gomock/controller_test.go
@@ -492,11 +492,9 @@
 	doCalled := false
 	var argument string
 	ctrl.RecordCall(subject, "FooMethod", "argument").Do(
-		func(arg string) int {
+		func(arg string) {
 			doCalled = true
 			argument = arg
-
-			return 0
 		})
 	if doCalled {
 		t.Error("Do() callback called too early.")
diff --git a/gomock/internal/validate/validate.go b/gomock/internal/validate/validate.go
deleted file mode 100644
index 5ef253a..0000000
--- a/gomock/internal/validate/validate.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2020 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package validate
-
-import (
-	"fmt"
-	"reflect"
-)
-
-// InputAndOutputSig compares the argument and return signatures of actualFunc
-// against expectedFunc. It returns an error unless everything matches.
-func InputAndOutputSig(actualFunc, expectedFunc reflect.Type) error {
-	if err := InputSig(actualFunc, expectedFunc); err != nil {
-		return err
-	}
-
-	if err := outputSig(actualFunc, expectedFunc); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-// InputSig compares the argument signatures of actualFunc
-// against expectedFunc. It returns an error unless everything matches.
-func InputSig(actualFunc, expectedFunc reflect.Type) error {
-	// check number of arguments and type of each argument
-	if actualFunc.NumIn() != expectedFunc.NumIn() {
-		return fmt.Errorf(
-			"expected function to have %d arguments not %d",
-			expectedFunc.NumIn(), actualFunc.NumIn())
-	}
-
-	lastIdx := expectedFunc.NumIn()
-
-	// If the function has a variadic argument validate that one first so that
-	// we aren't checking for it while we iterate over the other args
-	if expectedFunc.IsVariadic() {
-		if ok := variadicArg(lastIdx, actualFunc, expectedFunc); !ok {
-			i := lastIdx - 1
-			return fmt.Errorf(
-				"expected function to have"+
-					" arg of type %v at position %d"+
-					" not type %v",
-				expectedFunc.In(i), i, actualFunc.In(i),
-			)
-		}
-
-		lastIdx--
-	}
-
-	for i := 0; i < lastIdx; i++ {
-		expectedArg := expectedFunc.In(i)
-		actualArg := actualFunc.In(i)
-
-		if err := arg(actualArg, expectedArg); err != nil {
-			return fmt.Errorf("input argument at %d: %s", i, err)
-		}
-	}
-
-	return nil
-}
-
-func outputSig(actualFunc, expectedFunc reflect.Type) error {
-	// check number of return vals and type of each val
-	if actualFunc.NumOut() != expectedFunc.NumOut() {
-		return fmt.Errorf(
-			"expected function to have %d return vals not %d",
-			expectedFunc.NumOut(), actualFunc.NumOut())
-	}
-
-	for i := 0; i < expectedFunc.NumOut(); i++ {
-		expectedArg := expectedFunc.Out(i)
-		actualArg := actualFunc.Out(i)
-
-		if err := arg(actualArg, expectedArg); err != nil {
-			return fmt.Errorf("return argument at %d: %s", i, err)
-		}
-	}
-
-	return nil
-}
-
-func variadicArg(lastIdx int, actualFunc, expectedFunc reflect.Type) bool {
-	if actualFunc.In(lastIdx-1) != expectedFunc.In(lastIdx-1) {
-		if actualFunc.In(lastIdx-1).Kind() != reflect.Slice {
-			return false
-		}
-
-		expectedArgT := expectedFunc.In(lastIdx - 1)
-		expectedElem := expectedArgT.Elem()
-		if expectedElem.Kind() != reflect.Interface {
-			return false
-		}
-
-		actualArgT := actualFunc.In(lastIdx - 1)
-		actualElem := actualArgT.Elem()
-
-		if ok := actualElem.ConvertibleTo(expectedElem); !ok {
-			return false
-		}
-
-	}
-
-	return true
-}
-
-func interfaceArg(actualArg, expectedArg reflect.Type) error {
-	if !actualArg.ConvertibleTo(expectedArg) {
-		return fmt.Errorf(
-			"expected arg convertible to type %v not type %v",
-			expectedArg, actualArg,
-		)
-	}
-
-	return nil
-}
-
-func mapArg(actualArg, expectedArg reflect.Type) error {
-	expectedKey := expectedArg.Key()
-	actualKey := actualArg.Key()
-
-	switch expectedKey.Kind() {
-	case reflect.Interface:
-		if err := interfaceArg(actualKey, expectedKey); err != nil {
-			return fmt.Errorf("map key: %s", err)
-		}
-	default:
-		if actualKey != expectedKey {
-			return fmt.Errorf("expected map key of type %v not type %v",
-				expectedKey, actualKey)
-		}
-	}
-
-	expectedElem := expectedArg.Elem()
-	actualElem := actualArg.Elem()
-
-	switch expectedElem.Kind() {
-	case reflect.Interface:
-		if err := interfaceArg(actualElem, expectedElem); err != nil {
-			return fmt.Errorf("map element: %s", err)
-		}
-	default:
-		if actualElem != expectedElem {
-			return fmt.Errorf("expected map element of type %v not type %v",
-				expectedElem, actualElem)
-		}
-	}
-
-	return nil
-}
-
-func arg(actualArg, expectedArg reflect.Type) error {
-	switch expectedArg.Kind() {
-	// If the expected arg is an interface we only care if the actual arg is convertible
-	// to that interface
-	case reflect.Interface:
-		if err := interfaceArg(actualArg, expectedArg); err != nil {
-			return err
-		}
-	default:
-		// If the expected arg is not an interface then first check to see if
-		// the actual arg is even the same reflect.Kind
-		if expectedArg.Kind() != actualArg.Kind() {
-			return fmt.Errorf("expected arg of kind %v not %v",
-				expectedArg.Kind(), actualArg.Kind())
-		}
-
-		switch expectedArg.Kind() {
-		// If the expected arg is a map then we need to handle the case where
-		// the map key or element type is an interface
-		case reflect.Map:
-			if err := mapArg(actualArg, expectedArg); err != nil {
-				return err
-			}
-		default:
-			if actualArg != expectedArg {
-				return fmt.Errorf(
-					"Expected arg of type %v not type %v",
-					expectedArg, actualArg,
-				)
-			}
-		}
-	}
-
-	return nil
-}