]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types: print package path in error messages if package name is not unique
authorRobert Griesemer <gri@golang.org>
Mon, 2 Dec 2019 17:38:03 +0000 (09:38 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 6 Dec 2019 03:52:48 +0000 (03:52 +0000)
Change package qualification to print the full package path for packages
that have non-unique names (that is, where multiple different packages
have the same name). Use the package name as qualifier in all other cases
(but don't print any qualification if we're talking about the package
being type-checked).

This matches the behavior of the compiler.

Fixes #35895.

Change-Id: I33ab8e7adfae1378907c01e33cabda114f65887f
Reviewed-on: https://go-review.googlesource.com/c/go/+/209578
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/go/types/check.go
src/go/types/errors.go
src/go/types/resolver.go
src/go/types/testdata/issues.src

index eec33057de5fb2056e90751bb2c15a10b30daf8b..b599df1c50d845d9f1ec9d085d1e82abf5ad91f2 100644 (file)
@@ -79,6 +79,7 @@ type Checker struct {
        objMap map[Object]*declInfo       // maps package-level objects and (non-interface) methods to declaration info
        impMap map[importKey]*Package     // maps (import path, source directory) to (complete or fake) package
        posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions
+       pkgCnt map[string]int             // counts number of imported packages with a given name (for better error messages)
 
        // information collected during type-checking of a set of package files
        // (initialized by Files, valid only for the duration of check.Files;
@@ -190,6 +191,7 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
                objMap: make(map[Object]*declInfo),
                impMap: make(map[importKey]*Package),
                posMap: make(map[*Interface][]token.Pos),
+               pkgCnt: make(map[string]int),
        }
 }
 
index 23f2611b486919c4a91756a8db01aaf4a6200a10..91b077163c403f1080a09e69ac3c8e5c3f817595 100644 (file)
@@ -10,7 +10,7 @@ import (
        "fmt"
        "go/ast"
        "go/token"
-       "path"
+       "strconv"
        "strings"
 )
 
@@ -25,8 +25,13 @@ func unreachable() {
 }
 
 func (check *Checker) qualifier(pkg *Package) string {
+       // Qualify the package unless it's the package being type-checked.
        if pkg != check.pkg {
-               return path.Base(pkg.path) // avoid excessively long path names in error messages
+               // If the same package name was used by multiple packages, display the full path.
+               if check.pkgCnt[pkg.name] > 1 {
+                       return strconv.Quote(pkg.path)
+               }
+               return pkg.name
        }
        return ""
 }
index d66a5428ff7a1ff896c547c9d759442e1c8ac83a..839d076e361447223b7c821ad07fe07128dccc33 100644 (file)
@@ -188,6 +188,7 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
        // package should be complete or marked fake, but be cautious
        if imp.complete || imp.fake {
                check.impMap[key] = imp
+               check.pkgCnt[imp.name]++
                return imp
        }
 
index 5ddf6e0e71c4babc70471b7ec7065f22e2fefb8c..fe2407999c5e9e4208467fc3733e316f3c98e021 100644 (file)
@@ -4,8 +4,12 @@
 
 package issues
 
-import "fmt"
-import syn "cmd/compile/internal/syntax"
+import (
+       "fmt"
+       syn "cmd/compile/internal/syntax"
+       t1 "text/template"
+       t2 "html/template"
+)
 
 func issue7035() {
        type T struct{ X int }
@@ -316,7 +320,7 @@ 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)
+       // The error message below should refer to the actual package name (syntax)
        // not the local package name (syn).
        f.foo /* ERROR f.foo undefined \(type \*syntax.File has no field or method foo\) */
 }
@@ -337,3 +341,15 @@ func issue26234b(x T) {
 func issue26234c() {
        T.x /* ERROR T.x undefined \(type T has no method x\) */ ()
 }
+
+func issue35895() {
+       // T is defined in this package, don't qualify its name with the package name.
+       var _ T = 0 // ERROR cannot convert 0 \(untyped int constant\) to T
+
+       // There is only one package with name syntax imported, only use the (global) package name in error messages.
+       var _ *syn.File = 0 // ERROR cannot convert 0 \(untyped int constant\) to \*syntax.File
+
+       // Because both t1 and t2 have the same global package name (template),
+       // qualify packages with full path name in this case.
+       var _ t1.Template = t2 /* ERROR cannot use .* \(value of type "html/template".Template\) as "text/template".Template */ .Template{}
+}
\ No newline at end of file