]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: fewer spurious "declared but not used" follow-on errors
authorRobert Griesemer <gri@golang.org>
Mon, 15 May 2017 18:46:05 +0000 (11:46 -0700)
committerRobert Griesemer <gri@golang.org>
Mon, 15 May 2017 21:15:06 +0000 (21:15 +0000)
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 <adonovan@google.com>
src/go/types/call.go
src/go/types/expr.go
src/go/types/testdata/issues.src

index 7c54baa67acc4b8102a97ff2d5f6e8e27eb61dd2..ffd962977751259d2543ad905662f35464c8be3e 100644 (file)
@@ -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)
+               }
        }
 }
 
index f76da17fe53360877a85afbc2c7eabd22b06b6be..7de13f5be6f00bc117c0eede133ad97bc7c716d6 100644 (file)
@@ -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
                }
 
index e44c1c2521aaef6cad4319867e1f6e008c1667f1..8729555e175546bc0a9847cd1d5a8023ca13fd50 100644 (file)
@@ -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}
+}