This is an automated email from the ASF dual-hosted git repository.

altay pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 83fe192  [BEAM-6825] Improve Combine error messages. (#8243)
83fe192 is described below

commit 83fe192b9f58a0c99d5718a5dea087d438fa5d7c
Author: Robert Burke <[email protected]>
AuthorDate: Tue Apr 9 09:40:48 2019 -0700

    [BEAM-6825] Improve Combine error messages. (#8243)
    
    * [BEAM-6825] Improve Combine error messages.
    
    * !fixup Address style nits, and error readability.
---
 sdks/go/pkg/beam/core/funcx/signature.go         |  46 +++-
 sdks/go/pkg/beam/core/funcx/signature_test.go    |  16 +-
 sdks/go/pkg/beam/core/graph/fn.go                | 135 +++++++++-
 sdks/go/pkg/beam/core/graph/fn_test.go           | 311 +++++++++++++++++++++++
 sdks/go/pkg/beam/transforms/stats/mean.go        |   9 +-
 sdks/go/pkg/beam/transforms/stats/stats.shims.go | 189 +++++++-------
 6 files changed, 582 insertions(+), 124 deletions(-)

diff --git a/sdks/go/pkg/beam/core/funcx/signature.go 
b/sdks/go/pkg/beam/core/funcx/signature.go
index fbb0ad6..6caa5cd 100644
--- a/sdks/go/pkg/beam/core/funcx/signature.go
+++ b/sdks/go/pkg/beam/core/funcx/signature.go
@@ -108,23 +108,32 @@ func replace(list []reflect.Type, old, new reflect.Type) 
[]reflect.Type {
 // "foo" would satisfy (context.Context, string) -> bool and only "bar" would
 // satisfy (int) -> bool.
 func Satisfy(fn interface{}, sig *Signature) error {
-       value := reflect.ValueOf(fn)
-       if value.Kind() != reflect.Func {
-               return fmt.Errorf("not a function: %v", value)
-       }
-
        var in, out []reflect.Type
-       for i := 0; i < value.Type().NumIn(); i++ {
-               in = append(in, value.Type().In(i))
+       var typ reflect.Type
+       switch fx := fn.(type) {
+       case *Fn:
+               typ = fx.Fn.Type()
+       case reflectx.Func:
+               typ = fx.Type()
+       default:
+               value := reflect.ValueOf(fn)
+               if value.Kind() != reflect.Func {
+                       return fmt.Errorf("not a function: %v", value)
+               }
+               typ = value.Type()
+       }
+       for i := 0; i < typ.NumIn(); i++ {
+               in = append(in, typ.In(i))
        }
-       for i := 0; i < value.Type().NumOut(); i++ {
-               out = append(out, value.Type().Out(i))
+       for i := 0; i < typ.NumOut(); i++ {
+               out = append(out, typ.Out(i))
        }
        if len(in) < len(sig.Args) || len(out) < len(sig.Return) {
-               return fmt.Errorf("not enough required parameters: %v", value)
+               return fmt.Errorf("not enough required parameters: %v", typ)
        }
+
        if len(in) > len(sig.Args)+len(sig.OptArgs) || len(out) > 
len(sig.Return)+len(sig.OptReturn) {
-               return fmt.Errorf("too many parameters: %v", value)
+               return fmt.Errorf("too many parameters: %v", typ)
        }
 
        // (1) Create generic binding. If inconsistent, reject fn. We do not 
allow
@@ -144,10 +153,10 @@ func Satisfy(fn interface{}, sig *Signature) error {
        if err := matchReq(in[off:], sig.Args); err != nil {
                return err
        }
-       if err := matchReq(out[:len(sig.Return)], sig.Return); err != nil {
+       if err := matchOpt(in[:off], sig.OptArgs, m); err != nil {
                return err
        }
-       if err := matchOpt(in[:off], sig.OptArgs, m); err != nil {
+       if err := matchReq(out[:len(sig.Return)], sig.Return); err != nil {
                return err
        }
        return matchOpt(out[len(sig.Return):], sig.OptReturn, m)
@@ -179,12 +188,21 @@ func matchReq(list, models []reflect.Type) error {
                        continue
                }
                if model != t {
-                       return fmt.Errorf("type mismatch: %v, want %v", t, 
model)
+                       return &TypeMismatchError{Got: t, Want: model}
                }
        }
        return nil
 }
 
+// TypeMismatchError indicates we didn't get the type we expected.
+type TypeMismatchError struct {
+       Got, Want reflect.Type
+}
+
+func (e *TypeMismatchError) Error() string {
+       return fmt.Sprintf("type mismatch: got %v, want %v", e.Got, e.Want)
+}
+
 func matchOpt(list, models []reflect.Type, m map[string]reflect.Type) error {
        i := 0
        for _, t := range list {
diff --git a/sdks/go/pkg/beam/core/funcx/signature_test.go 
b/sdks/go/pkg/beam/core/funcx/signature_test.go
index fecf3c4..ce40ad1 100644
--- a/sdks/go/pkg/beam/core/funcx/signature_test.go
+++ b/sdks/go/pkg/beam/core/funcx/signature_test.go
@@ -206,7 +206,21 @@ func TestSatisfy(t *testing.T) {
 
        for _, test := range tests {
                if err := Satisfy(test.Fn, test.Sig); (err == nil) != test.Ok {
-                       t.Errorf("Satisfy(%v, %v) = %v, want (err==nil)==%v", 
reflect.ValueOf(test.Fn).Type(), test.Sig, err, test.Ok)
+                       t.Errorf("iface: Satisfy(%v, %v) = %v, want 
(err==nil)==%v", reflect.ValueOf(test.Fn).Type(), test.Sig, err, test.Ok)
+               }
+
+               rfn := reflectx.MakeFunc(test.Fn)
+               if err := Satisfy(rfn, test.Sig); (err == nil) != test.Ok {
+                       t.Errorf("reflectx.Func: Satisfy(%v, %v) = %v, want 
(err==nil)==%v", reflect.ValueOf(test.Fn).Type(), test.Sig, err, test.Ok)
+               }
+
+               fx, err := New(rfn)
+               if err != nil {
+                       t.Errorf("Unable to create New Fn from reflectx.Func 
%v: %v", rfn.Name(), err)
+                       continue
+               }
+               if err := Satisfy(fx, test.Sig); (err == nil) != test.Ok {
+                       t.Errorf("*funcx.Fn:Satisfy(%v, %v) = %v, want 
(err==nil)==%v", reflect.ValueOf(test.Fn).Type(), test.Sig, err, test.Ok)
                }
        }
 }
diff --git a/sdks/go/pkg/beam/core/graph/fn.go 
b/sdks/go/pkg/beam/core/graph/fn.go
index 29c92f8..cc18d30 100644
--- a/sdks/go/pkg/beam/core/graph/fn.go
+++ b/sdks/go/pkg/beam/core/graph/fn.go
@@ -20,6 +20,7 @@ import (
        "reflect"
 
        "github.com/apache/beam/sdks/go/pkg/beam/core/funcx"
+       "github.com/apache/beam/sdks/go/pkg/beam/core/typex"
        "github.com/apache/beam/sdks/go/pkg/beam/core/util/reflectx"
 )
 
@@ -213,12 +214,12 @@ func AsDoFn(fn *Fn) (*DoFn, error) {
        if fn.Fn != nil {
                fn.methods[processElementName] = fn.Fn
        }
-       if err := verifyValidNames(fn, setupName, startBundleName, 
processElementName, finishBundleName, teardownName); err != nil {
+       if err := verifyValidNames("graph.AsDoFn", fn, setupName, 
startBundleName, processElementName, finishBundleName, teardownName); err != 
nil {
                return nil, err
        }
 
        if _, ok := fn.methods[processElementName]; !ok {
-               return nil, fmt.Errorf("failed to find %v method: %v", 
processElementName, fn)
+               return nil, fmt.Errorf("graph.AsDoFn: failed to find %v method: 
%v", processElementName, fn)
        }
 
        // TODO(herohde) 5/18/2017: validate the signatures, incl. consistency.
@@ -281,26 +282,75 @@ func NewCombineFn(fn interface{}) (*CombineFn, error) {
 
 // AsCombineFn converts a Fn to a CombineFn, if possible.
 func AsCombineFn(fn *Fn) (*CombineFn, error) {
+       const fnKind = "graph.AsCombineFn"
        if fn.methods == nil {
                fn.methods = make(map[string]*funcx.Fn)
        }
        if fn.Fn != nil {
                fn.methods[mergeAccumulatorsName] = fn.Fn
        }
-       if err := verifyValidNames(fn, setupName, createAccumulatorName, 
addInputName, mergeAccumulatorsName, extractOutputName, compactName, 
teardownName); err != nil {
+       if err := verifyValidNames(fnKind, fn, setupName, 
createAccumulatorName, addInputName, mergeAccumulatorsName, extractOutputName, 
compactName, teardownName); err != nil {
                return nil, err
        }
 
-       if _, ok := fn.methods[mergeAccumulatorsName]; !ok {
-               return nil, fmt.Errorf("failed to find %v method: %v", 
mergeAccumulatorsName, fn)
+       mergeFn, ok := fn.methods[mergeAccumulatorsName]
+       if !ok {
+               return nil, fmt.Errorf("%v: failed to find required %v method 
on type: %v", fnKind, mergeAccumulatorsName, fn.Name())
        }
 
-       // TODO(herohde) 5/24/2017: validate the signatures, incl. consistency.
+       // CombineFn methods must satisfy the following:
+       // CreateAccumulator func() (A, error?)
+       // AddInput func(A, I) (A, error?)
+       // MergeAccumulators func(A, A) (A, error?)
+       // ExtractOutput func(A) (O, error?)
+       // This means that the other signatures *must* match the type used in 
MergeAccumulators.
+       if len(mergeFn.Ret) <= 0 {
+               return nil, fmt.Errorf("%v: %v requires at least 1 return 
value. : %v", fnKind, mergeAccumulatorsName, mergeFn)
+       }
+       accumType := mergeFn.Ret[0].T
+
+       for _, mthd := range []struct {
+               name    string
+               sigFunc func(fx *funcx.Fn, accumType reflect.Type) 
*funcx.Signature
+       }{
+               {mergeAccumulatorsName, func(fx *funcx.Fn, accumType 
reflect.Type) *funcx.Signature {
+                       return funcx.Replace(mergeAccumulatorsSig, typex.TType, 
accumType)
+               }},
+               {createAccumulatorName, func(fx *funcx.Fn, accumType 
reflect.Type) *funcx.Signature {
+                       return funcx.Replace(createAccumulatorSig, typex.TType, 
accumType)
+               }},
+               {addInputName, func(fx *funcx.Fn, accumType reflect.Type) 
*funcx.Signature {
+                       // AddInput needs the last parameter type substituted.
+                       p := fx.Param[len(fx.Param)-1]
+                       aiSig := funcx.Replace(addInputSig, typex.TType, 
accumType)
+                       return funcx.Replace(aiSig, typex.VType, p.T)
+               }},
+               {extractOutputName, func(fx *funcx.Fn, accumType reflect.Type) 
*funcx.Signature {
+                       // ExtractOutput needs the first Return type 
substituted.
+                       r := fx.Ret[0]
+                       eoSig := funcx.Replace(extractOutputSig, typex.TType, 
accumType)
+                       return funcx.Replace(eoSig, typex.WType, r.T)
+               }},
+       } {
+               if err := validateSignature(fnKind, mthd.name, fn, accumType, 
mthd.sigFunc); err != nil {
+                       return nil, err
+               }
+       }
 
        return (*CombineFn)(fn), nil
 }
 
-func verifyValidNames(fn *Fn, names ...string) error {
+func validateSignature(fnKind, methodName string, fn *Fn, accumType 
reflect.Type, sigFunc func(*funcx.Fn, reflect.Type) *funcx.Signature) error {
+       if fx, ok := fn.methods[methodName]; ok {
+               sig := sigFunc(fx, accumType)
+               if err := funcx.Satisfy(fx, sig); err != nil {
+                       return &verifyMethodError{fnKind, methodName, err, fn, 
accumType, sig}
+               }
+       }
+       return nil
+}
+
+func verifyValidNames(fnKind string, fn *Fn, names ...string) error {
        m := make(map[string]bool)
        for _, name := range names {
                m[name] = true
@@ -308,8 +358,77 @@ func verifyValidNames(fn *Fn, names ...string) error {
 
        for key := range fn.methods {
                if !m[key] {
-                       return fmt.Errorf("unexpected method %v present. Valid 
methods are: %v", key, names)
+                       return fmt.Errorf("%s: unexpected exported method %v 
present. Valid methods are: %v", fnKind, key, names)
                }
        }
        return nil
 }
+
+type verifyMethodError struct {
+       // Context for the error.
+       fnKind, methodName string
+       // The triggering error.
+       err error
+
+       fn        *Fn
+       accumType reflect.Type
+       sig       *funcx.Signature
+}
+
+func (e *verifyMethodError) Error() string {
+       name := e.fn.methods[e.methodName].Fn.Name()
+       if e.fn.Fn == nil {
+               // Methods might be hidden behind reflect.methodValueCall, 
which is
+               // not useful to the end user.
+               name = fmt.Sprintf("%s.%s", e.fn.Name(), e.methodName)
+       }
+       typ := e.fn.methods[e.methodName].Fn.Type()
+       switch e.methodName {
+       case mergeAccumulatorsName:
+               // Provide a clearer error for MergeAccumulators, since it's 
the root method
+               // for CombineFns.
+               // The root error doesn't matter here since we can't be certain 
what the accumulator
+               // type is before mergeAccumulators is verified.
+               return fmt.Sprintf("%v: %s must be a binary merge of 
accumulators to be a CombineFn. "+
+                       "It is of type \"%v\", but it must be of type 
func(context.Context?, A, A) (A, error?) "+
+                       "where A is the accumulator type",
+                       e.fnKind, name, typ)
+       case createAccumulatorName, addInputName, extractOutputName:
+               // Commonly the accumulator type won't match.
+               if err, ok := e.err.(*funcx.TypeMismatchError); ok && err.Want 
== e.accumType {
+                       return fmt.Sprintf("%s invalid %v: %s has type \"%v\", 
but expected \"%v\" "+
+                               "to be the accumulator type \"%v\"; expected a 
signature like %v",
+                               e.fnKind, e.methodName, name, typ, err.Got, 
e.accumType, e.sig)
+               }
+       }
+       return fmt.Sprintf("%s invalid %v %v: got type %v but "+
+               "expected a signature like %v; original error: %v",
+               e.fnKind, e.methodName, name, typ, e.sig, e.err)
+}
+
+var (
+       mergeAccumulatorsSig = &funcx.Signature{
+               OptArgs:   []reflect.Type{reflectx.Context},
+               Args:      []reflect.Type{typex.TType, typex.TType},
+               Return:    []reflect.Type{typex.TType},
+               OptReturn: []reflect.Type{reflectx.Error},
+       }
+       createAccumulatorSig = &funcx.Signature{
+               OptArgs:   []reflect.Type{reflectx.Context},
+               Args:      []reflect.Type{},
+               Return:    []reflect.Type{typex.TType},
+               OptReturn: []reflect.Type{reflectx.Error},
+       }
+       addInputSig = &funcx.Signature{
+               OptArgs:   []reflect.Type{reflectx.Context},
+               Args:      []reflect.Type{typex.TType, typex.VType},
+               Return:    []reflect.Type{typex.TType},
+               OptReturn: []reflect.Type{reflectx.Error},
+       }
+       extractOutputSig = &funcx.Signature{
+               OptArgs:   []reflect.Type{reflectx.Context},
+               Args:      []reflect.Type{typex.TType},
+               Return:    []reflect.Type{typex.WType},
+               OptReturn: []reflect.Type{reflectx.Error},
+       }
+)
diff --git a/sdks/go/pkg/beam/core/graph/fn_test.go 
b/sdks/go/pkg/beam/core/graph/fn_test.go
new file mode 100644
index 0000000..d6b8a67
--- /dev/null
+++ b/sdks/go/pkg/beam/core/graph/fn_test.go
@@ -0,0 +1,311 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You 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 graph
+
+import (
+       "context"
+       "reflect"
+       "testing"
+)
+
+func TestNewCombineFn(t *testing.T) {
+       t.Run("valid", func(t *testing.T) {
+               tests := []struct {
+                       cfn interface{}
+               }{
+                       {cfn: func(int, int) int { return 0 }},
+                       {cfn: func(string, string) string { return "" }},
+                       {cfn: func(MyAccum, MyAccum) MyAccum { return MyAccum{} 
}},
+                       {cfn: func(MyAccum, MyAccum) (MyAccum, error) { return 
MyAccum{}, nil }},
+                       {cfn: func(context.Context, MyAccum, MyAccum) MyAccum { 
return MyAccum{} }},
+                       {cfn: func(context.Context, MyAccum, MyAccum) (MyAccum, 
error) { return MyAccum{}, nil }},
+                       {cfn: &GoodCombineFn{}},
+                       {cfn: &GoodWErrorCombineFn{}},
+                       {cfn: &GoodWContextCombineFn{}},
+                       {cfn: &GoodCombineFnUnexportedExtraMethod{}},
+               }
+
+               for _, test := range tests {
+                       t.Run(reflect.TypeOf(test.cfn).String(), func(t 
*testing.T) {
+                               if _, err := NewCombineFn(test.cfn); err != nil 
{
+                                       t.Fatalf("NewCombineFn failed: %v", err)
+                               }
+                       })
+               }
+       })
+       t.Run("invalid", func(t *testing.T) {
+               tests := []struct {
+                       cfn interface{}
+               }{
+                       // Validate MergeAccumulator errors
+                       {cfn: func() int { return 0 }},
+                       {cfn: func(int, int) {}},
+                       {cfn: func(int, int) string { return "" }},
+                       {cfn: func(string, string) int { return 0 }},
+                       {cfn: func(int, string) int { return 0 }},
+                       {cfn: func(string, int) int { return 0 }},
+                       {cfn: func(string, int) (int, error) { return 0, nil }},
+                       {cfn: &BadCombineFnNoMergeAccumulators{}},
+                       {cfn: &BadCombineFnNonBinaryMergeAccumulators{}},
+                       // Validate accumulator type mismatches
+                       {cfn: &BadCombineFnMisMatchedCreateAccumulator{}},
+                       {cfn: &BadCombineFnMisMatchedAddInputIn{}},
+                       {cfn: &BadCombineFnMisMatchedAddInputOut{}},
+                       {cfn: &BadCombineFnMisMatchedAddInputBoth{}},
+                       {cfn: &BadCombineFnMisMatchedExtractOutput{}},
+                       // Validate signatures
+                       {cfn: &BadCombineFnInvalidCreateAccumulator1{}},
+                       {cfn: &BadCombineFnInvalidCreateAccumulator2{}},
+                       {cfn: &BadCombineFnInvalidCreateAccumulator3{}},
+                       {cfn: &BadCombineFnInvalidCreateAccumulator4{}},
+                       {cfn: &BadCombineFnInvalidAddInput1{}},
+                       {cfn: &BadCombineFnInvalidAddInput2{}},
+                       {cfn: &BadCombineFnInvalidAddInput3{}},
+                       {cfn: &BadCombineFnInvalidAddInput4{}},
+                       {cfn: &BadCombineFnInvalidExtractOutput1{}},
+                       {cfn: &BadCombineFnInvalidExtractOutput2{}},
+                       {cfn: &BadCombineFnInvalidExtractOutput3{}},
+                       {cfn: &BadCombineFnExtraExportedMethod{}},
+               }
+               for _, test := range tests {
+                       t.Run(reflect.TypeOf(test.cfn).String(), func(t 
*testing.T) {
+                               if cfn, err := NewCombineFn(test.cfn); err != 
nil {
+                                       // Note to Developer: To work on 
improving the error messages, use t.Errorf instead!
+                                       t.Logf("NewCombineFn failed as 
expected:\n%v", err)
+                               } else {
+                                       t.Errorf("AsCombineFn(%v) = %v, want 
failure", cfn.Name(), cfn)
+                               }
+                       })
+               }
+       })
+}
+
+// Do not copy. The following types are for testing signatures only.
+// They are not working examples.
+// Keep all test functions Above this point.
+type MyAccum struct{}
+
+// Examples of correct CombineFn signatures
+
+type GoodCombineFn struct{}
+
+func (fn *GoodCombineFn) MergeAccumulators(MyAccum, MyAccum) MyAccum {
+       return MyAccum{}
+}
+
+func (fn *GoodCombineFn) CreateAccumulator() MyAccum {
+       return MyAccum{}
+}
+
+func (fn *GoodCombineFn) AddInput(MyAccum, int) MyAccum {
+       return MyAccum{}
+}
+
+func (fn *GoodCombineFn) ExtractOutput(MyAccum) int64 {
+       return 0
+}
+
+type GoodWErrorCombineFn struct{}
+
+func (fn *GoodWErrorCombineFn) MergeAccumulators(int, int) (int, error) {
+       return 0, nil
+}
+
+type GoodWContextCombineFn struct{}
+
+func (fn *GoodWContextCombineFn) MergeAccumulators(context.Context, MyAccum, 
MyAccum) MyAccum {
+       return MyAccum{}
+}
+
+func (fn *GoodWContextCombineFn) CreateAccumulator(context.Context) MyAccum {
+       return MyAccum{}
+}
+
+func (fn *GoodWContextCombineFn) AddInput(context.Context, MyAccum, int) 
MyAccum {
+       return MyAccum{}
+}
+
+func (fn *GoodWContextCombineFn) ExtractOutput(context.Context, MyAccum) int64 
{
+       return 0
+}
+
+type GoodCombineFnUnexportedExtraMethod struct {
+       *GoodCombineFn
+}
+
+func (fn *GoodCombineFnUnexportedExtraMethod) 
unexportedExtraMethod(context.Context, string) string {
+       return ""
+}
+
+// Examples of incorrect CombineFn signatures.
+// Embedding *GoodCombineFn avoids repetitive MergeAccumulators signatures 
when desired.
+// The immeadiately following examples are relating to accumulator mismatches.
+
+type BadCombineFnNoMergeAccumulators struct{}
+
+func (fn *BadCombineFnNoMergeAccumulators) CreateAccumulator() string { return 
"" }
+
+type BadCombineFnNonBinaryMergeAccumulators struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnNonBinaryMergeAccumulators) MergeAccumulators(int, 
string) int {
+       return 0
+}
+
+type BadCombineFnMisMatchedCreateAccumulator struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnMisMatchedCreateAccumulator) CreateAccumulator() string {
+       return ""
+}
+
+type BadCombineFnMisMatchedAddInputIn struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnMisMatchedAddInputIn) AddInput(string, int) MyAccum {
+       return MyAccum{}
+}
+
+type BadCombineFnMisMatchedAddInputOut struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnMisMatchedAddInputOut) AddInput(MyAccum, int) string {
+       return ""
+}
+
+type BadCombineFnMisMatchedAddInputBoth struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnMisMatchedAddInputBoth) AddInput(string, int) string {
+       return ""
+}
+
+type BadCombineFnMisMatchedExtractOutput struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnMisMatchedExtractOutput) ExtractOutput(string) int {
+       return 0
+}
+
+// Examples of incorrect CreateAccumulator signatures
+
+type BadCombineFnInvalidCreateAccumulator1 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidCreateAccumulator1) 
CreateAccumulator(context.Context, string) int {
+       return 0
+}
+
+type BadCombineFnInvalidCreateAccumulator2 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidCreateAccumulator2) CreateAccumulator(string) int 
{
+       return 0
+}
+
+type BadCombineFnInvalidCreateAccumulator3 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidCreateAccumulator3) CreateAccumulator() (MyAccum, 
string) {
+       return MyAccum{}, ""
+}
+
+type BadCombineFnInvalidCreateAccumulator4 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidCreateAccumulator4) CreateAccumulator() (string, 
MyAccum) {
+       return "", MyAccum{}
+}
+
+// Examples of incorrect AddInput signatures
+
+type BadCombineFnInvalidAddInput1 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidAddInput1) AddInput(context.Context, string) int {
+       return 0
+}
+
+type BadCombineFnInvalidAddInput2 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidAddInput2) AddInput(string) int {
+       return 0
+}
+
+type BadCombineFnInvalidAddInput3 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidAddInput3) AddInput(context.Context, string, 
string, string) int {
+       return 0
+}
+
+type BadCombineFnInvalidAddInput4 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidAddInput4) AddInput(MyAccum, string) (int, int, 
int) {
+       return 0, 0, 0
+}
+
+// Examples of incorrect ExtractOutput signatures
+
+type BadCombineFnInvalidExtractOutput1 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidExtractOutput1) ExtractOutput(MyAccum, string) 
(int, int, int) {
+       return 0, 0, 0
+}
+
+type BadCombineFnInvalidExtractOutput2 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidExtractOutput2) ExtractOutput() (int, int, int) {
+       return 0, 0, 0
+}
+
+type BadCombineFnInvalidExtractOutput3 struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnInvalidExtractOutput3) ExtractOutput(context.Context, 
MyAccum, int) int {
+       return 0
+}
+
+// Other CombineFn Errors
+
+type BadCombineFnExtraExportedMethod struct {
+       *GoodCombineFn
+}
+
+func (fn *BadCombineFnExtraExportedMethod) ExtraMethod(string) int {
+       return 0
+}
diff --git a/sdks/go/pkg/beam/transforms/stats/mean.go 
b/sdks/go/pkg/beam/transforms/stats/mean.go
index 9d68231..3b74cde 100644
--- a/sdks/go/pkg/beam/transforms/stats/mean.go
+++ b/sdks/go/pkg/beam/transforms/stats/mean.go
@@ -74,13 +74,8 @@ func (f *meanFn) AddInput(a meanAccum, val beam.T) meanAccum 
{
        return a
 }
 
-func (f *meanFn) MergeAccumulators(list []meanAccum) meanAccum {
-       var ret meanAccum
-       for _, a := range list {
-               ret.Count += a.Count
-               ret.Sum += a.Sum
-       }
-       return ret
+func (f *meanFn) MergeAccumulators(a, b meanAccum) meanAccum {
+       return meanAccum{Count: a.Count + b.Count, Sum: a.Sum + b.Sum}
 }
 
 func (f *meanFn) ExtractOutput(a meanAccum) float64 {
diff --git a/sdks/go/pkg/beam/transforms/stats/stats.shims.go 
b/sdks/go/pkg/beam/transforms/stats/stats.shims.go
index 3af95fb..cd2a95a 100644
--- a/sdks/go/pkg/beam/transforms/stats/stats.shims.go
+++ b/sdks/go/pkg/beam/transforms/stats/stats.shims.go
@@ -68,41 +68,41 @@ func init() {
        runtime.RegisterType(reflect.TypeOf((*meanAccum)(nil)).Elem())
        runtime.RegisterType(reflect.TypeOf((*meanFn)(nil)).Elem())
        reflectx.RegisterStructWrapper(reflect.TypeOf((*meanFn)(nil)).Elem(), 
wrapMakerMeanFn)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(float32, float32) 
float32)(nil)).Elem(), funcMakerFloat32Float32ГFloat32)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(float64, float64) 
float64)(nil)).Elem(), funcMakerFloat64Float64ГFloat64)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(int16, int16) 
int16)(nil)).Elem(), funcMakerInt16Int16ГInt16)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(int32, int32) 
int32)(nil)).Elem(), funcMakerInt32Int32ГInt32)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(int64, int64) 
int64)(nil)).Elem(), funcMakerInt64Int64ГInt64)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(int8, int8) 
int8)(nil)).Elem(), funcMakerInt8Int8ГInt8)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(int, int) 
int)(nil)).Elem(), funcMakerIntIntГInt)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(meanAccum, typex.T) 
meanAccum)(nil)).Elem(), funcMakerMeanAccumTypex۰TГMeanAccum)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(meanAccum) 
float64)(nil)).Elem(), funcMakerMeanAccumГFloat64)
-       reflectx.RegisterFunc(reflect.TypeOf((*func([]meanAccum) 
meanAccum)(nil)).Elem(), funcMakerSliceOfMeanAccumГMeanAccum)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(typex.T) (typex.T, 
int))(nil)).Elem(), funcMakerTypex۰TГTypex۰TInt)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(uint16, uint16) 
uint16)(nil)).Elem(), funcMakerUint16Uint16ГUint16)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(uint32, uint32) 
uint32)(nil)).Elem(), funcMakerUint32Uint32ГUint32)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(uint64, uint64) 
uint64)(nil)).Elem(), funcMakerUint64Uint64ГUint64)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(uint8, uint8) 
uint8)(nil)).Elem(), funcMakerUint8Uint8ГUint8)
-       reflectx.RegisterFunc(reflect.TypeOf((*func(uint, uint) 
uint)(nil)).Elem(), funcMakerUintUintГUint)
-       reflectx.RegisterFunc(reflect.TypeOf((*func() meanAccum)(nil)).Elem(), 
funcMakerГMeanAccum)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(float32,float32) 
(float32))(nil)).Elem(), funcMakerFloat32Float32ГFloat32)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(float64,float64) 
(float64))(nil)).Elem(), funcMakerFloat64Float64ГFloat64)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(int16,int16) 
(int16))(nil)).Elem(), funcMakerInt16Int16ГInt16)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(int32,int32) 
(int32))(nil)).Elem(), funcMakerInt32Int32ГInt32)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(int64,int64) 
(int64))(nil)).Elem(), funcMakerInt64Int64ГInt64)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(int8,int8) 
(int8))(nil)).Elem(), funcMakerInt8Int8ГInt8)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(int,int) 
(int))(nil)).Elem(), funcMakerIntIntГInt)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(meanAccum,meanAccum) 
(meanAccum))(nil)).Elem(), funcMakerMeanAccumMeanAccumГMeanAccum)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(meanAccum,typex.T) 
(meanAccum))(nil)).Elem(), funcMakerMeanAccumTypex۰TГMeanAccum)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(meanAccum) 
(float64))(nil)).Elem(), funcMakerMeanAccumГFloat64)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(typex.T) 
(typex.T,int))(nil)).Elem(), funcMakerTypex۰TГTypex۰TInt)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(uint16,uint16) 
(uint16))(nil)).Elem(), funcMakerUint16Uint16ГUint16)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(uint32,uint32) 
(uint32))(nil)).Elem(), funcMakerUint32Uint32ГUint32)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(uint64,uint64) 
(uint64))(nil)).Elem(), funcMakerUint64Uint64ГUint64)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(uint8,uint8) 
(uint8))(nil)).Elem(), funcMakerUint8Uint8ГUint8)
+       reflectx.RegisterFunc(reflect.TypeOf((*func(uint,uint) 
(uint))(nil)).Elem(), funcMakerUintUintГUint)
+       reflectx.RegisterFunc(reflect.TypeOf((*func() 
(meanAccum))(nil)).Elem(), funcMakerГMeanAccum)
 }
 
 func wrapMakerMeanFn(fn interface{}) map[string]reflectx.Func {
        dfn := fn.(*meanFn)
        return map[string]reflectx.Func{
-               "AddInput":          reflectx.MakeFunc(func(a0 meanAccum, a1 
typex.T) meanAccum { return dfn.AddInput(a0, a1) }),
-               "CreateAccumulator": reflectx.MakeFunc(func() meanAccum { 
return dfn.CreateAccumulator() }),
-               "ExtractOutput":     reflectx.MakeFunc(func(a0 meanAccum) 
float64 { return dfn.ExtractOutput(a0) }),
-               "MergeAccumulators": reflectx.MakeFunc(func(a0 []meanAccum) 
meanAccum { return dfn.MergeAccumulators(a0) }),
+               "AddInput": reflectx.MakeFunc(func(a0 meanAccum, a1 typex.T) 
(meanAccum) { return dfn.AddInput(a0, a1) }),
+               "CreateAccumulator": reflectx.MakeFunc(func() (meanAccum) { 
return dfn.CreateAccumulator() }),
+               "ExtractOutput": reflectx.MakeFunc(func(a0 meanAccum) (float64) 
{ return dfn.ExtractOutput(a0) }),
+               "MergeAccumulators": reflectx.MakeFunc(func(a0 meanAccum, a1 
meanAccum) (meanAccum) { return dfn.MergeAccumulators(a0, a1) }),
        }
 }
 
 type callerFloat32Float32ГFloat32 struct {
-       fn func(float32, float32) float32
+       fn func(float32,float32) (float32)
 }
 
 func funcMakerFloat32Float32ГFloat32(fn interface{}) reflectx.Func {
-       f := fn.(func(float32, float32) float32)
+       f := fn.(func(float32,float32) (float32))
        return &callerFloat32Float32ГFloat32{fn: f}
 }
 
@@ -119,16 +119,16 @@ func (c *callerFloat32Float32ГFloat32) Call(args 
[]interface{}) []interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerFloat32Float32ГFloat32) Call2x1(arg0, arg1 interface{}) 
interface{} {
+func (c *callerFloat32Float32ГFloat32) Call2x1(arg0, arg1 interface{}) 
(interface{}) {
        return c.fn(arg0.(float32), arg1.(float32))
 }
 
 type callerFloat64Float64ГFloat64 struct {
-       fn func(float64, float64) float64
+       fn func(float64,float64) (float64)
 }
 
 func funcMakerFloat64Float64ГFloat64(fn interface{}) reflectx.Func {
-       f := fn.(func(float64, float64) float64)
+       f := fn.(func(float64,float64) (float64))
        return &callerFloat64Float64ГFloat64{fn: f}
 }
 
@@ -145,16 +145,16 @@ func (c *callerFloat64Float64ГFloat64) Call(args 
[]interface{}) []interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerFloat64Float64ГFloat64) Call2x1(arg0, arg1 interface{}) 
interface{} {
+func (c *callerFloat64Float64ГFloat64) Call2x1(arg0, arg1 interface{}) 
(interface{}) {
        return c.fn(arg0.(float64), arg1.(float64))
 }
 
