Skip to content

text/template: Invalid handling off typed nils in if and with  #30501

Closed
@bep

Description

@bep

This issue is a rework of #30481, which I felt was closed a little prematurely. This is, on one or more levels, a real issue that needs to be addressed. I will try to make this shorter and to the point.

The program below prints:

<nil>:	         IsTrue: false: Nil == nil: true 
*main.Nill:	 IsTrue: false: Nil == nil: false Failed, got <nil>

Also see https://play.golang.org/p/HzwnX062jjk

The documentation for template.IsTrue states that

IsTrue reports whether the value is 'true', in the sense of not the zero of its type, and whether the value has a meaningful truth value. This is the definition of truth used by if and other such actions.

So, while I understand that Nil != nil in the second example above, which, I suspect, is part of the reason why the template package uses reflect. I would expect that all values that is truthful according to template.IsTrue is also truthful in if and with.

package main

import (
	"bytes"
	"fmt"
	"log"
	"text/template"
)

type Niller interface {
	Nil() Niller
	Foo() string
}

type Nill struct {
	nilv Niller
}

func (n Nill) Nil() Niller {
	return n.nilv
}

func (n Nill) Foo() string {
	return "asdf"
}

func main() {

	tmpl, err := template.New("").Parse(`
{{- with .Niller.Nil }}{{ if not $.IsTrue }}Failed, got {{ . }}{{ end }}
{{- else }}{{ if $.IsTrue }}Failed else{{ end -}}
{{ end -}}
`)
	if err != nil {
		log.Fatal(err)
	}

	var (
		nil1 Niller
		nil2 *Nill
	)

	execute(tmpl, nil1)
	execute(tmpl, nil2)

}

func execute(tmpl *template.Template, niller Niller) {
	var buff bytes.Buffer
	n := &Nill{nilv: niller}
	isTrue, ok := template.IsTrue(n.Nil())
	if !ok {
		log.Fatal("IsTrue failed")
	}

	data := map[string]interface{}{
		"IsTrue": isTrue,
		"Niller": n,
	}

	err := tmpl.Execute(&buff, data)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("%T:\t IsTrue: %t: Nil == nil: %t %s\n", niller, isTrue, (n.Nil() == nil), buff.String())
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions