Repository: go
Issue: cmd/vet: potential false positive in the "suspect or" check
Labels: NeedsInvestigation,Analysis

### What version of Go are you using (`go version`)?

`go version go1.11.1 linux/amd64`

### Does this issue reproduce with the latest release?

yes

### What operating system and processor architecture are you using (`go env`)?

```
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/jnml/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/jnml"
GOPROXY=""
GORACE=""
GOROOT="/home/jnml/go"
GOTMPDIR=""
GOTOOLDIR="/home/jnml/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build777349074=/tmp/go-build -gno-record-gcc-switches"
```

### What did you do?

Using `github.com/cznic/ql`, branch `file2`, checked out at `3497607bfaba518eab540d317a6c168396b8002f`.

```
==== jnml@4670:~/src/github.com/cznic/ql> go test
# github.com/cznic/ql
./file2.go:37: suspect or: szKey != szVal || szKey != szBuf
FAIL	github.com/cznic/ql [build failed]
==== jnml@4670:~/src/github.com/cznic/ql> 
```

### What did you expect to see?

Build succeeds, tests are executed and failures reported.

### What did you see instead?

Build fails.

### Additional info

The line go vet does not like [is here](https://github.com/cznic/ql/blob/3497607bfaba518eab540d317a6c168396b8002f/file2.go#L37)

```go
func init() {
	if al := cfile.AllocAllign; al != 16 || al <= binary.MaxVarintLen64 {
		panic("internal error")
	}

	if szKey != szVal || szKey != szBuf { // <-- line 37
		panic("internal error")
	}
}

const (
	magic2      = "\x61\xdbql"
	szBuf       = szKey
	szKey       = cfile.AllocAllign // BTree
	szVal       = szKey             // BTree
	wal2PageLog = 12                //TODO tune pagelog
)
```

Line 37 tests for equality of the three values `szKey, szValue, szBuf` which other code depends on as it would have to be more complicated for the general case and the equality allow simplifying it. I see nothing wrong about the line, I donť think `vet` should reject it.

The `vet` test is located [here](https://github.com/golang/go/blob/50bd1c4d4eb4fac8ddeb5f063c099daccfb71b26/src/cmd/vet/bool.go#L90)

```go
// checkSuspect checks for expressions of the form
//   x != c1 || x != c2
//   x == c1 && x == c2
// where c1 and c2 are constant expressions.
// If c1 and c2 are the same then it's redundant;
// if c1 and c2 are different then it's always true or always false.
// Exprs must contain only side effect free expressions.
func (op boolOp) checkSuspect(f *File, exprs []ast.Expr) {
...
}
```

The comment `if c1 and c2 are different then it's always true or always false.` is correct, but that does not imply something is wrong.

There's nothing wrong in implementing

```
a == b == c
```

in Go as 

```go
a == b && a == c
```

Where the negation, rejected by `vet`, is 

```go
a != b || a != c
```

Workaround: `vet` is happy if the expression is rewritten as

```go
szKey != szVal || szVal != szBuf
```

even though the two versions are logical identities.