 type callerInt16Int16ГInt16 struct {
-       fn func(int16, int16) int16
+       fn func(int16,int16) (int16)
 }
 
 func funcMakerInt16Int16ГInt16(fn interface{}) reflectx.Func {
-       f := fn.(func(int16, int16) int16)
+       f := fn.(func(int16,int16) (int16))
        return &callerInt16Int16ГInt16{fn: f}
 }
 
@@ -171,16 +171,16 @@ func (c *callerInt16Int16ГInt16) Call(args []interface{}) 
[]interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerInt16Int16ГInt16) Call2x1(arg0, arg1 interface{}) interface{} {
+func (c *callerInt16Int16ГInt16) Call2x1(arg0, arg1 interface{}) (interface{}) 
{
        return c.fn(arg0.(int16), arg1.(int16))
 }
 
 type callerInt32Int32ГInt32 struct {
-       fn func(int32, int32) int32
+       fn func(int32,int32) (int32)
 }
 
 func funcMakerInt32Int32ГInt32(fn interface{}) reflectx.Func {
-       f := fn.(func(int32, int32) int32)
+       f := fn.(func(int32,int32) (int32))
        return &callerInt32Int32ГInt32{fn: f}
 }
 
@@ -197,16 +197,16 @@ func (c *callerInt32Int32ГInt32) Call(args []interface{}) 
[]interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerInt32Int32ГInt32) Call2x1(arg0, arg1 interface{}) interface{} {
+func (c *callerInt32Int32ГInt32) Call2x1(arg0, arg1 interface{}) (interface{}) 
{
        return c.fn(arg0.(int32), arg1.(int32))
 }
 
 type callerInt64Int64ГInt64 struct {
-       fn func(int64, int64) int64
+       fn func(int64,int64) (int64)
 }
 
 func funcMakerInt64Int64ГInt64(fn interface{}) reflectx.Func {
-       f := fn.(func(int64, int64) int64)
+       f := fn.(func(int64,int64) (int64))
        return &callerInt64Int64ГInt64{fn: f}
 }
 
@@ -223,16 +223,16 @@ func (c *callerInt64Int64ГInt64) Call(args []interface{}) 
[]interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerInt64Int64ГInt64) Call2x1(arg0, arg1 interface{}) interface{} {
+func (c *callerInt64Int64ГInt64) Call2x1(arg0, arg1 interface{}) (interface{}) 
{
        return c.fn(arg0.(int64), arg1.(int64))
 }
 
 type callerInt8Int8ГInt8 struct {
-       fn func(int8, int8) int8
+       fn func(int8,int8) (int8)
 }
 
 func funcMakerInt8Int8ГInt8(fn interface{}) reflectx.Func {
-       f := fn.(func(int8, int8) int8)
+       f := fn.(func(int8,int8) (int8))
        return &callerInt8Int8ГInt8{fn: f}
 }
 
@@ -249,16 +249,16 @@ func (c *callerInt8Int8ГInt8) Call(args []interface{}) 
[]interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerInt8Int8ГInt8) Call2x1(arg0, arg1 interface{}) interface{} {
+func (c *callerInt8Int8ГInt8) Call2x1(arg0, arg1 interface{}) (interface{}) {
        return c.fn(arg0.(int8), arg1.(int8))
 }
 
 type callerIntIntГInt struct {
-       fn func(int, int) int
+       fn func(int,int) (int)
 }
 
 func funcMakerIntIntГInt(fn interface{}) reflectx.Func {
-       f := fn.(func(int, int) int)
+       f := fn.(func(int,int) (int))
        return &callerIntIntГInt{fn: f}
 }
 
@@ -275,16 +275,42 @@ func (c *callerIntIntГInt) Call(args []interface{}) 
[]interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerIntIntГInt) Call2x1(arg0, arg1 interface{}) interface{} {
+func (c *callerIntIntГInt) Call2x1(arg0, arg1 interface{}) (interface{}) {
        return c.fn(arg0.(int), arg1.(int))
 }
 
+type callerMeanAccumMeanAccumГMeanAccum struct {
+       fn func(meanAccum,meanAccum) (meanAccum)
+}
+
+func funcMakerMeanAccumMeanAccumГMeanAccum(fn interface{}) reflectx.Func {
+       f := fn.(func(meanAccum,meanAccum) (meanAccum))
+       return &callerMeanAccumMeanAccumГMeanAccum{fn: f}
+}
+
+func (c *callerMeanAccumMeanAccumГMeanAccum) Name() string {
+       return reflectx.FunctionName(c.fn)
+}
+
+func (c *callerMeanAccumMeanAccumГMeanAccum) Type() reflect.Type {
+       return reflect.TypeOf(c.fn)
+}
+
+func (c *callerMeanAccumMeanAccumГMeanAccum) Call(args []interface{}) 
[]interface{} {
+       out0 := c.fn(args[0].(meanAccum), args[1].(meanAccum))
+       return []interface{}{out0}
+}
+
+func (c *callerMeanAccumMeanAccumГMeanAccum) Call2x1(arg0, arg1 interface{}) 
(interface{}) {
+       return c.fn(arg0.(meanAccum), arg1.(meanAccum))
+}
+
 type callerMeanAccumTypex۰TГMeanAccum struct {
-       fn func(meanAccum, typex.T) meanAccum
+       fn func(meanAccum,typex.T) (meanAccum)
 }
 
 func funcMakerMeanAccumTypex۰TГMeanAccum(fn interface{}) reflectx.Func {
-       f := fn.(func(meanAccum, typex.T) meanAccum)
+       f := fn.(func(meanAccum,typex.T) (meanAccum))
        return &callerMeanAccumTypex۰TГMeanAccum{fn: f}
 }
 
@@ -301,16 +327,16 @@ func (c *callerMeanAccumTypex۰TГMeanAccum) Call(args 
[]interface{}) []interfac
        return []interface{}{out0}
 }
 
-func (c *callerMeanAccumTypex۰TГMeanAccum) Call2x1(arg0, arg1 interface{}) 
interface{} {
+func (c *callerMeanAccumTypex۰TГMeanAccum) Call2x1(arg0, arg1 interface{}) 
(interface{}) {
        return c.fn(arg0.(meanAccum), arg1.(typex.T))
 }
 
 type callerMeanAccumГFloat64 struct {
-       fn func(meanAccum) float64
+       fn func(meanAccum) (float64)
 }
 
 func funcMakerMeanAccumГFloat64(fn interface{}) reflectx.Func {
-       f := fn.(func(meanAccum) float64)
+       f := fn.(func(meanAccum) (float64))
        return &callerMeanAccumГFloat64{fn: f}
 }
 
@@ -327,42 +353,16 @@ func (c *callerMeanAccumГFloat64) Call(args 
[]interface{}) []interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerMeanAccumГFloat64) Call1x1(arg0 interface{}) interface{} {
+func (c *callerMeanAccumГFloat64) Call1x1(arg0 interface{}) (interface{}) {
        return c.fn(arg0.(meanAccum))
 }
 
-type callerSliceOfMeanAccumГMeanAccum struct {
-       fn func([]meanAccum) meanAccum
-}
-
-func funcMakerSliceOfMeanAccumГMeanAccum(fn interface{}) reflectx.Func {
-       f := fn.(func([]meanAccum) meanAccum)
-       return &callerSliceOfMeanAccumГMeanAccum{fn: f}
-}
-
-func (c *callerSliceOfMeanAccumГMeanAccum) Name() string {
-       return reflectx.FunctionName(c.fn)
-}
-
-func (c *callerSliceOfMeanAccumГMeanAccum) Type() reflect.Type {
-       return reflect.TypeOf(c.fn)
-}
-
-func (c *callerSliceOfMeanAccumГMeanAccum) Call(args []interface{}) 
[]interface{} {
-       out0 := c.fn(args[0].([]meanAccum))
-       return []interface{}{out0}
-}
-
-func (c *callerSliceOfMeanAccumГMeanAccum) Call1x1(arg0 interface{}) 
interface{} {
-       return c.fn(arg0.([]meanAccum))
-}
-
 type callerTypex۰TГTypex۰TInt struct {
-       fn func(typex.T) (typex.T, int)
+       fn func(typex.T) (typex.T,int)
 }
 
 func funcMakerTypex۰TГTypex۰TInt(fn interface{}) reflectx.Func {
-       f := fn.(func(typex.T) (typex.T, int))
+       f := fn.(func(typex.T) (typex.T,int))
        return &callerTypex۰TГTypex۰TInt{fn: f}
 }
 
@@ -384,11 +384,11 @@ func (c *callerTypex۰TГTypex۰TInt) Call1x2(arg0 
interface{}) (interface{}, in
 }
 
 type callerUint16Uint16ГUint16 struct {
-       fn func(uint16, uint16) uint16
+       fn func(uint16,uint16) (uint16)
 }
 
 func funcMakerUint16Uint16ГUint16(fn interface{}) reflectx.Func {
-       f := fn.(func(uint16, uint16) uint16)
+       f := fn.(func(uint16,uint16) (uint16))
        return &callerUint16Uint16ГUint16{fn: f}
 }
 
@@ -405,16 +405,16 @@ func (c *callerUint16Uint16ГUint16) Call(args 
[]interface{}) []interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerUint16Uint16ГUint16) Call2x1(arg0, arg1 interface{}) 
interface{} {
+func (c *callerUint16Uint16ГUint16) Call2x1(arg0, arg1 interface{}) 
(interface{}) {
        return c.fn(arg0.(uint16), arg1.(uint16))
 }
 
