Commit 5088b64b authored by Robert Griesemer's avatar Robert Griesemer

go/types: fewer spurious "declared but not used" follow-on errors

Mark variables as used even when they appear within an expression
context which we can't type-check; e.g., because the expression is
erroneous, or comes from an import "C" declaration.

Fixes #20358.

Change-Id: Ib28cc78d3867c597c7a1ace54de09ada02f5b33a
Reviewed-on: https://go-review.googlesource.com/43500Reviewed-by: 's avatarAlan Donovan <adonovan@google.com>
parent 27da3ba5
......@@ -93,7 +93,9 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind {
func (check *Checker) use(arg ...ast.Expr) {
var x operand
for _, e := range arg {
check.rawExpr(&x, e, nil)
if e != nil { // be safe
check.rawExpr(&x, e, nil)
}
}
}
......
......@@ -1161,6 +1161,17 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
}
default:
// when "using" all elements unpack KeyValueExpr
// explicitly because check.use doesn't accept them
for _, e := range e.Elts {
if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
// Ideally, we should also "use" kv.Key but we can't know
// if it's an externally defined struct key or not. Going
// forward anyway can lead to other errors. Give up instead.
e = kv.Value
}
check.use(e)
}
// if utyp is invalid, an error was reported before
if utyp != Typ[Invalid] {
check.errorf(e.Pos(), "invalid composite literal type %s", typ)
......@@ -1182,6 +1193,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case *ast.IndexExpr:
check.expr(x, e.X)
if x.mode == invalid {
check.use(e.Index)
goto Error
}
......@@ -1251,6 +1263,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
case *ast.SliceExpr:
check.expr(x, e.X)
if x.mode == invalid {
check.use(e.Low, e.High, e.Max)
goto Error
}
......
......@@ -186,3 +186,24 @@ func issue15755() {
_ = u
_ = v
}
// Test that we don't get "declared but not used"
// errors in the context of invalid/C objects.
func issue20358() {
var F C /* ERROR "undeclared" */ .F
var A C /* ERROR "undeclared" */ .A
var S C /* ERROR "undeclared" */ .S
type T C /* ERROR "undeclared" */ .T
type P C /* ERROR "undeclared" */ .P
// these variables must be "used" even though
// the LHS expressions/types below in which
// context they are used are unknown/invalid
var f, a, s1, s2, s3, t, p int
_ = F(f)
_ = A[a]
_ = S[s1:s2:s3]
_ = T{t}
_ = P{f: p}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment