mirror of
https://github.com/golang/go
synced 2024-11-18 23:44:43 -07:00
ced954c167
An identifier X in anonymous struct field struct{X} is both a definition of a field (*Var) and reference to a type (*TypeName). Now that we have split the map, we can capture both of these aspects. Interestingly, every client but one was going to extra effort to iterate over just the uses or just the defs; this simplifies them. Also, fix two bug related to tagless switches: - An entry was being recorded in the Object map for a piece of synthetic syntax. - The "true" identifier was being looked up in the current scope, which allowed perverse users to locally redefine it. Now we use the bool (not untyped boolean) constant true, per the consequent clarification of the spec (issue 7404). + tests. Fixes golang/go#7276 LGTM=gri R=gri CC=golang-codereviews https://golang.org/cl/68270044
64 lines
1.3 KiB
Go
64 lines
1.3 KiB
Go
// Copyright 2013 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
/*
|
|
This file contains the code to check for useless function comparisons.
|
|
A useless comparison is one like f == nil as opposed to f() == nil.
|
|
*/
|
|
|
|
package main
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/token"
|
|
|
|
"code.google.com/p/go.tools/go/types"
|
|
)
|
|
|
|
func (f *File) checkNilFuncComparison(e *ast.BinaryExpr) {
|
|
if !vet("nilfunc") {
|
|
return
|
|
}
|
|
|
|
// Only want == or != comparisons.
|
|
if e.Op != token.EQL && e.Op != token.NEQ {
|
|
return
|
|
}
|
|
|
|
// Only want comparisons with a nil identifier on one side.
|
|
var e2 ast.Expr
|
|
switch {
|
|
case f.isNil(e.X):
|
|
e2 = e.Y
|
|
case f.isNil(e.Y):
|
|
e2 = e.X
|
|
default:
|
|
return
|
|
}
|
|
|
|
// Only want identifiers or selector expressions.
|
|
var obj types.Object
|
|
switch v := e2.(type) {
|
|
case *ast.Ident:
|
|
obj = f.pkg.uses[v]
|
|
case *ast.SelectorExpr:
|
|
obj = f.pkg.uses[v.Sel]
|
|
default:
|
|
return
|
|
}
|
|
|
|
// Only want functions.
|
|
if _, ok := obj.(*types.Func); !ok {
|
|
return
|
|
}
|
|
|
|
f.Badf(e.Pos(), "comparison of function %v %v nil is always %v", obj.Name(), e.Op, e.Op == token.NEQ)
|
|
}
|
|
|
|
// isNil reports whether the provided expression is the built-in nil
|
|
// identifier.
|
|
func (f *File) isNil(e ast.Expr) bool {
|
|
return f.pkg.types[e].Type == types.Typ[types.UntypedNil]
|
|
}
|