 type callerUint32Uint32ГUint32 struct {
-       fn func(uint32, uint32) uint32
+       fn func(uint32,uint32) (uint32)
 }
 
 func funcMakerUint32Uint32ГUint32(fn interface{}) reflectx.Func {
-       f := fn.(func(uint32, uint32) uint32)
+       f := fn.(func(uint32,uint32) (uint32))
        return &callerUint32Uint32ГUint32{fn: f}
 }
 
@@ -431,16 +431,16 @@ func (c *callerUint32Uint32ГUint32) Call(args 
[]interface{}) []interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerUint32Uint32ГUint32) Call2x1(arg0, arg1 interface{}) 
interface{} {
+func (c *callerUint32Uint32ГUint32) Call2x1(arg0, arg1 interface{}) 
(interface{}) {
        return c.fn(arg0.(uint32), arg1.(uint32))
 }
 
 type callerUint64Uint64ГUint64 struct {
-       fn func(uint64, uint64) uint64
+       fn func(uint64,uint64) (uint64)
 }
 
 func funcMakerUint64Uint64ГUint64(fn interface{}) reflectx.Func {
-       f := fn.(func(uint64, uint64) uint64)
+       f := fn.(func(uint64,uint64) (uint64))
        return &callerUint64Uint64ГUint64{fn: f}
 }
 
@@ -457,16 +457,16 @@ func (c *callerUint64Uint64ГUint64) Call(args 
[]interface{}) []interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerUint64Uint64ГUint64) Call2x1(arg0, arg1 interface{}) 
interface{} {
+func (c *callerUint64Uint64ГUint64) Call2x1(arg0, arg1 interface{}) 
(interface{}) {
        return c.fn(arg0.(uint64), arg1.(uint64))
 }
 
