diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index d7fca8fd2c..309d654987 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -126,6 +126,8 @@ func Import(path string) (m module.Version, dir string, err error) { } dir := filepath.Join(cfg.GOROOT, "src", path) return module.Version{}, dir, nil + } else if pathIsStd && path == cfg.GOROOTsrc { + return module.Version{}, dir, errors.New("directory should not directly contain source files") } // -mod=vendor is special. diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 89d906f194..b28776b81c 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -126,6 +126,12 @@ func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match { // It's not strictly necessary but helpful to keep the checks. if modRoot != "" && dir == modRoot { pkg = targetPrefix + if modRoot == cfg.GOROOTsrc { + // A package in GOROOT/src would have an empty path. + // Keep the path as cfg.GOROOTsrc. We'll report an error in Import. + // See golang.org/issue/36587. + pkg = modRoot + } } else if modRoot != "" && strings.HasPrefix(dir, modRoot+string(filepath.Separator)) && !strings.Contains(dir[len(modRoot):], "@") { suffix := filepath.ToSlash(dir[len(modRoot):]) if strings.HasPrefix(suffix, "/vendor/") { diff --git a/src/cmd/go/testdata/script/list_gofile_in_goroot.txt b/src/cmd/go/testdata/script/list_gofile_in_goroot.txt new file mode 100644 index 0000000000..0a3b128eae --- /dev/null +++ b/src/cmd/go/testdata/script/list_gofile_in_goroot.txt @@ -0,0 +1,46 @@ +# Return an error if the user tries to list a go source file directly in $GOROOT/src. +# Tests golang.org/issue/36587 + +mkdir $WORK/fakegoroot/src +mkdir $WORK/fakegopath/src + +env GOROOT=$WORK/fakegoroot +env GOPATH=$WORK/fakegopath + +cp go.mod $GOROOT/src/go.mod +cp foo.go $GOROOT/src/foo.go + +go env GOROOT +stdout $WORK(/|\\)fakegoroot + +# switch to GOROOT/src +cd $GOROOT/src + +# GO111MODULE=on,GOROOT +env GO111MODULE=on +! go list ./... +stderr 'directory should not directly contain source files' +go list -e . +go list -f '{{if .Error}}{{.Error.Err}}{{end}}' -e ./... +stdout 'directory should not directly contain source files' + +# GO111MODULE=off,GOROOT +env GO111MODULE=off +go list ./... +[!windows] stdout _$WORK/fakegoroot/src +[windows] stdout fakegoroot/src # On windows the ":" in the volume name is mangled + +# switch to GOPATH/src +cp $WORK/gopath/src/foo.go $GOPATH/src/foo.go +cd $GOPATH/src + +# GO111MODULE=off,GOPATH +env GO111MODULE=off +go list ./... + +-- go.mod -- +module g + +go 1.14 +-- foo.go -- +package foo \ No newline at end of file