Skip to content

Commit b81e01d

Browse files
committed
go/types: print package path in error messages if package name is not unique
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 golang#35895. Change-Id: I33ab8e7adfae1378907c01e33cabda114f65887f Reviewed-on: https://go-review.googlesource.com/c/go/+/209578 Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 5fd7581 commit b81e01d

4 files changed

Lines changed: 29 additions & 5 deletions

File tree

src/go/types/check.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ type Checker struct {
7979
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
8080
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
8181
posMap map[*Interface][]token.Pos // maps interface types to lists of embedded interface positions
82+
pkgCnt map[string]int // counts number of imported packages with a given name (for better error messages)
8283

8384
// information collected during type-checking of a set of package files
8485
// (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
190191
objMap: make(map[Object]*declInfo),
191192
impMap: make(map[importKey]*Package),
192193
posMap: make(map[*Interface][]token.Pos),
194+
pkgCnt: make(map[string]int),
193195
}
194196
}
195197

src/go/types/errors.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"fmt"
1111
"go/ast"
1212
"go/token"
13-
"path"
13+
"strconv"
1414
"strings"
1515
)
1616

@@ -25,8 +25,13 @@ func unreachable() {
2525
}
2626

2727
func (check *Checker) qualifier(pkg *Package) string {
28+
// Qualify the package unless it's the package being type-checked.
2829
if pkg != check.pkg {
29-
return path.Base(pkg.path) // avoid excessively long path names in error messages
30+
// If the same package name was used by multiple packages, display the full path.
31+
if check.pkgCnt[pkg.name] > 1 {
32+
return strconv.Quote(pkg.path)
33+
}
34+
return pkg.name
3035
}
3136
return ""
3237
}

src/go/types/resolver.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
188188
// package should be complete or marked fake, but be cautious
189189
if imp.complete || imp.fake {
190190
check.impMap[key] = imp
191+
check.pkgCnt[imp.name]++
191192
return imp
192193
}
193194

src/go/types/testdata/issues.src

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44

55
package issues
66

7-
import "fmt"
8-
import syn "cmd/compile/internal/syntax"
7+
import (
8+
"fmt"
9+
syn "cmd/compile/internal/syntax"
10+
t1 "text/template"
11+
t2 "html/template"
12+
)
913

1014
func issue7035() {
1115
type T struct{ X int }
@@ -316,7 +320,7 @@ func issue28281g() (... /* ERROR expected type */ TT)
316320

317321
// Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output
318322
func issue26234a(f *syn.File) {
319-
// The error message below should refer to the actual package path base (syntax)
323+
// The error message below should refer to the actual package name (syntax)
320324
// not the local package name (syn).
321325
f.foo /* ERROR f.foo undefined \(type \*syntax.File has no field or method foo\) */
322326
}
@@ -337,3 +341,15 @@ func issue26234b(x T) {
337341
func issue26234c() {
338342
T.x /* ERROR T.x undefined \(type T has no method x\) */ ()
339343
}
344+
345+
func issue35895() {
346+
// T is defined in this package, don't qualify its name with the package name.
347+
var _ T = 0 // ERROR cannot convert 0 \(untyped int constant\) to T
348+
349+
// There is only one package with name syntax imported, only use the (global) package name in error messages.
350+
var _ *syn.File = 0 // ERROR cannot convert 0 \(untyped int constant\) to \*syntax.File
351+
352+
// Because both t1 and t2 have the same global package name (template),
353+
// qualify packages with full path name in this case.
354+
var _ t1.Template = t2 /* ERROR cannot use .* \(value of type "html/template".Template\) as "text/template".Template */ .Template{}
355+
}

0 commit comments

Comments
 (0)