 type callerUint8Uint8ГUint8 struct {
-       fn func(uint8, uint8) uint8
+       fn func(uint8,uint8) (uint8)
 }
 
 func funcMakerUint8Uint8ГUint8(fn interface{}) reflectx.Func {
-       f := fn.(func(uint8, uint8) uint8)
+       f := fn.(func(uint8,uint8) (uint8))
        return &callerUint8Uint8ГUint8{fn: f}
 }
 
@@ -483,16 +483,16 @@ func (c *callerUint8Uint8ГUint8) Call(args []interface{}) 
[]interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerUint8Uint8ГUint8) Call2x1(arg0, arg1 interface{}) interface{} {
+func (c *callerUint8Uint8ГUint8) Call2x1(arg0, arg1 interface{}) (interface{}) 
{
        return c.fn(arg0.(uint8), arg1.(uint8))
 }
 
 type callerUintUintГUint struct {
-       fn func(uint, uint) uint
+       fn func(uint,uint) (uint)
 }
 
 func funcMakerUintUintГUint(fn interface{}) reflectx.Func {
-       f := fn.(func(uint, uint) uint)
+       f := fn.(func(uint,uint) (uint))
        return &callerUintUintГUint{fn: f}
 }
 
@@ -509,16 +509,16 @@ func (c *callerUintUintГUint) Call(args []interface{}) 
[]interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerUintUintГUint) Call2x1(arg0, arg1 interface{}) interface{} {
+func (c *callerUintUintГUint) Call2x1(arg0, arg1 interface{}) (interface{}) {
        return c.fn(arg0.(uint), arg1.(uint))
 }
 
 type callerГMeanAccum struct {
-       fn func() meanAccum
+       fn func() (meanAccum)
 }
 
 func funcMakerГMeanAccum(fn interface{}) reflectx.Func {
-       f := fn.(func() meanAccum)
+       f := fn.(func() (meanAccum))
        return &callerГMeanAccum{fn: f}
 }
 
@@ -535,8 +535,9 @@ func (c *callerГMeanAccum) Call(args []interface{}) 
[]interface{} {
        return []interface{}{out0}
 }
 
-func (c *callerГMeanAccum) Call0x1() interface{} {
+func (c *callerГMeanAccum) Call0x1() (interface{}) {
        return c.fn()
 }
 
+
 // DO NOT MODIFY: GENERATED CODE

Reply via email to