go.tools/go/types: avoid spurious "declared but not used" errors in case of other errors
LGTM=adonovan R=adonovan CC=golang-codereviews https://golang.org/cl/76810044
This commit is contained in:
parent
a4491f08bf
commit
a781b00b0d
|
|
@ -210,12 +210,13 @@ func (check *checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos)
|
||||||
l := len(lhs)
|
l := len(lhs)
|
||||||
get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
|
get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())
|
||||||
if l != r {
|
if l != r {
|
||||||
// invalidate lhs
|
// invalidate lhs and use rhs
|
||||||
for _, obj := range lhs {
|
for _, obj := range lhs {
|
||||||
if obj.typ == nil {
|
if obj.typ == nil {
|
||||||
obj.typ = Typ[Invalid]
|
obj.typ = Typ[Invalid]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
check.use(rhs...)
|
||||||
if returnPos.IsValid() {
|
if returnPos.IsValid() {
|
||||||
check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r)
|
check.errorf(returnPos, "wrong number of return values (want %d, got %d)", l, r)
|
||||||
return
|
return
|
||||||
|
|
@ -246,6 +247,7 @@ func (check *checker) assignVars(lhs, rhs []ast.Expr) {
|
||||||
get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2)
|
get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2)
|
||||||
if l != r {
|
if l != r {
|
||||||
check.errorf(rhs[0].Pos(), "assignment count mismatch (%d vs %d)", l, r)
|
check.errorf(rhs[0].Pos(), "assignment count mismatch (%d vs %d)", l, r)
|
||||||
|
check.use(rhs...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||||
bin := predeclaredFuncs[id]
|
bin := predeclaredFuncs[id]
|
||||||
if call.Ellipsis.IsValid() && id != _Append {
|
if call.Ellipsis.IsValid() && id != _Append {
|
||||||
check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name)
|
check.invalidOp(call.Ellipsis, "invalid use of ... with built-in %s", bin.name)
|
||||||
check.use(call.Args)
|
check.use(call.Args...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -481,7 +481,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
||||||
selx, _ := unparen(arg0).(*ast.SelectorExpr)
|
selx, _ := unparen(arg0).(*ast.SelectorExpr)
|
||||||
if selx == nil {
|
if selx == nil {
|
||||||
check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0)
|
check.invalidArg(arg0.Pos(), "%s is not a selector expression", arg0)
|
||||||
check.rawExpr(x, arg0, nil) // evaluate to avoid spurious "declared but not used" errors
|
check.use(arg0)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
check.expr(x, selx.X)
|
check.expr(x, selx.X)
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ func (check *checker) call(x *operand, e *ast.CallExpr) exprKind {
|
||||||
|
|
||||||
switch x.mode {
|
switch x.mode {
|
||||||
case invalid:
|
case invalid:
|
||||||
check.use(e.Args)
|
check.use(e.Args...)
|
||||||
x.mode = invalid
|
x.mode = invalid
|
||||||
x.expr = e
|
x.expr = e
|
||||||
return statement
|
return statement
|
||||||
|
|
@ -82,12 +82,12 @@ func (check *checker) call(x *operand, e *ast.CallExpr) exprKind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use type-checks each list element.
|
// use type-checks each argument.
|
||||||
// Useful to make sure a list of expressions is evaluated
|
// Useful to make sure expressions are evaluated
|
||||||
// (and variables are "used") in the presence of other errors.
|
// (and variables are "used") in the presence of other errors.
|
||||||
func (check *checker) use(list []ast.Expr) {
|
func (check *checker) use(arg ...ast.Expr) {
|
||||||
var x operand
|
var x operand
|
||||||
for _, e := range list {
|
for _, e := range arg {
|
||||||
check.rawExpr(&x, e, nil)
|
check.rawExpr(&x, e, nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,11 @@ func (check *checker) arityMatch(s, init *ast.ValueSpec) {
|
||||||
// init exprs from s
|
// init exprs from s
|
||||||
n := s.Values[l]
|
n := s.Values[l]
|
||||||
check.errorf(n.Pos(), "extra init expr %s", n)
|
check.errorf(n.Pos(), "extra init expr %s", n)
|
||||||
|
// TODO(gri) avoid declared but not used error here
|
||||||
} else {
|
} else {
|
||||||
// init exprs "inherited"
|
// init exprs "inherited"
|
||||||
check.errorf(s.Pos(), "extra init expr at %s", init.Pos())
|
check.errorf(s.Pos(), "extra init expr at %s", init.Pos())
|
||||||
|
// TODO(gri) avoid declared but not used error here
|
||||||
}
|
}
|
||||||
case l > r && (init != nil || r != 1):
|
case l > r && (init != nil || r != 1):
|
||||||
n := s.Names[r]
|
n := s.Names[r]
|
||||||
|
|
|
||||||
|
|
@ -341,6 +341,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
||||||
}
|
}
|
||||||
} else if len(s.Results) > 0 {
|
} else if len(s.Results) > 0 {
|
||||||
check.error(s.Results[0].Pos(), "no result values expected")
|
check.error(s.Results[0].Pos(), "no result values expected")
|
||||||
|
check.use(s.Results...)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.BranchStmt:
|
case *ast.BranchStmt:
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package vardecl
|
package vardecl
|
||||||
|
|
||||||
// Prerequisites.
|
// Prerequisites.
|
||||||
|
import "math"
|
||||||
func f() {}
|
func f() {}
|
||||||
func g() (x, y int) { return }
|
func g() (x, y int) { return }
|
||||||
var m map[string]int
|
var m map[string]int
|
||||||
|
|
@ -147,6 +148,26 @@ func (r T) _(a, b, c int) (u, v, w int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Invalid (unused) expressions must not lead to spurious "declared but not used errors"
|
||||||
|
func _() {
|
||||||
|
var a, b, c int
|
||||||
|
var x, y int
|
||||||
|
x, y = a /* ERROR assignment count mismatch */ , b, c
|
||||||
|
_ = x
|
||||||
|
_ = y
|
||||||
|
}
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
var x int
|
||||||
|
return x /* ERROR no result values expected */
|
||||||
|
return math /* ERROR no result values expected */ .Sin(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _() int {
|
||||||
|
var x, y int
|
||||||
|
return /* ERROR wrong number of return values */ x, y
|
||||||
|
}
|
||||||
|
|
||||||
// Short variable declarations must declare at least one new non-blank variable.
|
// Short variable declarations must declare at least one new non-blank variable.
|
||||||
func _() {
|
func _() {
|
||||||
_ := /* ERROR no new variables */ 0
|
_ := /* ERROR no new variables */ 0
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue