Skip to content

Commit

Permalink
text/template: compare reflect.Value instances differently
Browse files Browse the repository at this point in the history
To avoid false positives from the reflectvaluecompare checker #43993

Use v.IsValid() instead of

var zero reflect.Value
v != zero

Also avoid comparing directly with the singleton reflect.Value
representing a missing value. Detect the missing value by type instead.

Change-Id: I3a00d63cf61c077e7c7ae816474aa1f032be325b
Reviewed-on: https://go-review.googlesource.com/c/go/+/308769
Reviewed-by: Cherry Mui <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Run-TryBot: Keith Randall <[email protected]>
Reviewed-by: Daniel Martí <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
  • Loading branch information
randall77 authored and mvdan committed Aug 22, 2022
1 parent 8d57f4d commit 9a9aad4
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 5 deletions.
14 changes: 10 additions & 4 deletions src/text/template/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ type missingValType struct{}

var missingVal = reflect.ValueOf(missingValType{})

var missingValReflectType = reflect.TypeOf(missingValType{})

func isMissing(v reflect.Value) bool {
return v.IsValid() && v.Type() == missingValReflectType
}

// at marks the state to be on node n, for error reporting.
func (s *state) at(node parse.Node) {
s.node = node
Expand Down Expand Up @@ -471,7 +477,7 @@ func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value ref
}

func (s *state) notAFunction(args []parse.Node, final reflect.Value) {
if len(args) > 1 || final != missingVal {
if len(args) > 1 || !isMissing(final) {
s.errorf("can't give argument to non-function %s", args[0])
}
}
Expand Down Expand Up @@ -629,7 +635,7 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
if method := ptr.MethodByName(fieldName); method.IsValid() {
return s.evalCall(dot, method, false, node, fieldName, args, final)
}
hasArgs := len(args) > 1 || final != missingVal
hasArgs := len(args) > 1 || !isMissing(final)
// It's not a method; must be a field of a struct or an element of a map.
switch receiver.Kind() {
case reflect.Struct:
Expand Down Expand Up @@ -700,7 +706,7 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
}
typ := fun.Type()
numIn := len(args)
if final != missingVal {
if !isMissing(final) {
numIn++
}
numFixed := len(args)
Expand Down Expand Up @@ -763,7 +769,7 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
}
}
// Add final value if necessary.
if final != missingVal {
if !isMissing(final) {
t := typ.In(typ.NumIn() - 1)
if typ.IsVariadic() {
if numIn-1 < numFixed {
Expand Down
2 changes: 1 addition & 1 deletion src/text/template/funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ func basicKind(v reflect.Value) (kind, error) {

// isNil returns true if v is the zero reflect.Value, or nil of its type.
func isNil(v reflect.Value) bool {
if v == zero {
if !v.IsValid() {
return true
}
switch v.Kind() {
Expand Down

0 comments on commit 9a9aad4

Please sign in to comment.