lint: remove the var decl check

Removes the var decl check which often fires when the type is required
for documentation purposes. For example, when an enumerated list of
pre-defined values of a certain type is created, it may be desirable to
group those values under the type itself in the docs. If the type is
infered, godoc will not group them, but if the type is manually listed
they will be placed in the correct location.

Since this lint is not an important stylistic consideration and
frequently produces false positives, removing it is consistent with the
scope of lints in this project.

Fixes golang/lint#429

Change-Id: I2afd928eae0bb11b39886c045556cda0771e3af5
Reviewed-on: https://go-review.googlesource.com/c/lint/+/191317
Run-TryBot: Sam Whited <sam@samwhited.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Andrew Bonventre <andybons@golang.org>
diff --git a/lint.go b/lint.go
index 6b9fd6e..532a75a 100644
--- a/lint.go
+++ b/lint.go
@@ -198,7 +198,6 @@
 	f.lintBlankImports()
 	f.lintExported()
 	f.lintNames()
-	f.lintVarDecls()
 	f.lintElses()
 	f.lintRanges()
 	f.lintErrorf()
@@ -977,84 +976,6 @@
 	"0i":  true,
 }
 
-// lintVarDecls examines variable declarations. It complains about declarations with
-// redundant LHS types that can be inferred from the RHS.
-func (f *file) lintVarDecls() {
-	var lastGen *ast.GenDecl // last GenDecl entered.
-
-	f.walk(func(node ast.Node) bool {
-		switch v := node.(type) {
-		case *ast.GenDecl:
-			if v.Tok != token.CONST && v.Tok != token.VAR {
-				return false
-			}
-			lastGen = v
-			return true
-		case *ast.ValueSpec:
-			if lastGen.Tok == token.CONST {
-				return false
-			}
-			if len(v.Names) > 1 || v.Type == nil || len(v.Values) == 0 {
-				return false
-			}
-			rhs := v.Values[0]
-			// An underscore var appears in a common idiom for compile-time interface satisfaction,
-			// as in "var _ Interface = (*Concrete)(nil)".
-			if isIdent(v.Names[0], "_") {
-				return false
-			}
-			// If the RHS is a zero value, suggest dropping it.
-			zero := false
-			if lit, ok := rhs.(*ast.BasicLit); ok {
-				zero = zeroLiteral[lit.Value]
-			} else if isIdent(rhs, "nil") {
-				zero = true
-			}
-			if zero {
-				f.errorf(rhs, 0.9, category("zero-value"), "should drop = %s from declaration of var %s; it is the zero value", f.render(rhs), v.Names[0])
-				return false
-			}
-			lhsTyp := f.pkg.typeOf(v.Type)
-			rhsTyp := f.pkg.typeOf(rhs)
-
-			if !validType(lhsTyp) || !validType(rhsTyp) {
-				// Type checking failed (often due to missing imports).
-				return false
-			}
-
-			if !types.Identical(lhsTyp, rhsTyp) {
-				// Assignment to a different type is not redundant.
-				return false
-			}
-
-			// The next three conditions are for suppressing the warning in situations
-			// where we were unable to typecheck.
-
-			// If the LHS type is an interface, don't warn, since it is probably a
-			// concrete type on the RHS. Note that our feeble lexical check here
-			// will only pick up interface{} and other literal interface types;
-			// that covers most of the cases we care to exclude right now.
-			if _, ok := v.Type.(*ast.InterfaceType); ok {
-				return false
-			}
-			// If the RHS is an untyped const, only warn if the LHS type is its default type.
-			if defType, ok := f.isUntypedConst(rhs); ok && !isIdent(v.Type, defType) {
-				return false
-			}
-
-			f.errorf(v.Type, 0.8, category("type-inference"), "should omit type %s from declaration of var %s; it will be inferred from the right-hand side", f.render(v.Type), v.Names[0])
-			return false
-		}
-		return true
-	})
-}
-
-func validType(T types.Type) bool {
-	return T != nil &&
-		T != types.Typ[types.Invalid] &&
-		!strings.Contains(T.String(), "invalid type") // good but not foolproof
-}
-
 // lintElses examines else blocks. It complains about any else block whose if block ends in a return.
 func (f *file) lintElses() {
 	// We don't want to flag if { } else if { } else { } constructions.
diff --git a/testdata/var-decl.go b/testdata/var-decl.go
deleted file mode 100644
index 9201d18..0000000
--- a/testdata/var-decl.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Test for redundant type declaration.
-
-// Package foo ...
-package foo
-
-import (
-	"fmt"
-	"io"
-	"net/http"
-	"nosuchpkg" // export data unavailable
-	"os"
-)
-
-// Q is a test type.
-type Q bool
-
-var myInt int = 7                           // MATCH /should.*int.*myInt.*inferred/
-var mux *http.ServeMux = http.NewServeMux() // MATCH /should.*\*http\.ServeMux.*inferred/
-
-var myZeroInt int = 0         // MATCH /should.*= 0.*myZeroInt.*zero value/
-var myZeroFlt float32 = 0.    // MATCH /should.*= 0\..*myZeroFlt.*zero value/
-var myZeroF64 float64 = 0.0   // MATCH /should.*= 0\..*myZeroF64.*zero value/
-var myZeroImg complex64 = 0i  // MATCH /should.*= 0i.*myZeroImg.*zero value/
-var myZeroStr string = ""     // MATCH /should.*= "".*myZeroStr.*zero value/
-var myZeroRaw string = ``     // MATCH /should.*= ``.*myZeroRaw.*zero value/
-var myZeroPtr *Q = nil        // MATCH /should.*= nil.*myZeroPtr.*zero value/
-var myZeroRune rune = '\x00'  // MATCH /should.*= '\\x00'.*myZeroRune.*zero value/
-var myZeroRune2 rune = '\000' // MATCH /should.*= '\\000'.*myZeroRune2.*zero value/
-
-// No warning because there's no type on the LHS
-var x = 0
-
-// This shouldn't get a warning because there's no initial values.
-var str fmt.Stringer
-
-// No warning because this is a const.
-const k uint64 = 7
-
-const num = 123
-
-// No warning because the var's RHS is known to be an untyped const.
-var flags uint32 = num
-
-// No warnings because the RHS is an ideal int, and the LHS is a different int type.
-var userID int64 = 1235
-var negID int64 = -1
-var parenID int64 = (17)
-var crazyID int64 = -(-(-(-9)))
-
-// Same, but for strings and floats.
-type stringT string
-type floatT float64
-
-var stringV stringT = "abc"
-var floatV floatT = 123.45
-
-// No warning because the LHS names an interface type.
-var data interface{} = googleIPs
-var googleIPs []int
-
-// No warning because it's a common idiom for interface satisfaction.
-var _ Server = (*serverImpl)(nil)
-
-// Server is a test type.
-type Server interface{}
-type serverImpl struct{}
-
-// LHS is a different type than the RHS.
-var myStringer fmt.Stringer = q(0)
-
-// LHS is a different type than the RHS.
-var out io.Writer = os.Stdout
-
-var out2 io.Writer = newWriter() // MATCH /should omit.*io\.Writer/
-
-func newWriter() io.Writer { return nil }
-
-// We don't figure out the true types of LHS and RHS here,
-// so we suppress the check.
-var ni nosuchpkg.Interface = nosuchpkg.NewConcrete()
-
-var y string = q(1).String() // MATCH /should.*string/
-
-type q int
-
-func (q) String() string { return "I'm a q" }