From 5088b64b07f7e8e93e3cdd3bd438c3b7e696eeae Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 15 May 2017 11:46:05 -0700 Subject: [PATCH] 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/43500 Reviewed-by: Alan Donovan --- src/go/types/call.go | 4 +++- src/go/types/expr.go | 13 +++++++++++++ src/go/types/testdata/issues.src | 21 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/go/types/call.go b/src/go/types/call.go index 7c54baa67a..ffd9629777 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -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) + } } } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index f76da17fe5..7de13f5be6 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -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 } diff --git a/src/go/types/testdata/issues.src b/src/go/types/testdata/issues.src index e44c1c2521..8729555e17 100644 --- a/src/go/types/testdata/issues.src +++ b/src/go/types/testdata/issues.src @@ -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} +} -- 2.50.0