See https://play.golang.org/p/fAb8AX92nf:
package main
import (
"fmt"
)
type ET struct{}
func (*ET) Error() string { return "err" }
func main() {
fmt.Printf("(*ET)(nil) == error(nil): %v\n", (*ET)(nil) == error(nil))
fmt.Printf("(*ET)(nil) != error(nil): %v\n", (*ET)(nil) != error(nil))
nilET := (*ET)(nil)
nilError := error(nil)
fmt.Printf("nilET == nilError: %v\n", nilET == nilError)
fmt.Printf("nilET != nilError: %v\n", nilET != nilError)
}
Expected output:
(*ET)(nil) == error(nil): false
(*ET)(nil) != error(nil): true
nilET == nilError: false
nilET != nilError: true
Actual output:
(*ET)(nil) == error(nil): false
(*ET)(nil) != error(nil): false
nilET == nilError: false
nilET != nilError: true
Note that the (*ET)(nil) != error(nil) case returns false. Unless I'm mistaken, it should return true.
Fun! Bisecting.
Go 1.8 agrees with tip. Go 1.7 rejects the code with:
# command-line-arguments
./x.go:12: illegal constant expression: *ET == error
./x.go:13: illegal constant expression: *ET != error
Go 1.7 would be incorrect as well, as these are not constant expressions (nil is not a constant).
gccgo says
(*ET)(nil) == error(nil): false
(*ET)(nil) != error(nil): true
nilET == nilError: false
nilET != nilError: true
Go 1.5 and 1.6 also say illegal constant expression. Go 1.0 through Go 1.4 generate the same output as gccgo.
Most helpful comment
gccgo says