]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: better error messages for field lookup errors
authorRobert Griesemer <gri@golang.org>
Thu, 6 Dec 2018 01:08:27 +0000 (17:08 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 6 Dec 2018 02:43:14 +0000 (02:43 +0000)
- follow wording of cmd/compile more closely
- only print base of a package path to avoid overly long error messages

Fixes #26234.

Change-Id: I47a8c64b3adcf73980cd296a24cf8ac721e5df06
Reviewed-on: https://go-review.googlesource.com/c/152764
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
src/go/types/call.go
src/go/types/errors.go
src/go/types/testdata/issues.src

index 52f1ac31ce1db19090ab61edc9ffc977aa38b054..0ea1623903daebe6f787b1be3a2404af428ec70f 100644 (file)
@@ -374,11 +374,13 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                switch {
                case index != nil:
                        // TODO(gri) should provide actual type where the conflict happens
-                       check.invalidOp(e.Sel.Pos(), "ambiguous selector %s", sel)
+                       check.errorf(e.Sel.Pos(), "ambiguous selector %s", sel)
                case indirect:
-                       check.invalidOp(e.Sel.Pos(), "%s is not in method set of %s", sel, x.typ)
+                       // TODO(gri) be more specific with this error message
+                       check.errorf(e.Sel.Pos(), "%s is not in method set of %s", sel, x.typ)
                default:
-                       check.invalidOp(e.Sel.Pos(), "%s has no field or method %s", x, sel)
+                       // TODO(gri) should check if capitalization of sel matters and provide better error message in that case
+                       check.errorf(e.Sel.Pos(), "%s.%s undefined (type %s has no field or method %s)", x.expr, sel, x.typ, sel)
                }
                goto Error
        }
@@ -392,7 +394,8 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                // method expression
                m, _ := obj.(*Func)
                if m == nil {
-                       check.invalidOp(e.Sel.Pos(), "%s has no method %s", x, sel)
+                       // TODO(gri) should check if capitalization of sel matters and provide better error message in that case
+                       check.errorf(e.Sel.Pos(), "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel)
                        goto Error
                }
 
index 4c8d8537ee6a6e2989d6716e45117077814f203a..68c96c037eacf6f3cf22344df9e2dbef3221746d 100644 (file)
@@ -10,6 +10,7 @@ import (
        "fmt"
        "go/ast"
        "go/token"
+       "path"
        "strings"
 )
 
@@ -25,7 +26,7 @@ func unreachable() {
 
 func (check *Checker) qualifier(pkg *Package) string {
        if pkg != check.pkg {
-               return pkg.path
+               return path.Base(pkg.path) // avoid excessively long path names in error messages
        }
        return ""
 }
index 8260f58519d012c5cafde1c4181adbdae73141ea..d02030110935ec4f79fd50f2451c1c8b50f518f1 100644 (file)
@@ -5,6 +5,7 @@
 package issues
 
 import "fmt"
+import syn "cmd/compile/internal/syntax"
 
 func issue7035() {
        type T struct{ X int }
@@ -312,4 +313,28 @@ func issue28281d(... /* ERROR can only use ... with final parameter */ int, int)
 func issue28281e(a, b, c  ... /* ERROR can only use ... with final parameter */ int, d int)
 func issue28281f(... /* ERROR can only use ... with final parameter */ int, ... /* ERROR can only use ... with final parameter */ int, int)
 func (... /* ERROR expected type */ TT) f()
-func issue28281g() (... /* ERROR expected type */ TT)
\ No newline at end of file
+func issue28281g() (... /* ERROR expected type */ TT)
+
+// Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output
+func issue26234a(f *syn.File) {
+       // The error message below should refer to the actual package path base (syntax)
+       // not the local package name (syn).
+       f.foo /* ERROR f.foo undefined \(type \*syntax.File has no field or method foo\) */
+}
+
+type T struct {
+       x int
+       E1
+       E2
+}
+
+type E1 struct{ f int }
+type E2 struct{ f int }
+
+func issue26234b(x T) {
+       _ = x.f /* ERROR ambiguous selector f */
+}
+
+func issue26234c() {
+       T.x /* ERROR T.x undefined \(type T has no method x\) */ ()
+}