Skip to content

Commit 1de3131

Browse files
author
Bryan C. Mills
committed
cmd/go: avoid generating "malformed module path" errors for standard-library paths
If the path looks like it belongs in GOROOT/src and isn't there, we should mention that in the error message — instead of the fact that the path is not a valid module path, which the user likely already knows. Fixes #34769 Fixes #35734 Change-Id: I3589336d102e420a5ad3bf246816e29f3cbe6d71 Reviewed-on: https://go-review.googlesource.com/c/go/+/210339 Run-TryBot: Bryan C. Mills <[email protected]> Reviewed-by: Jay Conrod <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent bf86582 commit 1de3131

File tree

5 files changed

+84
-12
lines changed

5 files changed

+84
-12
lines changed

src/cmd/go/internal/modload/import.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"cmd/go/internal/modfetch"
2121
"cmd/go/internal/par"
2222
"cmd/go/internal/search"
23-
"cmd/go/internal/str"
2423

2524
"golang.org/x/mod/module"
2625
"golang.org/x/mod/semver"
@@ -40,7 +39,7 @@ var _ load.ImportPathError = (*ImportMissingError)(nil)
4039

4140
func (e *ImportMissingError) Error() string {
4241
if e.Module.Path == "" {
43-
if str.HasPathPrefix(e.Path, "cmd") {
42+
if search.IsStandardImportPath(e.Path) {
4443
return fmt.Sprintf("package %s is not in GOROOT (%s)", e.Path, filepath.Join(cfg.GOROOT, "src", e.Path))
4544
}
4645
if i := load.ImportPathError(nil); errors.As(e.QueryErr, &i) {
@@ -121,8 +120,8 @@ func Import(path string) (m module.Version, dir string, err error) {
121120
}
122121

123122
// Is the package in the standard library?
124-
if search.IsStandardImportPath(path) &&
125-
goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
123+
pathIsStd := search.IsStandardImportPath(path)
124+
if pathIsStd && goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
126125
if targetInGorootSrc {
127126
if dir, ok := dirInModule(path, targetPrefix, ModRoot(), true); ok {
128127
return Target, dir, nil
@@ -131,9 +130,6 @@ func Import(path string) (m module.Version, dir string, err error) {
131130
dir := filepath.Join(cfg.GOROOT, "src", path)
132131
return module.Version{}, dir, nil
133132
}
134-
if str.HasPathPrefix(path, "cmd") {
135-
return module.Version{}, "", &ImportMissingError{Path: path}
136-
}
137133

138134
// -mod=vendor is special.
139135
// Everything must be in the main module or the main module's vendor directory.
@@ -187,6 +183,12 @@ func Import(path string) (m module.Version, dir string, err error) {
187183
// Look up module containing the package, for addition to the build list.
188184
// Goal is to determine the module, download it to dir, and return m, dir, ErrMissing.
189185
if cfg.BuildMod == "readonly" {
186+
if pathIsStd {
187+
// 'import lookup disabled' would be confusing for standard-library paths,
188+
// since the user probably isn't expecting us to look up a module for
189+
// those anyway.
190+
return module.Version{}, "", &ImportMissingError{Path: path}
191+
}
190192
return module.Version{}, "", fmt.Errorf("import lookup disabled by -mod=%s", cfg.BuildMod)
191193
}
192194
if modRoot == "" && !allowMissingModuleImports {
@@ -253,6 +255,17 @@ func Import(path string) (m module.Version, dir string, err error) {
253255
}
254256
}
255257

258+
if pathIsStd {
259+
// This package isn't in the standard library, isn't in any module already
260+
// in the build list, and isn't in any other module that the user has
261+
// shimmed in via a "replace" directive.
262+
// Moreover, the import path is reserved for the standard library, so
263+
// QueryPackage cannot possibly find a module containing this package.
264+
//
265+
// Instead of trying QueryPackage, report an ImportMissingError immediately.
266+
return module.Version{}, "", &ImportMissingError{Path: path}
267+
}
268+
256269
candidates, err := QueryPackage(path, "latest", Allowed)
257270
if err != nil {
258271
if errors.Is(err, os.ErrNotExist) {

src/cmd/go/testdata/script/mod_bad_domain.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ env GO111MODULE=on
22

33
# explicit get should report errors about bad names
44
! go get appengine
5-
stderr 'malformed module path "appengine": missing dot in first path element'
5+
stderr '^go get appengine: package appengine is not in GOROOT \(.*\)$'
66
! go get x/y.z
77
stderr 'malformed module path "x/y.z": missing dot in first path element'
88

9+
# 'go list -m' should report errors about module names, never GOROOT.
10+
! go list -m -versions appengine
11+
stderr 'malformed module path "appengine": missing dot in first path element'
12+
! go list -m -versions x/y.z
13+
stderr 'malformed module path "x/y.z": missing dot in first path element'
14+
915
# build should report all unsatisfied imports,
1016
# but should be more definitive about non-module import paths
1117
! go build ./useappengine

src/cmd/go/testdata/script/mod_build_info_err.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Verifies golang.org/issue/34393.
33

44
go list -e -deps -f '{{with .Error}}{{.Pos}}: {{.Err}}{{end}}' ./main
5-
stdout 'bad[/\\]bad.go:3:8: malformed module path "string": missing dot in first path element'
5+
stdout 'bad[/\\]bad.go:3:8: malformed module path "🐧.example.com/string": invalid char ''🐧'''
66

77
-- go.mod --
88
module m
@@ -19,4 +19,4 @@ func main() {}
1919
-- bad/bad.go --
2020
package bad
2121

22-
import _ "string"
22+
import _ "🐧.example.com/string"
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
env GO111MODULE=on
2+
3+
# Regression test for https://golang.org/issue/34769.
4+
# Missing standard-library imports should refer to GOROOT rather than
5+
# complaining about a malformed module path.
6+
# This is especially important when GOROOT is set incorrectly,
7+
# since such an error will occur for every package in std.
8+
9+
# Building a nonexistent std package directly should fail usefully.
10+
11+
! go build -mod=readonly nonexist
12+
! stderr 'import lookup disabled'
13+
! stderr 'missing dot'
14+
stderr '^can''t load package: package nonexist is not in GOROOT \('$GOROOT'[/\\]src[/\\]nonexist\)$'
15+
16+
! go build nonexist
17+
! stderr 'import lookup disabled'
18+
! stderr 'missing dot'
19+
stderr '^can''t load package: package nonexist is not in GOROOT \('$GOROOT'[/\\]src[/\\]nonexist\)$'
20+
21+
# Building a nonexistent std package indirectly should also fail usefully.
22+
23+
! go build -mod=readonly ./importnonexist
24+
! stderr 'import lookup disabled'
25+
! stderr 'missing dot'
26+
stderr '^importnonexist[/\\]x.go:2:8: package nonexist is not in GOROOT \('$GOROOT'[/\\]src[/\\]nonexist\)$'
27+
28+
! go build ./importnonexist
29+
! stderr 'import lookup disabled'
30+
! stderr 'missing dot'
31+
stderr '^importnonexist[/\\]x.go:2:8: package nonexist is not in GOROOT \('$GOROOT'[/\\]src[/\\]nonexist\)$'
32+
33+
# Building an *actual* std package should fail if GOROOT is set to something bogus.
34+
35+
[!short] go build ./importjson # Prove that it works when GOROOT is valid.
36+
37+
env GOROOT=$WORK/not-a-valid-goroot
38+
! go build ./importjson
39+
! stderr 'import lookup disabled'
40+
! stderr 'missing dot'
41+
stderr 'importjson[/\\]x.go:2:8: package encoding/json is not in GOROOT \('$WORK'[/\\]not-a-valid-goroot[/\\]src[/\\]encoding[/\\]json\)$'
42+
43+
-- go.mod --
44+
module example.com
45+
go 1.14
46+
-- importnonexist/x.go --
47+
package importnonexist
48+
import _ "nonexist"
49+
-- importjson/x.go --
50+
package importjson
51+
import _ "encoding/json"
52+
-- $WORK/not-a-valid-goroot/README --
53+
This directory is not a valid GOROOT.

src/cmd/go/testdata/script/mod_tidy_error.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ env GO111MODULE=on
44
# 'go mod tidy' and 'go mod vendor' should not hide loading errors.
55

66
! go mod tidy
7-
stderr '^issue27063 imports\n\tnonexist: malformed module path "nonexist": missing dot in first path element'
7+
stderr '^issue27063 imports\n\tnonexist: package nonexist is not in GOROOT \(.*\)'
88
stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
99
stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'
1010

1111
! go mod vendor
12-
stderr '^issue27063 imports\n\tnonexist: malformed module path "nonexist": missing dot in first path element'
12+
stderr '^issue27063 imports\n\tnonexist: package nonexist is not in GOROOT \(.*\)'
1313
stderr '^issue27063 imports\n\tnonexist.example.com: cannot find module providing package nonexist.example.com'
1414
stderr '^issue27063 imports\n\tissue27063/other imports\n\tother.example.com/nonexist: cannot find module providing package other.example.com/nonexist'
1515

0 commit comments

Comments
 (0)