Skip to content

Commit c016133

Browse files
author
Bryan C. Mills
committed
cmd/go/internal/modload: set errors for packages with invalid import paths
Prior to CL 339170, relative errors in module mode resulted in a base.Fatalf from the module loader, which caused unrecoverable errors from 'go list -e' but successfully rejected relative imports (which were never intended to work in module mode in the first place). After that CL, the base.Fatalf is no longer present, but some errors that had triggered that base.Fatalf were no longer diagnosed at all: the module loader left them for the package loader to report, and the package loader assumed that the module loader would report them. Since the module loader already knows that the paths are invalid, it now reports those errors itself. Fixes #51125 Change-Id: I70e5818cfcfeea0ac70e17274427b08a74fd7c13 Reviewed-on: https://go-review.googlesource.com/c/go/+/386176 Trust: Bryan Mills <[email protected]> Run-TryBot: Bryan Mills <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent a289e9c commit c016133

File tree

7 files changed

+80
-25
lines changed

7 files changed

+80
-25
lines changed

src/cmd/compile/internal/test/testdata/ptrsort.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ package main
66
import (
77
"fmt"
88

9-
"./mysort"
9+
"cmd/compile/internal/test/testdata/mysort"
1010
)
1111

1212
type MyString struct {

src/cmd/go/internal/load/pkg.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -819,11 +819,11 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
819819
}
820820
r := resolvedImportCache.Do(importKey, func() any {
821821
var r resolvedImport
822-
if build.IsLocalImport(path) {
822+
if cfg.ModulesEnabled {
823+
r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
824+
} else if build.IsLocalImport(path) {
823825
r.dir = filepath.Join(parentDir, path)
824826
r.path = dirToImportPath(r.dir)
825-
} else if cfg.ModulesEnabled {
826-
r.dir, r.path, r.err = modload.Lookup(parentPath, parentIsStd, path)
827827
} else if mode&ResolveImport != 0 {
828828
// We do our own path resolution, because we want to
829829
// find out the key to use in packageCache without the
@@ -1113,6 +1113,7 @@ func dirAndRoot(path string, dir, root string) (string, string) {
11131113
}
11141114

11151115
if !str.HasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || path != "command-line-arguments" && !build.IsLocalImport(path) && filepath.Join(root, path) != dir {
1116+
debug.PrintStack()
11161117
base.Fatalf("unexpected directory layout:\n"+
11171118
" import path: %s\n"+
11181119
" root: %s\n"+

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,26 @@ func (e *invalidImportError) Unwrap() error {
248248
// return the module, its root directory, and a list of other modules that
249249
// lexically could have provided the package but did not.
250250
func importFromModules(ctx context.Context, path string, rs *Requirements, mg *ModuleGraph) (m module.Version, dir string, altMods []module.Version, err error) {
251+
invalidf := func(format string, args ...interface{}) (module.Version, string, []module.Version, error) {
252+
return module.Version{}, "", nil, &invalidImportError{
253+
importPath: path,
254+
err: fmt.Errorf(format, args...),
255+
}
256+
}
257+
251258
if strings.Contains(path, "@") {
252-
return module.Version{}, "", nil, fmt.Errorf("import path should not have @version")
259+
return invalidf("import path %q should not have @version", path)
253260
}
254261
if build.IsLocalImport(path) {
255-
return module.Version{}, "", nil, fmt.Errorf("relative import not supported")
262+
return invalidf("%q is relative, but relative import paths are not supported in module mode", path)
256263
}
264+
if filepath.IsAbs(path) {
265+
return invalidf("%q is not a package path; see 'go help packages'", path)
266+
}
267+
if search.IsMetaPackage(path) {
268+
return invalidf("%q is not an importable package; see 'go help packages'", path)
269+
}
270+
257271
if path == "C" {
258272
// There's no directory for import "C".
259273
return module.Version{}, "", nil, nil

src/cmd/go/internal/modload/load.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,24 +1675,6 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
16751675

16761676
// load loads an individual package.
16771677
func (ld *loader) load(ctx context.Context, pkg *loadPkg) {
1678-
if strings.Contains(pkg.path, "@") {
1679-
// Leave for error during load.
1680-
return
1681-
}
1682-
if build.IsLocalImport(pkg.path) || filepath.IsAbs(pkg.path) {
1683-
// Leave for error during load.
1684-
// (Module mode does not allow local imports.)
1685-
return
1686-
}
1687-
1688-
if search.IsMetaPackage(pkg.path) {
1689-
pkg.err = &invalidImportError{
1690-
importPath: pkg.path,
1691-
err: fmt.Errorf("%q is not an importable package; see 'go help packages'", pkg.path),
1692-
}
1693-
return
1694-
}
1695-
16961678
var mg *ModuleGraph
16971679
if ld.requirements.pruning == unpruned {
16981680
var err error

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ stderr 'internal'
1010

1111
# Test internal packages outside GOROOT are respected
1212
cd ../testinternal2
13+
env GO111MODULE=off
1314
! go build -v .
1415
stderr 'p\.go:3:8: use of internal package .*internal/w not allowed'
16+
env GO111MODULE=''
1517

1618
[gccgo] skip # gccgo does not have GOROOT
1719
cd ../testinternal
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Regression test for https://go.dev/issue/51125:
2+
# Relative import paths (a holdover from GOPATH) were accidentally allowed in module mode.
3+
4+
cd $WORK
5+
6+
# Relative imports should not be allowed with a go.mod file.
7+
8+
! go run driver.go
9+
stderr '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
10+
11+
go list -e -f '{{with .Error}}{{.}}{{end}}' -deps driver.go
12+
stdout '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
13+
! stderr .
14+
15+
16+
# Relative imports should not be allowed in module mode even without a go.mod file.
17+
rm go.mod
18+
19+
! go run driver.go
20+
stderr '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
21+
22+
go list -e -f '{{with .Error}}{{.}}{{end}}' -deps driver.go
23+
stdout '^driver.go:3:8: "./mypkg" is relative, but relative import paths are not supported in module mode$'
24+
! stderr .
25+
26+
27+
# In GOPATH mode, they're still allowed (but only outside of GOPATH/src).
28+
env GO111MODULE=off
29+
30+
[!short] go run driver.go
31+
32+
go list -deps driver.go
33+
34+
35+
-- $WORK/go.mod --
36+
module example
37+
38+
go 1.17
39+
-- $WORK/driver.go --
40+
package main
41+
42+
import "./mypkg"
43+
44+
func main() {
45+
mypkg.MyFunc()
46+
}
47+
-- $WORK/mypkg/code.go --
48+
package mypkg
49+
50+
import "fmt"
51+
52+
func MyFunc() {
53+
fmt.Println("Hello, world!")
54+
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Relative imports in command line package
22

3+
env GO111MODULE=off
4+
35
# Run tests outside GOPATH.
46
env GOPATH=$WORK/tmp
57

@@ -47,4 +49,4 @@ func TestF1(t *testing.T) {
4749
if F() != p2.F() {
4850
t.Fatal(F())
4951
}
50-
}
52+
}

0 commit comments

Comments
 (0)