]> Cypherpunks repositories - gostls13.git/commitdiff
text/template: Make function call builtin handle nil errors correctly
authorElias Naur <elias.naur@gmail.com>
Tue, 13 Aug 2013 01:11:05 +0000 (11:11 +1000)
committerRob Pike <r@golang.org>
Tue, 13 Aug 2013 01:11:05 +0000 (11:11 +1000)
The call builtin unconditionally tries to convert a second return value from a function to the error type. This fails in case nil is returned, effectively making call useless for functions returning two values.

This CL adds a nil check for the second return value, and adds a test.

Note that for regular function and method calls the nil error case is handled correctly and is verified by a test.

R=r
CC=golang-dev
https://golang.org/cl/12804043

src/pkg/text/template/exec_test.go
src/pkg/text/template/funcs.go

index b89856593132f3be7fd4615d468beb68737d0135..3d110af9cce18a8c60f17acf853a82ca4ca6a109 100644 (file)
@@ -64,6 +64,7 @@ type T struct {
        VariadicFunc    func(...string) string
        VariadicFuncInt func(int, ...string) string
        NilOKFunc       func(*int) bool
+       ErrFunc         func() (string, error)
        // Template to test evaluation of templates.
        Tmpl *Template
        // Unexported field; cannot be accessed by template.
@@ -129,6 +130,7 @@ var tVal = &T{
        VariadicFunc:      func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
        VariadicFuncInt:   func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
        NilOKFunc:         func(s *int) bool { return s == nil },
+       ErrFunc:           func() (string, error) { return "bla", nil },
        Tmpl:              Must(New("x").Parse("test template")), // "x" is the value of .X
 }
 
@@ -322,6 +324,7 @@ var execTests = []execTest{
        {"if .BinaryFunc call", "{{ if .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{end}}", "[1=2]", tVal, true},
        {"if not .BinaryFunc call", "{{ if not .BinaryFunc}}{{call .BinaryFunc `1` `2`}}{{else}}No{{end}}", "No", tVal, true},
        {"Interface Call", `{{stringer .S}}`, "foozle", map[string]interface{}{"S": bytes.NewBufferString("foozle")}, true},
+       {".ErrFunc", "{{call .ErrFunc}}", "bla", tVal, true},
 
        // Erroneous function calls (check args).
        {".BinaryFuncTooFew", "{{call .BinaryFunc `1`}}", "", tVal, false},
index 8187663648a27d6e1d7143b7635364aab108238d..643a728cb7a4ac80d4f8e7da4ac6784cb83cd344 100644 (file)
@@ -199,7 +199,7 @@ func call(fn interface{}, args ...interface{}) (interface{}, error) {
                argv[i] = value
        }
        result := v.Call(argv)
-       if len(result) == 2 {
+       if len(result) == 2 && !result[1].IsNil() {
                return result[0].Interface(), result[1].Interface().(error)
        }
        return result[0].Interface(), nil