Avoid type-inference warnings due to partial type info.
Signed-off-by: Joe Tsai <joetsai@google.com>
diff --git a/lint.go b/lint.go
index 3aaaf2a..14cc626 100644
--- a/lint.go
+++ b/lint.go
@@ -935,18 +935,6 @@
"0i": true,
}
-// knownWeakerTypes is a set of types that are commonly used to weaken var declarations.
-// A common form of var declarations that legitimately mentions an explicit LHS type
-// is where the LHS type is "weaker" than the exact RHS type, where "weaker" means an
-// interface compared to a concrete type, or an interface compared to a superset interface.
-// A canonical example is `var out io.Writer = os.Stdout`.
-// This is only used when type checking fails to determine the exact types.
-var knownWeakerTypes = map[string]bool{
- "io.Reader": true,
- "io.Writer": true,
- "proto.Message": true,
-}
-
// lintVarDecls examines variable declarations. It complains about declarations with
// redundant LHS types that can be inferred from the RHS.
func (f *file) lintVarDecls() {
@@ -986,7 +974,13 @@
}
lhsTyp := f.pkg.typeOf(v.Type)
rhsTyp := f.pkg.typeOf(rhs)
- if lhsTyp != nil && rhsTyp != nil && !types.Identical(lhsTyp, rhsTyp) {
+
+ 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
}
@@ -1005,13 +999,6 @@
if defType, ok := f.isUntypedConst(rhs); ok && !isIdent(v.Type, defType) {
return false
}
- // If the LHS is a known weaker type, and we couldn't type check both sides,
- // don't warn.
- if lhsTyp == nil || rhsTyp == nil {
- if knownWeakerTypes[f.render(v.Type)] {
- 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
@@ -1020,6 +1007,12 @@
})
}
+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
index d382bee..9201d18 100644
--- a/testdata/var-decl.go
+++ b/testdata/var-decl.go
@@ -3,8 +3,13 @@
// Package foo ...
package foo
-import "fmt"
-import "net/http"
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "nosuchpkg" // export data unavailable
+ "os"
+)
// Q is a test type.
type Q bool
@@ -63,16 +68,17 @@
// LHS is a different type than the RHS.
var myStringer fmt.Stringer = q(0)
-// We don't figure out the true types of LHS and RHS here,
-// but io.Writer is a known weaker type for many common uses,
-// so the suggestion should be suppressed here.
+// LHS is a different type than the RHS.
var out io.Writer = os.Stdout
-// This next one, however, should be type checked.
-var out2 io.Writer = newWriter() // MATCH /should.*io\.Writer/
+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