Update prebuilts to go 1.13

From https://ci.android.com/builds/submitted/5859978/darwin_mac/latest/go.zip

Test: m blueprint_tools
Change-Id: I6f37742484ee4268b6a43e4cf6d818e95f151145
diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go
index 2a8be90..ff42516 100644
--- a/src/cmd/go/internal/modload/build.go
+++ b/src/cmd/go/internal/modload/build.go
@@ -12,6 +12,7 @@
 	"cmd/go/internal/modinfo"
 	"cmd/go/internal/module"
 	"cmd/go/internal/search"
+	"cmd/go/internal/semver"
 	"encoding/hex"
 	"fmt"
 	"internal/goroot"
@@ -38,9 +39,6 @@
 		if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
 			return filepath.Join(cfg.GOROOT, "src", path)
 		}
-		if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, "vendor/"+path) {
-			return filepath.Join(cfg.GOROOT, "src/vendor", path)
-		}
 	}
 	return ""
 }
@@ -77,13 +75,15 @@
 
 // addUpdate fills in m.Update if an updated version is available.
 func addUpdate(m *modinfo.ModulePublic) {
-	if m.Version != "" {
-		if info, err := Query(m.Path, "latest", Allowed); err == nil && info.Version != m.Version {
-			m.Update = &modinfo.ModulePublic{
-				Path:    m.Path,
-				Version: info.Version,
-				Time:    &info.Time,
-			}
+	if m.Version == "" {
+		return
+	}
+
+	if info, err := Query(m.Path, "upgrade", m.Version, Allowed); err == nil && semver.Compare(info.Version, m.Version) > 0 {
+		m.Update = &modinfo.ModulePublic{
+			Path:    m.Path,
+			Version: info.Version,
+			Time:    &info.Time,
 		}
 	}
 }
@@ -127,7 +127,7 @@
 	// complete fills in the extra fields in m.
 	complete := func(m *modinfo.ModulePublic) {
 		if m.Version != "" {
-			if q, err := Query(m.Path, m.Version, nil); err != nil {
+			if q, err := Query(m.Path, m.Version, "", nil); err != nil {
 				m.Error = &modinfo.ModuleError{Err: err.Error()}
 			} else {
 				m.Version = q.Version
@@ -219,7 +219,7 @@
 		if r.Path == "" {
 			h = "\t" + modfetch.Sum(mod)
 		}
-		fmt.Fprintf(&buf, "dep\t%s\t%s%s\n", mod.Path, mod.Version, h)
+		fmt.Fprintf(&buf, "dep\t%s\t%s%s\n", mod.Path, mv, h)
 		if r.Path != "" {
 			fmt.Fprintf(&buf, "=>\t%s\t%s\t%s\n", r.Path, r.Version, modfetch.Sum(r))
 		}
@@ -250,21 +250,15 @@
 }
 
 func ModInfoProg(info string) []byte {
-	// Inject a variable with the debug information as runtime/debug.modinfo,
+	// Inject a variable with the debug information as runtime.modinfo,
 	// but compile it in package main so that it is specific to the binary.
-	//
 	// The variable must be a literal so that it will have the correct value
 	// before the initializer for package main runs.
 	//
-	// We also want the value to be present even if runtime/debug.modinfo is
-	// otherwise unused in the rest of the program. Reading it in an init function
-	// suffices for now.
-
+	// The runtime startup code refers to the variable, which keeps it live in all binaries.
 	return []byte(fmt.Sprintf(`package main
 import _ "unsafe"
-//go:linkname __debug_modinfo__ runtime/debug.modinfo
+//go:linkname __debug_modinfo__ runtime.modinfo
 var __debug_modinfo__ = %q
-var keepalive_modinfo = __debug_modinfo__
-func init() { keepalive_modinfo = __debug_modinfo__ }
 	`, string(infoStart)+info+string(infoEnd)))
 }
diff --git a/src/cmd/go/internal/modload/help.go b/src/cmd/go/internal/modload/help.go
index d9c8ae4..1927c1c 100644
--- a/src/cmd/go/internal/modload/help.go
+++ b/src/cmd/go/internal/modload/help.go
@@ -19,34 +19,28 @@
 Modules replace the old GOPATH-based approach to specifying
 which source files are used in a given build.
 
-Preliminary module support
+Module support
 
-Go 1.11 includes preliminary support for Go modules,
-including a new module-aware 'go get' command.
-We intend to keep revising this support, while preserving compatibility,
-until it can be declared official (no longer preliminary),
-and then at a later point we may remove support for work
-in GOPATH and the old 'go get' command.
+Go 1.13 includes support for Go modules. Module-aware mode is active by default
+whenever a go.mod file is found in, or in a parent of, the current directory.
 
-The quickest way to take advantage of the new Go 1.11 module support
-is to check out your repository into a directory outside GOPATH/src,
-create a go.mod file (described in the next section) there, and run
+The quickest way to take advantage of module support is to check out your
+repository, create a go.mod file (described in the next section) there, and run
 go commands from within that file tree.
 
-For more fine-grained control, the module support in Go 1.11 respects
+For more fine-grained control, Go 1.13 continues to respect
 a temporary environment variable, GO111MODULE, which can be set to one
 of three string values: off, on, or auto (the default).
-If GO111MODULE=off, then the go command never uses the
-new module support. Instead it looks in vendor directories and GOPATH
-to find dependencies; we now refer to this as "GOPATH mode."
 If GO111MODULE=on, then the go command requires the use of modules,
-never consulting GOPATH. We refer to this as the command being
-module-aware or running in "module-aware mode".
-If GO111MODULE=auto or is unset, then the go command enables or
-disables module support based on the current directory.
-Module support is enabled only when the current directory is outside
-GOPATH/src and itself contains a go.mod file or is below a directory
-containing a go.mod file.
+never consulting GOPATH. We refer to this as the command
+being module-aware or running in "module-aware mode".
+If GO111MODULE=off, then the go command never uses
+module support. Instead it looks in vendor directories and GOPATH
+to find dependencies; we now refer to this as "GOPATH mode."
+If GO111MODULE=auto or is unset, then the go command enables or disables
+module support based on the current directory.
+Module support is enabled only when the current directory contains a
+go.mod file or is below a directory containing a go.mod file.
 
 In module-aware mode, GOPATH no longer defines the meaning of imports
 during a build, but it still stores downloaded dependencies (in GOPATH/pkg/mod)
@@ -237,12 +231,25 @@
 The string "latest" matches the latest available tagged version,
 or else the underlying source repository's latest untagged revision.
 
-A revision identifier for the underlying source repository,
-such as a commit hash prefix, revision tag, or branch name,
-selects that specific code revision. If the revision is
-also tagged with a semantic version, the query evaluates to
-that semantic version. Otherwise the query evaluates to a
-pseudo-version for the commit.
+The string "upgrade" is like "latest", but if the module is
+currently required at a later version than the version "latest"
+would select (for example, a newer pre-release version), "upgrade"
+will select the later version instead.
+
+The string "patch" matches the latest available tagged version
+of a module with the same major and minor version numbers as the
+currently required version. If no version is currently required,
+"patch" is equivalent to "latest".
+
+A revision identifier for the underlying source repository, such as
+a commit hash prefix, revision tag, or branch name, selects that
+specific code revision. If the revision is also tagged with a
+semantic version, the query evaluates to that semantic version.
+Otherwise the query evaluates to a pseudo-version for the commit.
+Note that branches and tags with names that are matched by other
+query syntax cannot be selected this way. For example, the query
+"v2" means the latest version starting with "v2", not the branch
+named "v2".
 
 All queries prefer release versions to pre-release versions.
 For example, "<v1.2.3" will prefer to return "v1.2.2"
@@ -337,26 +344,35 @@
 
 Module downloading and verification
 
-The go command maintains, in the main module's root directory alongside
-go.mod, a file named go.sum containing the expected cryptographic checksums
-of the content of specific module versions. Each time a dependency is
-used, its checksum is added to go.sum if missing or else required to match
-the existing entry in go.sum.
+The go command can fetch modules from a proxy or connect to source control
+servers directly, according to the setting of the GOPROXY environment
+variable (see 'go help env'). The default setting for GOPROXY is
+"https://proxy.golang.org,direct", which means to try the
+Go module mirror run by Google and fall back to a direct connection
+if the proxy reports that it does not have the module (HTTP error 404 or 410).
+See https://proxy.golang.org/privacy for the service's privacy policy.
+If GOPROXY is set to the string "direct", downloads use a direct connection
+to source control servers. Setting GOPROXY to "off" disallows downloading
+modules from any source. Otherwise, GOPROXY is expected to be a comma-separated
+list of the URLs of module proxies, in which case the go command will fetch
+modules from those proxies. For each request, the go command tries each proxy
+in sequence, only moving to the next if the current proxy returns a 404 or 410
+HTTP response. The string "direct" may appear in the proxy list,
+to cause a direct connection to be attempted at that point in the search.
+Any proxies listed after "direct" are never consulted.
 
-The go command maintains a cache of downloaded packages and computes
-and records the cryptographic checksum of each package at download time.
-In normal operation, the go command checks these pre-computed checksums
-against the main module's go.sum file, instead of recomputing them on
-each command invocation. The 'go mod verify' command checks that
-the cached copies of module downloads still match both their recorded
-checksums and the entries in go.sum.
+The GOPRIVATE and GONOPROXY environment variables allow bypassing
+the proxy for selected modules. See 'go help module-private' for details.
 
-The go command can fetch modules from a proxy instead of connecting
-to source control systems directly, according to the setting of the GOPROXY
-environment variable.
+No matter the source of the modules, the go command checks downloads against
+known checksums, to detect unexpected changes in the content of any specific
+module version from one day to the next. This check first consults the current
+module's go.sum file but falls back to the Go checksum database, controlled by
+the GOSUMDB and GONOSUMDB environment variables. See 'go help module-auth'
+for details.
 
-See 'go help goproxy' for details about the proxy and also the format of
-the cached downloaded packages.
+See 'go help goproxy' for details about the proxy protocol and also
+the format of the cached downloaded packages.
 
 Modules and vendoring
 
@@ -461,5 +477,12 @@
 commands that load packages also use and therefore update go.mod,
 including go build, go get, go install, go list, go test, go mod graph,
 go mod tidy, and go mod why.
+
+The expected language version, set by the go directive, determines
+which language features are available when compiling the module.
+Language features available in that version will be available for use.
+Language features removed in earlier versions, or added in later versions,
+will not be available. Note that the language version does not affect
+build tags, which are determined by the Go release being used.
 	`,
 }
diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go
index 3210e16..70add35 100644
--- a/src/cmd/go/internal/modload/import.go
+++ b/src/cmd/go/internal/modload/import.go
@@ -18,20 +18,27 @@
 
 	"cmd/go/internal/cfg"
 	"cmd/go/internal/modfetch"
-	"cmd/go/internal/modfetch/codehost"
 	"cmd/go/internal/module"
 	"cmd/go/internal/par"
 	"cmd/go/internal/search"
 	"cmd/go/internal/semver"
+	"cmd/go/internal/str"
 )
 
 type ImportMissingError struct {
 	ImportPath string
 	Module     module.Version
+
+	// newMissingVersion is set to a newer version of Module if one is present
+	// in the build list. When set, we can't automatically upgrade.
+	newMissingVersion string
 }
 
 func (e *ImportMissingError) Error() string {
 	if e.Module.Path == "" {
+		if str.HasPathPrefix(e.ImportPath, "cmd") {
+			return fmt.Sprintf("package %s is not in GOROOT (%s)", e.ImportPath, filepath.Join(cfg.GOROOT, "src", e.ImportPath))
+		}
 		return "cannot find module providing package " + e.ImportPath
 	}
 	return "missing module for import: " + e.Module.Path + "@" + e.Module.Version + " provides " + e.ImportPath
@@ -61,17 +68,24 @@
 	}
 
 	// Is the package in the standard library?
-	if search.IsStandardImportPath(path) {
-		if goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
-			dir := filepath.Join(cfg.GOROOT, "src", path)
-			return module.Version{}, dir, nil
+	if search.IsStandardImportPath(path) &&
+		goroot.IsStandardPackage(cfg.GOROOT, cfg.BuildContext.Compiler, path) {
+		if targetInGorootSrc {
+			if dir, ok := dirInModule(path, targetPrefix, ModRoot(), true); ok {
+				return Target, dir, nil
+			}
 		}
+		dir := filepath.Join(cfg.GOROOT, "src", path)
+		return module.Version{}, dir, nil
+	}
+	if str.HasPathPrefix(path, "cmd") {
+		return module.Version{}, "", &ImportMissingError{ImportPath: path}
 	}
 
 	// -mod=vendor is special.
 	// Everything must be in the main module or the main module's vendor directory.
 	if cfg.BuildMod == "vendor" {
-		mainDir, mainOK := dirInModule(path, Target.Path, ModRoot(), true)
+		mainDir, mainOK := dirInModule(path, targetPrefix, ModRoot(), true)
 		vendorDir, vendorOK := dirInModule(path, "", filepath.Join(ModRoot(), "vendor"), false)
 		if mainOK && vendorOK {
 			return module.Version{}, "", fmt.Errorf("ambiguous import: found %s in multiple directories:\n\t%s\n\t%s", path, mainDir, vendorDir)
@@ -178,14 +192,37 @@
 		}
 	}
 
-	m, _, err = QueryPackage(path, "latest", Allowed)
+	candidates, err := QueryPackage(path, "latest", Allowed)
 	if err != nil {
-		if _, ok := err.(*codehost.VCSError); ok {
+		if errors.Is(err, os.ErrNotExist) {
+			// Return "cannot find module providing package […]" instead of whatever
+			// low-level error QueryPackage produced.
+			return module.Version{}, "", &ImportMissingError{ImportPath: path}
+		} else {
 			return module.Version{}, "", err
 		}
-		return module.Version{}, "", &ImportMissingError{ImportPath: path}
 	}
-	return m, "", &ImportMissingError{ImportPath: path, Module: m}
+	m = candidates[0].Mod
+	newMissingVersion := ""
+	for _, c := range candidates {
+		cm := c.Mod
+		for _, bm := range buildList {
+			if bm.Path == cm.Path && semver.Compare(bm.Version, cm.Version) > 0 {
+				// QueryPackage proposed that we add module cm to provide the package,
+				// but we already depend on a newer version of that module (and we don't
+				// have the package).
+				//
+				// This typically happens when a package is present at the "@latest"
+				// version (e.g., v1.0.0) of a module, but we have a newer version
+				// of the same module in the build list (e.g., v1.0.1-beta), and
+				// the package is not present there.
+				m = cm
+				newMissingVersion = bm.Version
+				break
+			}
+		}
+	}
+	return m, "", &ImportMissingError{ImportPath: path, Module: m, newMissingVersion: newMissingVersion}
 }
 
 // maybeInModule reports whether, syntactically,
@@ -229,8 +266,8 @@
 	if isLocal {
 		for d := dir; d != mdir && len(d) > len(mdir); {
 			haveGoMod := haveGoModCache.Do(d, func() interface{} {
-				_, err := os.Stat(filepath.Join(d, "go.mod"))
-				return err == nil
+				fi, err := os.Stat(filepath.Join(d, "go.mod"))
+				return err == nil && !fi.IsDir()
 			}).(bool)
 
 			if haveGoMod {
diff --git a/src/cmd/go/internal/modload/import_test.go b/src/cmd/go/internal/modload/import_test.go
index 9422a3d..c6ade5d 100644
--- a/src/cmd/go/internal/modload/import_test.go
+++ b/src/cmd/go/internal/modload/import_test.go
@@ -21,7 +21,7 @@
 	},
 	{
 		path: "golang.org/x/net",
-		err:  "cannot find module providing package golang.org/x/net",
+		err:  "module golang.org/x/net@.* found, but does not contain package golang.org/x/net",
 	},
 	{
 		path: "golang.org/x/text",
@@ -43,6 +43,7 @@
 
 func TestImport(t *testing.T) {
 	testenv.MustHaveExternalNetwork(t)
+	testenv.MustHaveExecPath(t, "git")
 
 	for _, tt := range importTests {
 		t.Run(strings.ReplaceAll(tt.path, "/", "_"), func(t *testing.T) {
diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go
index 22d14cc..807ce8d 100644
--- a/src/cmd/go/internal/modload/init.go
+++ b/src/cmd/go/internal/modload/init.go
@@ -6,6 +6,18 @@
 
 import (
 	"bytes"
+	"encoding/json"
+	"fmt"
+	"go/build"
+	"internal/lazyregexp"
+	"io/ioutil"
+	"os"
+	"path"
+	"path/filepath"
+	"runtime/debug"
+	"strconv"
+	"strings"
+
 	"cmd/go/internal/base"
 	"cmd/go/internal/cache"
 	"cmd/go/internal/cfg"
@@ -18,22 +30,11 @@
 	"cmd/go/internal/mvs"
 	"cmd/go/internal/renameio"
 	"cmd/go/internal/search"
-	"encoding/json"
-	"fmt"
-	"go/build"
-	"io/ioutil"
-	"os"
-	"path"
-	"path/filepath"
-	"regexp"
-	"runtime/debug"
-	"strconv"
-	"strings"
 )
 
 var (
 	cwd            string // TODO(bcmills): Is this redundant with base.Cwd?
-	MustUseModules = mustUseModules()
+	mustUseModules = false
 	initialized    bool
 
 	modRoot     string
@@ -42,6 +43,15 @@
 	excluded    map[module.Version]bool
 	Target      module.Version
 
+	// targetPrefix is the path prefix for packages in Target, without a trailing
+	// slash. For most modules, targetPrefix is just Target.Path, but the
+	// standard-library module "std" has an empty prefix.
+	targetPrefix string
+
+	// targetInGorootSrc caches whether modRoot is within GOROOT/src.
+	// The "std" module is special within GOROOT/src, but not otherwise.
+	targetInGorootSrc bool
+
 	gopath string
 
 	CmdModInit   bool   // running 'go mod init'
@@ -69,18 +79,6 @@
 	return filepath.Join(gopath, "bin")
 }
 
-// mustUseModules reports whether we are invoked as vgo
-// (as opposed to go).
-// If so, we only support builds with go.mod files.
-func mustUseModules() bool {
-	name := os.Args[0]
-	name = name[strings.LastIndex(name, "/")+1:]
-	name = name[strings.LastIndex(name, `\`)+1:]
-	return strings.HasPrefix(name, "vgo")
-}
-
-var inGOPATH bool // running in GOPATH/src
-
 // Init determines whether module mode is enabled, locates the root of the
 // current module (if any), sets environment variables for Git subprocesses, and
 // configures the cfg, codehost, load, modfetch, and search packages for use
@@ -91,18 +89,17 @@
 	}
 	initialized = true
 
-	env := os.Getenv("GO111MODULE")
+	env := cfg.Getenv("GO111MODULE")
 	switch env {
 	default:
 		base.Fatalf("go: unknown environment setting GO111MODULE=%s", env)
-	case "", "auto":
-		// leave MustUseModules alone
+	case "auto", "":
+		mustUseModules = false
 	case "on":
-		MustUseModules = true
+		mustUseModules = true
 	case "off":
-		if !MustUseModules {
-			return
-		}
+		mustUseModules = false
+		return
 	}
 
 	// Disable any prompting for passwords by Git.
@@ -138,36 +135,14 @@
 		base.Fatalf("go: %v", err)
 	}
 
-	inGOPATH = false
-	for _, gopath := range filepath.SplitList(cfg.BuildContext.GOPATH) {
-		if gopath == "" {
-			continue
-		}
-		if search.InDir(cwd, filepath.Join(gopath, "src")) != "" {
-			inGOPATH = true
-			break
-		}
-	}
-
-	if inGOPATH && !MustUseModules {
-		if CmdModInit {
-			die() // Don't init a module that we're just going to ignore.
-		}
-		// No automatic enabling in GOPATH.
-		if root, _ := FindModuleRoot(cwd, "", false); root != "" {
-			cfg.GoModInGOPATH = filepath.Join(root, "go.mod")
-		}
-		return
-	}
-
 	if CmdModInit {
 		// Running 'go mod init': go.mod will be created in current directory.
 		modRoot = cwd
 	} else {
-		modRoot, _ = FindModuleRoot(cwd, "", MustUseModules)
+		modRoot = findModuleRoot(cwd)
 		if modRoot == "" {
-			if !MustUseModules {
-				// GO111MODULE is 'auto' (or unset), and we can't find a module root.
+			if !mustUseModules {
+				// GO111MODULE is 'auto', and we can't find a module root.
 				// Stay in GOPATH mode.
 				return
 			}
@@ -254,9 +229,11 @@
 func init() {
 	load.ModInit = Init
 
-	// Set modfetch.PkgMod unconditionally, so that go clean -modcache can run even without modules enabled.
+	// Set modfetch.PkgMod and codehost.WorkRoot unconditionally,
+	// so that go clean -modcache and go mod download can run even without modules enabled.
 	if list := filepath.SplitList(cfg.BuildContext.GOPATH); len(list) > 0 && list[0] != "" {
 		modfetch.PkgMod = filepath.Join(list[0], "pkg/mod")
+		codehost.WorkRoot = filepath.Join(list[0], "pkg/mod/cache/vcs")
 	}
 }
 
@@ -266,7 +243,7 @@
 // (usually through MustModRoot).
 func Enabled() bool {
 	Init()
-	return modRoot != "" || MustUseModules
+	return modRoot != "" || mustUseModules
 }
 
 // ModRoot returns the root of the main module.
@@ -296,11 +273,21 @@
 	if printStackInDie {
 		debug.PrintStack()
 	}
-	if os.Getenv("GO111MODULE") == "off" {
+	if cfg.Getenv("GO111MODULE") == "off" {
 		base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
 	}
-	if inGOPATH && !MustUseModules {
-		base.Fatalf("go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'")
+	if cwd != "" {
+		if dir, name := findAltConfig(cwd); dir != "" {
+			rel, err := filepath.Rel(cwd, dir)
+			if err != nil {
+				rel = dir
+			}
+			cdCmd := ""
+			if rel != "." {
+				cdCmd = fmt.Sprintf("cd %s && ", rel)
+			}
+			base.Fatalf("go: cannot find main module, but found %s in %s\n\tto create a module there, run:\n\t%sgo mod init", name, dir, cdCmd)
+		}
 	}
 	base.Fatalf("go: cannot find main module; see 'go help modules'")
 }
@@ -315,6 +302,7 @@
 	Init()
 	if modRoot == "" {
 		Target = module.Version{Path: "command-line-arguments"}
+		targetPrefix = "command-line-arguments"
 		buildList = []module.Version{Target}
 		return
 	}
@@ -328,14 +316,8 @@
 	}
 
 	gomod := filepath.Join(modRoot, "go.mod")
-	data, err := ioutil.ReadFile(gomod)
+	data, err := renameio.ReadFile(gomod)
 	if err != nil {
-		if os.IsNotExist(err) {
-			legacyModInit()
-			modFileToBuildList()
-			WriteGoMod()
-			return
-		}
 		base.Fatalf("go: %v", err)
 	}
 
@@ -349,7 +331,7 @@
 
 	if len(f.Syntax.Stmt) == 0 || f.Module == nil {
 		// Empty mod file. Must add module path.
-		path, err := FindModulePath(modRoot)
+		path, err := findModulePath(modRoot)
 		if err != nil {
 			base.Fatalf("go: %v", err)
 		}
@@ -367,12 +349,21 @@
 		excluded[x.Mod] = true
 	}
 	modFileToBuildList()
+	stdVendorMode()
 	WriteGoMod()
 }
 
 // modFileToBuildList initializes buildList from the modFile.
 func modFileToBuildList() {
 	Target = modFile.Module.Mod
+	targetPrefix = Target.Path
+	if rel := search.InDir(cwd, cfg.GOROOTsrc); rel != "" {
+		targetInGorootSrc = true
+		if Target.Path == "std" {
+			targetPrefix = ""
+		}
+	}
+
 	list := []module.Version{Target}
 	for _, r := range modFile.Require {
 		list = append(list, r.Mod)
@@ -380,6 +371,42 @@
 	buildList = list
 }
 
+// stdVendorMode applies inside $GOROOT/src.
+// It checks that the go.mod matches vendor/modules.txt
+// and then sets -mod=vendor unless this is a command
+// that has to do explicitly with modules.
+func stdVendorMode() {
+	if !targetInGorootSrc {
+		return
+	}
+	if cfg.CmdName == "get" || strings.HasPrefix(cfg.CmdName, "mod ") {
+		return
+	}
+
+	readVendorList()
+BuildList:
+	for _, m := range buildList {
+		if m.Path == "cmd" || m.Path == "std" {
+			continue
+		}
+		for _, v := range vendorList {
+			if m.Path == v.Path {
+				if m.Version != v.Version {
+					base.Fatalf("go: inconsistent vendoring in %s:\n"+
+						"\tgo.mod requires %s %s but vendor/modules.txt has %s.\n"+
+						"\trun 'go mod tidy; go mod vendor' to sync",
+						modRoot, m.Path, m.Version, v.Version)
+				}
+				continue BuildList
+			}
+		}
+		base.Fatalf("go: inconsistent vendoring in %s:\n"+
+			"\tgo.mod requires %s %s but vendor/modules.txt does not include it.\n"+
+			"\trun 'go mod tidy; go mod vendor' to sync", modRoot, m.Path, m.Version)
+	}
+	cfg.BuildMod = "vendor"
+}
+
 // Allowed reports whether module m is allowed (not excluded) by the main module's go.mod.
 func Allowed(m module.Version) bool {
 	return !excluded[m]
@@ -387,17 +414,16 @@
 
 func legacyModInit() {
 	if modFile == nil {
-		path, err := FindModulePath(modRoot)
+		path, err := findModulePath(modRoot)
 		if err != nil {
 			base.Fatalf("go: %v", err)
 		}
 		fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", path)
 		modFile = new(modfile.File)
 		modFile.AddModuleStmt(path)
+		addGoStmt() // Add the go directive before converted module requirements.
 	}
 
-	addGoStmt()
-
 	for _, name := range altConfigs {
 		cfg := filepath.Join(modRoot, name)
 		data, err := ioutil.ReadFile(cfg)
@@ -420,15 +446,12 @@
 	}
 }
 
-// InitGoStmt adds a go statement, unless there already is one.
-func InitGoStmt() {
-	if modFile.Go == nil {
-		addGoStmt()
-	}
-}
-
-// addGoStmt adds a go statement referring to the current version.
+// addGoStmt adds a go directive to the go.mod file if it does not already include one.
+// The 'go' version added, if any, is the latest version supported by this toolchain.
 func addGoStmt() {
+	if modFile.Go != nil && modFile.Go.Version != "" {
+		return
+	}
 	tags := build.Default.ReleaseTags
 	version := tags[len(tags)-1]
 	if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) {
@@ -454,19 +477,13 @@
 	".git/config",
 }
 
-// Exported only for testing.
-func FindModuleRoot(dir, limit string, legacyConfigOK bool) (root, file string) {
+func findModuleRoot(dir string) (root string) {
 	dir = filepath.Clean(dir)
-	dir1 := dir
-	limit = filepath.Clean(limit)
 
 	// Look for enclosing go.mod.
 	for {
 		if fi, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil && !fi.IsDir() {
-			return dir, "go.mod"
-		}
-		if dir == limit {
-			break
+			return dir
 		}
 		d := filepath.Dir(dir)
 		if d == dir {
@@ -474,37 +491,45 @@
 		}
 		dir = d
 	}
+	return ""
+}
 
-	// Failing that, look for enclosing alternate version config.
-	if legacyConfigOK {
-		dir = dir1
-		for {
-			for _, name := range altConfigs {
-				if fi, err := os.Stat(filepath.Join(dir, name)); err == nil && !fi.IsDir() {
-					return dir, name
+func findAltConfig(dir string) (root, name string) {
+	dir = filepath.Clean(dir)
+	for {
+		for _, name := range altConfigs {
+			if fi, err := os.Stat(filepath.Join(dir, name)); err == nil && !fi.IsDir() {
+				if rel := search.InDir(dir, cfg.BuildContext.GOROOT); rel == "." {
+					// Don't suggest creating a module from $GOROOT/.git/config.
+					return "", ""
 				}
+				return dir, name
 			}
-			if dir == limit {
-				break
-			}
-			d := filepath.Dir(dir)
-			if d == dir {
-				break
-			}
-			dir = d
 		}
+		d := filepath.Dir(dir)
+		if d == dir {
+			break
+		}
+		dir = d
 	}
-
 	return "", ""
 }
 
-// Exported only for testing.
-func FindModulePath(dir string) (string, error) {
+func findModulePath(dir string) (string, error) {
 	if CmdModModule != "" {
 		// Running go mod init x/y/z; return x/y/z.
+		if err := module.CheckImportPath(CmdModModule); err != nil {
+			return "", err
+		}
 		return CmdModModule, nil
 	}
 
+	// TODO(bcmills): once we have located a plausible module path, we should
+	// query version control (if available) to verify that it matches the major
+	// version of the most recent tag.
+	// See https://golang.org/issue/29433, https://golang.org/issue/27009, and
+	// https://golang.org/issue/31549.
+
 	// Cast about for import comments,
 	// first in top-level directory, then in subdirectories.
 	list, _ := ioutil.ReadDir(dir)
@@ -554,18 +579,19 @@
 		}
 	}
 
-	// Look for .git/config with github origin as last resort.
-	data, _ = ioutil.ReadFile(filepath.Join(dir, ".git/config"))
-	if m := gitOriginRE.FindSubmatch(data); m != nil {
-		return "github.com/" + string(m[1]), nil
-	}
+	msg := `cannot determine module path for source directory %s (outside GOPATH, module path must be specified)
 
-	return "", fmt.Errorf("cannot determine module path for source directory %s (outside GOPATH, no import comments)", dir)
+Example usage:
+	'go mod init example.com/m' to initialize a v0 or v1 module
+	'go mod init example.com/m/v2' to initialize a v2 module
+
+Run 'go help mod init' for more information.
+`
+	return "", fmt.Errorf(msg, dir)
 }
 
 var (
-	gitOriginRE     = regexp.MustCompile(`(?m)^\[remote "origin"\]\r?\n\turl = (?:https://github.com/|git@github.com:|gh:)([^/]+/[^/]+?)(\.git)?\r?\n`)
-	importCommentRE = regexp.MustCompile(`(?m)^package[ \t]+[^ \t\r\n/]+[ \t]+//[ \t]+import[ \t]+(\"[^"]+\")[ \t]*\r?\n`)
+	importCommentRE = lazyregexp.New(`(?m)^package[ \t]+[^ \t\r\n/]+[ \t]+//[ \t]+import[ \t]+(\"[^"]+\")[ \t]*\r?\n`)
 )
 
 func findImportComment(file string) string {
@@ -629,6 +655,8 @@
 		return
 	}
 
+	addGoStmt()
+
 	if loaded != nil {
 		reqs := MinReqs()
 		min, err := reqs.Required(Target)
@@ -651,24 +679,27 @@
 		base.Fatalf("go: %v", err)
 	}
 
+	dirty := !bytes.Equal(new, modFileData)
+	if dirty && cfg.BuildMod == "readonly" {
+		// If we're about to fail due to -mod=readonly,
+		// prefer to report a dirty go.mod over a dirty go.sum
+		base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly")
+	}
 	// Always update go.sum, even if we didn't change go.mod: we may have
 	// downloaded modules that we didn't have before.
 	modfetch.WriteGoSum()
 
-	if bytes.Equal(new, modFileData) {
+	if !dirty {
 		// We don't need to modify go.mod from what we read previously.
 		// Ignore any intervening edits.
 		return
 	}
-	if cfg.BuildMod == "readonly" {
-		base.Fatalf("go: updates to go.mod needed, disabled by -mod=readonly")
-	}
 
 	unlock := modfetch.SideLock()
 	defer unlock()
 
 	file := filepath.Join(modRoot, "go.mod")
-	old, err := ioutil.ReadFile(file)
+	old, err := renameio.ReadFile(file)
 	if !bytes.Equal(old, modFileData) {
 		if bytes.Equal(old, new) {
 			// Some other process wrote the same go.mod file that we were about to write.
@@ -688,7 +719,7 @@
 
 	}
 
-	if err := renameio.WriteFile(file, new); err != nil {
+	if err := renameio.WriteFile(file, new, 0666); err != nil {
 		base.Fatalf("error writing go.mod: %v", err)
 	}
 	modFileData = new
@@ -705,13 +736,21 @@
 	// Avoid the query if it looks OK.
 	_, pathMajor, ok := module.SplitPathVersion(path)
 	if !ok {
-		return "", fmt.Errorf("malformed module path: %s", path)
+		return "", &module.ModuleError{
+			Path: path,
+			Err: &module.InvalidVersionError{
+				Version: vers,
+				Err:     fmt.Errorf("malformed module path %q", path),
+			},
+		}
 	}
-	if vers != "" && module.CanonicalVersion(vers) == vers && module.MatchPathMajor(vers, pathMajor) {
-		return vers, nil
+	if vers != "" && module.CanonicalVersion(vers) == vers {
+		if err := module.MatchPathMajor(vers, pathMajor); err == nil {
+			return vers, nil
+		}
 	}
 
-	info, err := Query(path, vers, nil)
+	info, err := Query(path, vers, "", nil)
 	if err != nil {
 		return "", err
 	}
diff --git a/src/cmd/go/internal/modload/init_test.go b/src/cmd/go/internal/modload/init_test.go
deleted file mode 100644
index 2df9d8a..0000000
--- a/src/cmd/go/internal/modload/init_test.go
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package modload
-
-import (
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"testing"
-)
-
-func TestFindModuleRootIgnoreDir(t *testing.T) {
-	// In Plan 9, directories are automatically created in /n.
-	// For example, /n/go.mod always exist, but it's a directory.
-	// Test that we ignore directories when trying to find go.mod and other config files.
-
-	dir, err := ioutil.TempDir("", "gotest")
-	if err != nil {
-		t.Fatalf("failed to create temporary directory: %v", err)
-	}
-	defer os.RemoveAll(dir)
-	if err := os.Mkdir(filepath.Join(dir, "go.mod"), os.ModeDir|0755); err != nil {
-		t.Fatalf("Mkdir failed: %v", err)
-	}
-	for _, name := range altConfigs {
-		if err := os.MkdirAll(filepath.Join(dir, name), os.ModeDir|0755); err != nil {
-			t.Fatalf("MkdirAll failed: %v", err)
-		}
-	}
-	p := filepath.Join(dir, "example")
-	if err := os.Mkdir(p, os.ModeDir|0755); err != nil {
-		t.Fatalf("Mkdir failed: %v", err)
-	}
-	if root, _ := FindModuleRoot(p, "", false); root != "" {
-		t.Errorf("FindModuleRoot(%q, \"\", false): %q, want empty string", p, root)
-	}
-	if root, _ := FindModuleRoot(p, "", true); root != "" {
-		t.Errorf("FindModuleRoot(%q, \"\", true): %q, want empty string", p, root)
-	}
-}
diff --git a/src/cmd/go/internal/modload/list.go b/src/cmd/go/internal/modload/list.go
index 2f1a3c2..35d0c28 100644
--- a/src/cmd/go/internal/modload/list.go
+++ b/src/cmd/go/internal/modload/list.go
@@ -5,6 +5,7 @@
 package modload
 
 import (
+	"errors"
 	"fmt"
 	"os"
 	"strings"
@@ -55,18 +56,26 @@
 			base.Fatalf("go: cannot use relative path %s to specify module", arg)
 		}
 		if i := strings.Index(arg, "@"); i >= 0 {
-			info, err := Query(arg[:i], arg[i+1:], nil)
+			path := arg[:i]
+			vers := arg[i+1:]
+			var current string
+			for _, m := range buildList {
+				if m.Path == path {
+					current = m.Version
+					break
+				}
+			}
+
+			info, err := Query(path, vers, current, nil)
 			if err != nil {
 				mods = append(mods, &modinfo.ModulePublic{
-					Path:    arg[:i],
-					Version: arg[i+1:],
-					Error: &modinfo.ModuleError{
-						Err: err.Error(),
-					},
+					Path:    path,
+					Version: vers,
+					Error:   modinfoError(path, vers, err),
 				})
 				continue
 			}
-			mods = append(mods, moduleInfo(module.Version{Path: arg[:i], Version: info.Version}, false))
+			mods = append(mods, moduleInfo(module.Version{Path: path, Version: info.Version}, false))
 			continue
 		}
 
@@ -101,17 +110,20 @@
 					// Don't make the user provide an explicit '@latest' when they're
 					// explicitly asking what the available versions are.
 					// Instead, resolve the module, even if it isn't an existing dependency.
-					info, err := Query(arg, "latest", nil)
+					info, err := Query(arg, "latest", "", nil)
 					if err == nil {
 						mods = append(mods, moduleInfo(module.Version{Path: arg, Version: info.Version}, false))
-						continue
+					} else {
+						mods = append(mods, &modinfo.ModulePublic{
+							Path:  arg,
+							Error: modinfoError(arg, "", err),
+						})
 					}
+					continue
 				}
 				mods = append(mods, &modinfo.ModulePublic{
-					Path: arg,
-					Error: &modinfo.ModuleError{
-						Err: fmt.Sprintf("module %q is not a known dependency", arg),
-					},
+					Path:  arg,
+					Error: modinfoError(arg, "", errors.New("not a known dependency")),
 				})
 			} else {
 				fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
@@ -121,3 +133,21 @@
 
 	return mods
 }
+
+// modinfoError wraps an error to create an error message in
+// modinfo.ModuleError with minimal redundancy.
+func modinfoError(path, vers string, err error) *modinfo.ModuleError {
+	var nerr *NoMatchingVersionError
+	var merr *module.ModuleError
+	if errors.As(err, &nerr) {
+		// NoMatchingVersionError contains the query, so we don't mention the
+		// query again in ModuleError.
+		err = &module.ModuleError{Path: path, Err: err}
+	} else if !errors.As(err, &merr) {
+		// If the error does not contain path and version, wrap it in a
+		// module.ModuleError.
+		err = &module.ModuleError{Path: path, Version: vers, Err: err}
+	}
+
+	return &modinfo.ModuleError{Err: err.Error()}
+}
diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go
index 5bb943d..b50a084 100644
--- a/src/cmd/go/internal/modload/load.go
+++ b/src/cmd/go/internal/modload/load.go
@@ -12,6 +12,7 @@
 	"io/ioutil"
 	"os"
 	"path"
+	pathpkg "path"
 	"path/filepath"
 	"sort"
 	"strings"
@@ -50,29 +51,28 @@
 var loaded *loader
 
 // ImportPaths returns the set of packages matching the args (patterns),
-// adding modules to the build list as needed to satisfy new imports.
+// on the target platform. Modules may be added to the build list
+// to satisfy new imports.
 func ImportPaths(patterns []string) []*search.Match {
-	InitMod()
+	matches := ImportPathsQuiet(patterns, imports.Tags())
+	search.WarnUnmatched(matches)
+	return matches
+}
 
-	var matches []*search.Match
-	for _, pattern := range search.CleanPatterns(patterns) {
-		m := &search.Match{
-			Pattern: pattern,
-			Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern),
-		}
-		if m.Literal {
-			m.Pkgs = []string{pattern}
-		}
-		matches = append(matches, m)
-	}
-
-	fsDirs := make([][]string, len(matches))
-	loaded = newLoader()
-	updateMatches := func(iterating bool) {
+// ImportPathsQuiet is like ImportPaths but does not warn about patterns with
+// no matches. It also lets the caller specify a set of build tags to match
+// packages. The build tags should typically be imports.Tags() or
+// imports.AnyTags(); a nil map has no special meaning.
+func ImportPathsQuiet(patterns []string, tags map[string]bool) []*search.Match {
+	var fsDirs [][]string
+	updateMatches := func(matches []*search.Match, iterating bool) {
 		for i, m := range matches {
 			switch {
 			case build.IsLocalImport(m.Pattern) || filepath.IsAbs(m.Pattern):
 				// Evaluate list of file system directories on first iteration.
+				if fsDirs == nil {
+					fsDirs = make([][]string, len(matches))
+				}
 				if fsDirs[i] == nil {
 					var dirs []string
 					if m.Literal {
@@ -90,7 +90,9 @@
 				// the exact version of a particular module increases during
 				// the loader iterations.
 				m.Pkgs = str.StringList(fsDirs[i])
-				for j, pkg := range m.Pkgs {
+				pkgs := m.Pkgs
+				m.Pkgs = m.Pkgs[:0]
+				for _, pkg := range pkgs {
 					dir := pkg
 					if !filepath.IsAbs(dir) {
 						dir = filepath.Join(cwd, pkg)
@@ -98,20 +100,56 @@
 						dir = filepath.Clean(dir)
 					}
 
+					// golang.org/issue/32917: We should resolve a relative path to a
+					// package path only if the relative path actually contains the code
+					// for that package.
+					if !dirContainsPackage(dir) {
+						// If we're outside of a module, ensure that the failure mode
+						// indicates that.
+						ModRoot()
+
+						// If the directory is local but does not exist, don't return it
+						// while loader is iterating, since this might trigger a fetch.
+						// After loader is done iterating, we still need to return the
+						// path, so that "go list -e" produces valid output.
+						if !iterating {
+							// We don't have a valid path to resolve to, so report the
+							// unresolved path.
+							m.Pkgs = append(m.Pkgs, pkg)
+						}
+						continue
+					}
+
 					// Note: The checks for @ here are just to avoid misinterpreting
 					// the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).
 					// It's not strictly necessary but helpful to keep the checks.
 					if modRoot != "" && dir == modRoot {
-						pkg = Target.Path
+						pkg = targetPrefix
 					} 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/") {
 							// TODO getmode vendor check
 							pkg = strings.TrimPrefix(suffix, "/vendor/")
+						} else if targetInGorootSrc && Target.Path == "std" {
+							// Don't add the prefix "std/" to packages in the "std" module.
+							// It's the one module path that isn't a prefix of its packages.
+							pkg = strings.TrimPrefix(suffix, "/")
+							if pkg == "builtin" {
+								// "builtin" is a pseudo-package with a real source file.
+								// It's not included in "std", so it shouldn't be included in
+								// "./..." within module "std" either.
+								continue
+							}
 						} else {
-							pkg = Target.Path + suffix
+							modPkg := targetPrefix + suffix
+							if _, ok := dirInModule(modPkg, targetPrefix, modRoot, true); ok {
+								pkg = modPkg
+							} else if !iterating {
+								ModRoot()
+								base.Errorf("go: directory %s is outside main module", base.ShortPath(dir))
+							}
 						}
-					} else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && !strings.Contains(sub, "@") {
+					} else if sub := search.InDir(dir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {
 						pkg = filepath.ToSlash(sub)
 					} else if path := pathInModuleCache(dir); path != "" {
 						pkg = path
@@ -122,17 +160,7 @@
 							base.Errorf("go: directory %s outside available modules", base.ShortPath(dir))
 						}
 					}
-					info, err := os.Stat(dir)
-					if err != nil || !info.IsDir() {
-						// If the directory is local but does not exist, don't return it
-						// while loader is iterating, since this would trigger a fetch.
-						// After loader is done iterating, we still need to return the
-						// path, so that "go list -e" produces valid output.
-						if iterating {
-							pkg = ""
-						}
-					}
-					m.Pkgs[j] = pkg
+					m.Pkgs = append(m.Pkgs, pkg)
 				}
 
 			case strings.Contains(m.Pattern, "..."):
@@ -154,25 +182,35 @@
 				if len(m.Pkgs) == 0 {
 					m.Pkgs = search.MatchPackages(m.Pattern).Pkgs
 				}
+
+			default:
+				m.Pkgs = []string{m.Pattern}
 			}
 		}
 	}
 
+	InitMod()
+
+	var matches []*search.Match
+	for _, pattern := range search.CleanPatterns(patterns) {
+		matches = append(matches, &search.Match{
+			Pattern: pattern,
+			Literal: !strings.Contains(pattern, "...") && !search.IsMetaPackage(pattern),
+		})
+	}
+
+	loaded = newLoader(tags)
 	loaded.load(func() []string {
 		var roots []string
-		updateMatches(true)
+		updateMatches(matches, true)
 		for _, m := range matches {
-			for _, pkg := range m.Pkgs {
-				if pkg != "" {
-					roots = append(roots, pkg)
-				}
-			}
+			roots = append(roots, m.Pkgs...)
 		}
 		return roots
 	})
 
 	// One last pass to finalize wildcards.
-	updateMatches(false)
+	updateMatches(matches, false)
 
 	// A given module path may be used as itself or as a replacement for another
 	// module, but not both at the same time. Otherwise, the aliasing behavior is
@@ -193,7 +231,6 @@
 	base.ExitIfErrors()
 	WriteGoMod()
 
-	search.WarnUnmatched(matches)
 	return matches
 }
 
@@ -201,7 +238,18 @@
 // if dir is in the module cache copy of a module in our build list.
 func pathInModuleCache(dir string) string {
 	for _, m := range buildList[1:] {
-		root, err := modfetch.DownloadDir(m)
+		var root string
+		var err error
+		if repl := Replacement(m); repl.Path != "" && repl.Version == "" {
+			root = repl.Path
+			if !filepath.IsAbs(root) {
+				root = filepath.Join(ModRoot(), root)
+			}
+		} else if repl.Path != "" {
+			root, err = modfetch.DownloadDir(repl)
+		} else {
+			root, err = modfetch.DownloadDir(m)
+		}
 		if err != nil {
 			continue
 		}
@@ -215,14 +263,30 @@
 	return ""
 }
 
-// warnPattern returns list, the result of matching pattern,
-// but if list is empty then first it prints a warning about
-// the pattern not matching any packages.
-func warnPattern(pattern string, list []string) []string {
-	if len(list) == 0 {
-		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
+var dirContainsPackageCache sync.Map // absolute dir → bool
+
+func dirContainsPackage(dir string) bool {
+	isPkg, ok := dirContainsPackageCache.Load(dir)
+	if !ok {
+		_, err := cfg.BuildContext.ImportDir(dir, 0)
+		if err == nil {
+			isPkg = true
+		} else {
+			if fi, statErr := os.Stat(dir); statErr != nil || !fi.IsDir() {
+				// A non-directory or inaccessible directory is not a Go package.
+				isPkg = false
+			} else if _, noGo := err.(*build.NoGoError); noGo {
+				// A directory containing no Go source files is not a Go package.
+				isPkg = false
+			} else {
+				// An error other than *build.NoGoError indicates that the package exists
+				// but has some other problem (such as a syntax error).
+				isPkg = true
+			}
+		}
+		isPkg, _ = dirContainsPackageCache.LoadOrStore(dir, isPkg)
 	}
-	return list
+	return isPkg.(bool)
 }
 
 // ImportFromFiles adds modules to the build list as needed
@@ -230,12 +294,13 @@
 func ImportFromFiles(gofiles []string) {
 	InitMod()
 
-	imports, testImports, err := imports.ScanFiles(gofiles, imports.Tags())
+	tags := imports.Tags()
+	imports, testImports, err := imports.ScanFiles(gofiles, tags)
 	if err != nil {
 		base.Fatalf("go: %v", err)
 	}
 
-	loaded = newLoader()
+	loaded = newLoader(tags)
 	loaded.load(func() []string {
 		var roots []string
 		roots = append(roots, imports...)
@@ -259,14 +324,14 @@
 	}
 
 	if dir == modRoot {
-		return Target.Path
+		return targetPrefix
 	}
 	if strings.HasPrefix(dir, modRoot+string(filepath.Separator)) {
 		suffix := filepath.ToSlash(dir[len(modRoot):])
 		if strings.HasPrefix(suffix, "/vendor/") {
 			return strings.TrimPrefix(suffix, "/vendor/")
 		}
-		return Target.Path + suffix
+		return targetPrefix + suffix
 	}
 	return "."
 }
@@ -284,7 +349,7 @@
 }
 
 func ReloadBuildList() []module.Version {
-	loaded = newLoader()
+	loaded = newLoader(imports.Tags())
 	loaded.load(func() []string { return nil })
 	return buildList
 }
@@ -310,35 +375,33 @@
 func loadAll(testAll bool) []string {
 	InitMod()
 
-	loaded = newLoader()
+	loaded = newLoader(imports.AnyTags())
 	loaded.isALL = true
-	loaded.tags = anyTags
 	loaded.testAll = testAll
 	if !testAll {
 		loaded.testRoots = true
 	}
-	all := TargetPackages()
+	all := TargetPackages("...")
 	loaded.load(func() []string { return all })
 	WriteGoMod()
 
 	var paths []string
 	for _, pkg := range loaded.pkgs {
-		if e, ok := pkg.err.(*ImportMissingError); ok && e.Module.Path == "" {
-			continue // Package doesn't actually exist.
+		if pkg.err != nil {
+			base.Errorf("%s: %v", pkg.stackText(), pkg.err)
+			continue
 		}
 		paths = append(paths, pkg.path)
 	}
+	base.ExitIfErrors()
 	return paths
 }
 
-// anyTags is a special tags map that satisfies nearly all build tag expressions.
-// Only "ignore" and malformed build tag requirements are considered false.
-var anyTags = map[string]bool{"*": true}
-
-// TargetPackages returns the list of packages in the target (top-level) module,
-// under all build tag settings.
-func TargetPackages() []string {
-	return matchPackages("...", anyTags, false, []module.Version{Target})
+// TargetPackages returns the list of packages in the target (top-level) module
+// matching pattern, which may be relative to the working directory, under all
+// build tag settings.
+func TargetPackages(pattern string) []string {
+	return matchPackages(pattern, imports.AnyTags(), false, []module.Version{Target})
 }
 
 // BuildList returns the module build list,
@@ -387,6 +450,29 @@
 	return pkg.mod
 }
 
+// PackageImports returns the imports for the package named by the import path.
+// Test imports will be returned as well if tests were loaded for the package
+// (i.e., if "all" was loaded or if LoadTests was set and the path was matched
+// by a command line argument). PackageImports will return nil for
+// unknown package paths.
+func PackageImports(path string) (imports, testImports []string) {
+	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
+	if !ok {
+		return nil, nil
+	}
+	imports = make([]string, len(pkg.imports))
+	for i, p := range pkg.imports {
+		imports[i] = p.path
+	}
+	if pkg.test != nil {
+		testImports = make([]string, len(pkg.test.imports))
+		for i, p := range pkg.test.imports {
+			testImports[i] = p.path
+		}
+	}
+	return imports, testImports
+}
+
 // ModuleUsedDirectly reports whether the main module directly imports
 // some package in the module with the given path.
 func ModuleUsedDirectly(path string) bool {
@@ -394,13 +480,17 @@
 }
 
 // Lookup returns the source directory, import path, and any loading error for
-// the package at path.
+// the package at path as imported from the package in parentDir.
 // Lookup requires that one of the Load functions in this package has already
 // been called.
-func Lookup(path string) (dir, realPath string, err error) {
+func Lookup(parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) {
 	if path == "" {
 		panic("Lookup called with empty package path")
 	}
+
+	if parentIsStd {
+		path = loaded.stdVendor(parentPath, path)
+	}
 	pkg, ok := loaded.pkgCache.Get(path).(*loadPkg)
 	if !ok {
 		// The loader should have found all the relevant paths.
@@ -434,10 +524,11 @@
 // TODO(rsc): It might be nice to make the loader take and return
 // a buildList rather than hard-coding use of the global.
 type loader struct {
-	tags      map[string]bool // tags for scanDir
-	testRoots bool            // include tests for roots
-	isALL     bool            // created with LoadALL
-	testAll   bool            // include tests for all packages
+	tags           map[string]bool // tags for scanDir
+	testRoots      bool            // include tests for roots
+	isALL          bool            // created with LoadALL
+	testAll        bool            // include tests for all packages
+	forceStdVendor bool            // if true, load standard-library dependencies from the vendor subtree
 
 	// reset on each iteration
 	roots    []*loadPkg
@@ -453,10 +544,17 @@
 // LoadTests controls whether the loaders load tests of the root packages.
 var LoadTests bool
 
-func newLoader() *loader {
+func newLoader(tags map[string]bool) *loader {
 	ld := new(loader)
-	ld.tags = imports.Tags()
+	ld.tags = tags
 	ld.testRoots = LoadTests
+
+	// Inside the "std" and "cmd" modules, we prefer to use the vendor directory
+	// unless the command explicitly changes the module graph.
+	if !targetInGorootSrc || (cfg.CmdName != "get" && !strings.HasPrefix(cfg.CmdName, "mod ")) {
+		ld.forceStdVendor = true
+	}
+
 	return ld
 }
 
@@ -511,8 +609,12 @@
 		for _, m := range buildList {
 			haveMod[m] = true
 		}
+		modAddedBy := make(map[module.Version]*loadPkg)
 		for _, pkg := range ld.pkgs {
 			if err, ok := pkg.err.(*ImportMissingError); ok && err.Module.Path != "" {
+				if err.newMissingVersion != "" {
+					base.Fatalf("go: %s: package provided by %s at latest version %s but not at required version %s", pkg.stackText(), err.Module.Path, err.Module.Version, err.newMissingVersion)
+				}
 				if added[pkg.path] {
 					base.Fatalf("go: %s: looping trying to add package", pkg.stackText())
 				}
@@ -520,6 +622,7 @@
 				numAdded++
 				if !haveMod[err.Module] {
 					haveMod[err.Module] = true
+					modAddedBy[err.Module] = pkg
 					buildList = append(buildList, err.Module)
 				}
 				continue
@@ -535,6 +638,14 @@
 		reqs = Reqs()
 		buildList, err = mvs.BuildList(Target, reqs)
 		if err != nil {
+			// If an error was found in a newly added module, report the package
+			// import stack instead of the module requirement stack. Packages
+			// are more descriptive.
+			if err, ok := err.(*mvs.BuildListError); ok {
+				if pkg := modAddedBy[err.Module()]; pkg != nil {
+					base.Fatalf("go: %s: %v", pkg.stackText(), err.Err)
+				}
+			}
 			base.Fatalf("go: %v", err)
 		}
 	}
@@ -631,7 +742,11 @@
 		}
 	}
 
+	inStd := (search.IsStandardImportPath(pkg.path) && search.InDir(pkg.dir, cfg.GOROOTsrc) != "")
 	for _, path := range imports {
+		if inStd {
+			path = ld.stdVendor(pkg.path, path)
+		}
 		pkg.imports = append(pkg.imports, ld.pkg(path, false))
 	}
 
@@ -642,6 +757,31 @@
 	}
 }
 
+// stdVendor returns the canonical import path for the package with the given
+// path when imported from the standard-library package at parentPath.
+func (ld *loader) stdVendor(parentPath, path string) string {
+	if search.IsStandardImportPath(path) {
+		return path
+	}
+
+	if str.HasPathPrefix(parentPath, "cmd") {
+		if ld.forceStdVendor || Target.Path != "cmd" {
+			vendorPath := pathpkg.Join("cmd", "vendor", path)
+			if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
+				return vendorPath
+			}
+		}
+	} else if ld.forceStdVendor || Target.Path != "std" {
+		vendorPath := pathpkg.Join("vendor", path)
+		if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {
+			return vendorPath
+		}
+	}
+
+	// Not vendored: resolve from modules.
+	return path
+}
+
 // computePatternAll returns the list of packages matching pattern "all",
 // starting with a list of the import paths for the packages in the main module.
 func (ld *loader) computePatternAll(paths []string) []string {
@@ -737,27 +877,33 @@
 // stackText builds the import stack text to use when
 // reporting an error in pkg. It has the general form
 //
-//	import root ->
-//		import other ->
-//		import other2 ->
-//		import pkg
+//	root imports
+//		other imports
+//		other2 tested by
+//		other2.test imports
+//		pkg
 //
 func (pkg *loadPkg) stackText() string {
 	var stack []*loadPkg
-	for p := pkg.stack; p != nil; p = p.stack {
+	for p := pkg; p != nil; p = p.stack {
 		stack = append(stack, p)
 	}
 
 	var buf bytes.Buffer
 	for i := len(stack) - 1; i >= 0; i-- {
 		p := stack[i]
+		fmt.Fprint(&buf, p.path)
 		if p.testOf != nil {
-			fmt.Fprintf(&buf, "test ->\n\t")
-		} else {
-			fmt.Fprintf(&buf, "import %q ->\n\t", p.path)
+			fmt.Fprint(&buf, ".test")
+		}
+		if i > 0 {
+			if stack[i-1].testOf == p {
+				fmt.Fprint(&buf, " tested by\n\t")
+			} else {
+				fmt.Fprint(&buf, " imports\n\t")
+			}
 		}
 	}
-	fmt.Fprintf(&buf, "import %q", pkg.path)
 	return buf.String()
 }
 
@@ -909,27 +1055,40 @@
 }
 
 func (r *mvsReqs) modFileToList(f *modfile.File) []module.Version {
-	var list []module.Version
+	list := make([]module.Version, 0, len(f.Require))
 	for _, r := range f.Require {
 		list = append(list, r.Mod)
 	}
 	return list
 }
 
+// required returns a unique copy of the requirements of mod.
 func (r *mvsReqs) required(mod module.Version) ([]module.Version, error) {
 	if mod == Target {
 		if modFile != nil && modFile.Go != nil {
 			r.versions.LoadOrStore(mod, modFile.Go.Version)
 		}
-		var list []module.Version
-		return append(list, r.buildList[1:]...), nil
+		return append([]module.Version(nil), r.buildList[1:]...), nil
 	}
 
 	if cfg.BuildMod == "vendor" {
 		// For every module other than the target,
 		// return the full list of modules from modules.txt.
 		readVendorList()
-		return vendorList, nil
+		return append([]module.Version(nil), vendorList...), nil
+	}
+
+	if targetInGorootSrc {
+		// When inside "std" or "cmd", only fetch and read go.mod files if we're
+		// explicitly running a command that can change the module graph. If we have
+		// to resolve a new dependency, we might pick the wrong version, but 'go mod
+		// tidy' will fix it — and new standard-library dependencies should be rare
+		// anyway.
+		//
+		// TODO(golang.org/issue/30240): Drop this special-case.
+		if cfg.CmdName != "get" && !strings.HasPrefix(cfg.CmdName, "mod ") {
+			return nil, nil
+		}
 	}
 
 	origPath := mod.Path
@@ -943,13 +1102,11 @@
 			gomod := filepath.Join(dir, "go.mod")
 			data, err := ioutil.ReadFile(gomod)
 			if err != nil {
-				base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err)
-				return nil, ErrRequire
+				return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
 			}
 			f, err := modfile.ParseLax(gomod, data, nil)
 			if err != nil {
-				base.Errorf("go: parsing %s: %v", base.ShortPath(gomod), err)
-				return nil, ErrRequire
+				return nil, fmt.Errorf("parsing %s: %v", base.ShortPath(gomod), err)
 			}
 			if f.Go != nil {
 				r.versions.LoadOrStore(mod, f.Go.Version)
@@ -970,22 +1127,20 @@
 
 	data, err := modfetch.GoMod(mod.Path, mod.Version)
 	if err != nil {
-		base.Errorf("go: %s@%s: %v\n", mod.Path, mod.Version, err)
-		return nil, ErrRequire
+		return nil, err
 	}
 	f, err := modfile.ParseLax("go.mod", data, nil)
 	if err != nil {
-		base.Errorf("go: %s@%s: parsing go.mod: %v", mod.Path, mod.Version, err)
-		return nil, ErrRequire
+		return nil, module.VersionError(mod, fmt.Errorf("parsing go.mod: %v", err))
 	}
 
 	if f.Module == nil {
-		base.Errorf("go: %s@%s: parsing go.mod: missing module line", mod.Path, mod.Version)
-		return nil, ErrRequire
+		return nil, module.VersionError(mod, errors.New("parsing go.mod: missing module line"))
 	}
 	if mpath := f.Module.Mod.Path; mpath != origPath && mpath != mod.Path {
-		base.Errorf("go: %s@%s: parsing go.mod: unexpected module path %q", mod.Path, mod.Version, mpath)
-		return nil, ErrRequire
+		return nil, module.VersionError(mod, fmt.Errorf(`parsing go.mod:
+	module declares its path as: %s
+	        but was required as: %s`, mpath, mod.Path))
 	}
 	if f.Go != nil {
 		r.versions.LoadOrStore(mod, f.Go.Version)
@@ -994,11 +1149,6 @@
 	return r.modFileToList(f), nil
 }
 
-// ErrRequire is the sentinel error returned when Require encounters problems.
-// It prints the problems directly to standard error, so that multiple errors
-// can be displayed easily.
-var ErrRequire = errors.New("error loading module requirements")
-
 func (*mvsReqs) Max(v1, v2 string) string {
 	if v1 != "" && semver.Compare(v1, v2) == -1 {
 		return v2
@@ -1015,11 +1165,15 @@
 func versions(path string) ([]string, error) {
 	// Note: modfetch.Lookup and repo.Versions are cached,
 	// so there's no need for us to add extra caching here.
-	repo, err := modfetch.Lookup(path)
-	if err != nil {
-		return nil, err
-	}
-	return repo.Versions("")
+	var versions []string
+	err := modfetch.TryProxies(func(proxy string) error {
+		repo, err := modfetch.Lookup(proxy, path)
+		if err == nil {
+			versions, err = repo.Versions("")
+		}
+		return err
+	})
+	return versions, err
 }
 
 // Previous returns the tagged version of m.Path immediately prior to
diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go
index 0856486..602bf47 100644
--- a/src/cmd/go/internal/modload/query.go
+++ b/src/cmd/go/internal/modload/query.go
@@ -5,35 +5,66 @@
 package modload
 
 import (
-	"cmd/go/internal/modfetch"
-	"cmd/go/internal/modfetch/codehost"
-	"cmd/go/internal/module"
-	"cmd/go/internal/semver"
+	"errors"
 	"fmt"
+	"os"
 	pathpkg "path"
 	"strings"
+	"sync"
+
+	"cmd/go/internal/imports"
+	"cmd/go/internal/modfetch"
+	"cmd/go/internal/module"
+	"cmd/go/internal/search"
+	"cmd/go/internal/semver"
+	"cmd/go/internal/str"
 )
 
 // Query looks up a revision of a given module given a version query string.
 // The module must be a complete module path.
 // The version must take one of the following forms:
 //
-//	- the literal string "latest", denoting the latest available, allowed tagged version,
-//	  with non-prereleases preferred over prereleases.
-//	  If there are no tagged versions in the repo, latest returns the most recent commit.
-//	- v1, denoting the latest available tagged version v1.x.x.
-//	- v1.2, denoting the latest available tagged version v1.2.x.
-//	- v1.2.3, a semantic version string denoting that tagged version.
-//	- <v1.2.3, <=v1.2.3, >v1.2.3, >=v1.2.3,
-//	   denoting the version closest to the target and satisfying the given operator,
-//	   with non-prereleases preferred over prereleases.
-//	- a repository commit identifier, denoting that commit.
+// - the literal string "latest", denoting the latest available, allowed
+//   tagged version, with non-prereleases preferred over prereleases.
+//   If there are no tagged versions in the repo, latest returns the most
+//   recent commit.
+// - the literal string "upgrade", equivalent to "latest" except that if
+//   current is a newer version, current will be returned (see below).
+// - the literal string "patch", denoting the latest available tagged version
+//   with the same major and minor number as current (see below).
+// - v1, denoting the latest available tagged version v1.x.x.
+// - v1.2, denoting the latest available tagged version v1.2.x.
+// - v1.2.3, a semantic version string denoting that tagged version.
+// - <v1.2.3, <=v1.2.3, >v1.2.3, >=v1.2.3,
+//   denoting the version closest to the target and satisfying the given operator,
+//   with non-prereleases preferred over prereleases.
+// - a repository commit identifier or tag, denoting that commit.
 //
-// If the allowed function is non-nil, Query excludes any versions for which allowed returns false.
+// current denotes the current version of the module; it may be "" if the
+// current version is unknown or should not be considered. If query is
+// "upgrade" or "patch", current will be returned if it is a newer
+// semantic version or a chronologically later pseudo-version than the
+// version that would otherwise be chosen. This prevents accidental downgrades
+// from newer pre-release or development versions.
+//
+// If the allowed function is non-nil, Query excludes any versions for which
+// allowed returns false.
 //
 // If path is the path of the main module and the query is "latest",
 // Query returns Target.Version as the version.
-func Query(path, query string, allowed func(module.Version) bool) (*modfetch.RevInfo, error) {
+func Query(path, query, current string, allowed func(module.Version) bool) (*modfetch.RevInfo, error) {
+	var info *modfetch.RevInfo
+	err := modfetch.TryProxies(func(proxy string) (err error) {
+		info, err = queryProxy(proxy, path, query, current, allowed)
+		return err
+	})
+	return info, err
+}
+
+func queryProxy(proxy, path, query, current string, allowed func(module.Version) bool) (*modfetch.RevInfo, error) {
+	if current != "" && !semver.IsValid(current) {
+		return nil, fmt.Errorf("invalid previous version %q", current)
+	}
 	if allowed == nil {
 		allowed = func(module.Version) bool { return true }
 	}
@@ -46,9 +77,26 @@
 	var ok func(module.Version) bool
 	var prefix string
 	var preferOlder bool
+	var mayUseLatest bool
 	switch {
 	case query == "latest":
 		ok = allowed
+		mayUseLatest = true
+
+	case query == "upgrade":
+		ok = allowed
+		mayUseLatest = true
+
+	case query == "patch":
+		if current == "" {
+			ok = allowed
+			mayUseLatest = true
+		} else {
+			prefix = semver.MajorMinor(current)
+			ok = func(m module.Version) bool {
+				return matchSemverPrefix(prefix, m.Version) && allowed(m)
+			}
+		}
 
 	case strings.HasPrefix(query, "<="):
 		v := query[len("<="):]
@@ -102,18 +150,27 @@
 		}
 		prefix = query + "."
 
-	case semver.IsValid(query):
-		vers := module.CanonicalVersion(query)
-		if !allowed(module.Version{Path: path, Version: vers}) {
-			return nil, fmt.Errorf("%s@%s excluded", path, vers)
-		}
-		return modfetch.Stat(path, vers)
-
 	default:
 		// Direct lookup of semantic version or commit identifier.
-		info, err := modfetch.Stat(path, query)
+		//
+		// If the identifier is not a canonical semver tag — including if it's a
+		// semver tag with a +metadata suffix — then modfetch.Stat will populate
+		// info.Version with a suitable pseudo-version.
+		info, err := modfetch.Stat(proxy, path, query)
 		if err != nil {
-			return nil, err
+			queryErr := err
+			// The full query doesn't correspond to a tag. If it is a semantic version
+			// with a +metadata suffix, see if there is a tag without that suffix:
+			// semantic versioning defines them to be equivalent.
+			if vers := module.CanonicalVersion(query); vers != "" && vers != query {
+				info, err = modfetch.Stat(proxy, path, vers)
+				if !errors.Is(err, os.ErrNotExist) {
+					return info, err
+				}
+			}
+			if err != nil {
+				return nil, queryErr
+			}
 		}
 		if !allowed(module.Version{Path: path, Version: info.Version}) {
 			return nil, fmt.Errorf("%s@%s excluded", path, info.Version)
@@ -131,8 +188,12 @@
 		return &modfetch.RevInfo{Version: Target.Version}, nil
 	}
 
+	if str.HasPathPrefix(path, "std") || str.HasPathPrefix(path, "cmd") {
+		return nil, fmt.Errorf("explicit requirement on standard-library module %s not allowed", path)
+	}
+
 	// Load versions and execute query.
-	repo, err := modfetch.Lookup(path)
+	repo, err := modfetch.Lookup(proxy, path)
 	if err != nil {
 		return nil, err
 	}
@@ -141,44 +202,67 @@
 		return nil, err
 	}
 
+	lookup := func(v string) (*modfetch.RevInfo, error) {
+		rev, err := repo.Stat(v)
+		if err != nil {
+			return nil, err
+		}
+
+		// For "upgrade" and "patch", make sure we don't accidentally downgrade
+		// from a newer prerelease or from a chronologically newer pseudoversion.
+		if current != "" && (query == "upgrade" || query == "patch") {
+			currentTime, err := modfetch.PseudoVersionTime(current)
+			if semver.Compare(rev.Version, current) < 0 || (err == nil && rev.Time.Before(currentTime)) {
+				return repo.Stat(current)
+			}
+		}
+
+		return rev, nil
+	}
+
 	if preferOlder {
 		for _, v := range versions {
 			if semver.Prerelease(v) == "" && ok(module.Version{Path: path, Version: v}) {
-				return repo.Stat(v)
+				return lookup(v)
 			}
 		}
 		for _, v := range versions {
 			if semver.Prerelease(v) != "" && ok(module.Version{Path: path, Version: v}) {
-				return repo.Stat(v)
+				return lookup(v)
 			}
 		}
 	} else {
 		for i := len(versions) - 1; i >= 0; i-- {
 			v := versions[i]
 			if semver.Prerelease(v) == "" && ok(module.Version{Path: path, Version: v}) {
-				return repo.Stat(v)
+				return lookup(v)
 			}
 		}
 		for i := len(versions) - 1; i >= 0; i-- {
 			v := versions[i]
 			if semver.Prerelease(v) != "" && ok(module.Version{Path: path, Version: v}) {
-				return repo.Stat(v)
+				return lookup(v)
 			}
 		}
 	}
 
-	if query == "latest" {
+	if mayUseLatest {
 		// Special case for "latest": if no tags match, use latest commit in repo,
 		// provided it is not excluded.
-		if info, err := repo.Latest(); err == nil && allowed(module.Version{Path: path, Version: info.Version}) {
-			return info, nil
+		latest, err := repo.Latest()
+		if err == nil {
+			if allowed(module.Version{Path: path, Version: latest.Version}) {
+				return lookup(latest.Version)
+			}
+		} else if !errors.Is(err, os.ErrNotExist) {
+			return nil, err
 		}
 	}
 
-	return nil, fmt.Errorf("no matching versions for query %q", query)
+	return nil, &NoMatchingVersionError{query: query, current: current}
 }
 
-// isSemverPrefix reports whether v is a semantic version prefix: v1 or  v1.2 (not v1.2.3).
+// isSemverPrefix reports whether v is a semantic version prefix: v1 or v1.2 (not v1.2.3).
 // The caller is assumed to have checked that semver.IsValid(v) is true.
 func isSemverPrefix(v string) bool {
 	dots := 0
@@ -199,53 +283,272 @@
 // matchSemverPrefix reports whether the shortened semantic version p
 // matches the full-width (non-shortened) semantic version v.
 func matchSemverPrefix(p, v string) bool {
-	return len(v) > len(p) && v[len(p)] == '.' && v[:len(p)] == p
+	return len(v) > len(p) && v[len(p)] == '.' && v[:len(p)] == p && semver.Prerelease(v) == ""
 }
 
-// QueryPackage looks up a revision of a module containing path.
+type QueryResult struct {
+	Mod      module.Version
+	Rev      *modfetch.RevInfo
+	Packages []string
+}
+
+// QueryPackage looks up the module(s) containing path at a revision matching
+// query. The results are sorted by module path length in descending order.
 //
-// If multiple modules with revisions matching the query provide the requested
-// package, QueryPackage picks the one with the longest module path.
+// If the package is in the main module, QueryPackage considers only the main
+// module and only the version "latest", without checking for other possible
+// modules.
+func QueryPackage(path, query string, allowed func(module.Version) bool) ([]QueryResult, error) {
+	if search.IsMetaPackage(path) || strings.Contains(path, "...") {
+		return nil, fmt.Errorf("pattern %s is not an importable package", path)
+	}
+	return QueryPattern(path, query, allowed)
+}
+
+// QueryPattern looks up the module(s) containing at least one package matching
+// the given pattern at the given version. The results are sorted by module path
+// length in descending order.
 //
-// If the path is in the main module and the query is "latest",
-// QueryPackage returns Target as the version.
-func QueryPackage(path, query string, allowed func(module.Version) bool) (module.Version, *modfetch.RevInfo, error) {
+// QueryPattern queries modules with package paths up to the first "..."
+// in the pattern. For the pattern "example.com/a/b.../c", QueryPattern would
+// consider prefixes of "example.com/a". If multiple modules have versions
+// that match the query and packages that match the pattern, QueryPattern
+// picks the one with the longest module path.
+//
+// If any matching package is in the main module, QueryPattern considers only
+// the main module and only the version "latest", without checking for other
+// possible modules.
+func QueryPattern(pattern, query string, allowed func(module.Version) bool) ([]QueryResult, error) {
+	base := pattern
+	var match func(m module.Version, root string, isLocal bool) (pkgs []string)
+
+	if i := strings.Index(pattern, "..."); i >= 0 {
+		base = pathpkg.Dir(pattern[:i+3])
+		match = func(m module.Version, root string, isLocal bool) []string {
+			return matchPackages(pattern, imports.AnyTags(), false, []module.Version{m})
+		}
+	} else {
+		match = func(m module.Version, root string, isLocal bool) []string {
+			prefix := m.Path
+			if m == Target {
+				prefix = targetPrefix
+			}
+			if _, ok := dirInModule(pattern, prefix, root, isLocal); ok {
+				return []string{pattern}
+			} else {
+				return nil
+			}
+		}
+	}
+
 	if HasModRoot() {
-		if _, ok := dirInModule(path, Target.Path, modRoot, true); ok {
+		pkgs := match(Target, modRoot, true)
+		if len(pkgs) > 0 {
 			if query != "latest" {
-				return module.Version{}, nil, fmt.Errorf("can't query specific version (%q) for package %s in the main module (%s)", query, path, Target.Path)
+				return nil, fmt.Errorf("can't query specific version for package %s in the main module (%s)", pattern, Target.Path)
 			}
 			if !allowed(Target) {
-				return module.Version{}, nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed", path, Target.Path)
+				return nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed", pattern, Target.Path)
 			}
-			return Target, &modfetch.RevInfo{Version: Target.Version}, nil
+			return []QueryResult{{
+				Mod:      Target,
+				Rev:      &modfetch.RevInfo{Version: Target.Version},
+				Packages: pkgs,
+			}}, nil
 		}
 	}
 
-	finalErr := errMissing
-	for p := path; p != "." && p != "/"; p = pathpkg.Dir(p) {
-		info, err := Query(p, query, allowed)
-		if err != nil {
-			if _, ok := err.(*codehost.VCSError); ok {
-				// A VCSError means we know where to find the code,
-				// we just can't. Abort search.
-				return module.Version{}, nil, err
+	var (
+		results          []QueryResult
+		candidateModules = modulePrefixesExcludingTarget(base)
+	)
+	if len(candidateModules) == 0 {
+		return nil, fmt.Errorf("package %s is not in the main module (%s)", pattern, Target.Path)
+	}
+
+	err := modfetch.TryProxies(func(proxy string) error {
+		queryModule := func(path string) (r QueryResult, err error) {
+			r.Mod.Path = path
+			r.Rev, err = queryProxy(proxy, path, query, "", allowed)
+			if err != nil {
+				return r, err
 			}
-			if finalErr == errMissing {
-				finalErr = err
+			r.Mod.Version = r.Rev.Version
+			root, isLocal, err := fetch(r.Mod)
+			if err != nil {
+				return r, err
 			}
-			continue
+			r.Packages = match(r.Mod, root, isLocal)
+			if len(r.Packages) == 0 {
+				return r, &PackageNotInModuleError{
+					Mod:     r.Mod,
+					Query:   query,
+					Pattern: pattern,
+				}
+			}
+			return r, nil
 		}
-		m := module.Version{Path: p, Version: info.Version}
-		root, isLocal, err := fetch(m)
-		if err != nil {
-			return module.Version{}, nil, err
+
+		var err error
+		results, err = queryPrefixModules(candidateModules, queryModule)
+		return err
+	})
+
+	return results, err
+}
+
+// modulePrefixesExcludingTarget returns all prefixes of path that may plausibly
+// exist as a module, excluding targetPrefix but otherwise including path
+// itself, sorted by descending length.
+func modulePrefixesExcludingTarget(path string) []string {
+	prefixes := make([]string, 0, strings.Count(path, "/")+1)
+
+	for {
+		if path != targetPrefix {
+			if _, _, ok := module.SplitPathVersion(path); ok {
+				prefixes = append(prefixes, path)
+			}
 		}
-		_, ok := dirInModule(path, m.Path, root, isLocal)
-		if ok {
-			return m, info, nil
+
+		j := strings.LastIndexByte(path, '/')
+		if j < 0 {
+			break
+		}
+		path = path[:j]
+	}
+
+	return prefixes
+}
+
+type prefixResult struct {
+	QueryResult
+	err error
+}
+
+func queryPrefixModules(candidateModules []string, queryModule func(path string) (QueryResult, error)) (found []QueryResult, err error) {
+	// If the path we're attempting is not in the module cache and we don't have a
+	// fetch result cached either, we'll end up making a (potentially slow)
+	// request to the proxy or (often even slower) the origin server.
+	// To minimize latency, execute all of those requests in parallel.
+	type result struct {
+		QueryResult
+		err error
+	}
+	results := make([]result, len(candidateModules))
+	var wg sync.WaitGroup
+	wg.Add(len(candidateModules))
+	for i, p := range candidateModules {
+		go func(p string, r *result) {
+			r.QueryResult, r.err = queryModule(p)
+			wg.Done()
+		}(p, &results[i])
+	}
+	wg.Wait()
+
+	// Classify the results. In case of failure, identify the error that the user
+	// is most likely to find helpful: the most useful class of error at the
+	// longest matching path.
+	var (
+		noPackage   *PackageNotInModuleError
+		noVersion   *NoMatchingVersionError
+		notExistErr error
+	)
+	for _, r := range results {
+		switch rErr := r.err.(type) {
+		case nil:
+			found = append(found, r.QueryResult)
+		case *PackageNotInModuleError:
+			if noPackage == nil {
+				noPackage = rErr
+			}
+		case *NoMatchingVersionError:
+			if noVersion == nil {
+				noVersion = rErr
+			}
+		default:
+			if errors.Is(rErr, os.ErrNotExist) {
+				if notExistErr == nil {
+					notExistErr = rErr
+				}
+			} else if err == nil {
+				err = r.err
+			}
 		}
 	}
 
-	return module.Version{}, nil, finalErr
+	// TODO(#26232): If len(found) == 0 and some of the errors are 4xx HTTP
+	// codes, have the auth package recheck the failed paths.
+	// If we obtain new credentials for any of them, re-run the above loop.
+
+	if len(found) == 0 && err == nil {
+		switch {
+		case noPackage != nil:
+			err = noPackage
+		case noVersion != nil:
+			err = noVersion
+		case notExistErr != nil:
+			err = notExistErr
+		default:
+			panic("queryPrefixModules: no modules found, but no error detected")
+		}
+	}
+
+	return found, err
+}
+
+// A NoMatchingVersionError indicates that Query found a module at the requested
+// path, but not at any versions satisfying the query string and allow-function.
+//
+// NOTE: NoMatchingVersionError MUST NOT implement Is(os.ErrNotExist).
+//
+// If the module came from a proxy, that proxy had to return a successful status
+// code for the versions it knows about, and thus did not have the opportunity
+// to return a non-400 status code to suppress fallback.
+type NoMatchingVersionError struct {
+	query, current string
+}
+
+func (e *NoMatchingVersionError) Error() string {
+	currentSuffix := ""
+	if (e.query == "upgrade" || e.query == "patch") && e.current != "" {
+		currentSuffix = fmt.Sprintf(" (current version is %s)", e.current)
+	}
+	return fmt.Sprintf("no matching versions for query %q", e.query) + currentSuffix
+}
+
+// A PackageNotInModuleError indicates that QueryPattern found a candidate
+// module at the requested version, but that module did not contain any packages
+// matching the requested pattern.
+//
+// NOTE: PackageNotInModuleError MUST NOT implement Is(os.ErrNotExist).
+//
+// If the module came from a proxy, that proxy had to return a successful status
+// code for the versions it knows about, and thus did not have the opportunity
+// to return a non-400 status code to suppress fallback.
+type PackageNotInModuleError struct {
+	Mod     module.Version
+	Query   string
+	Pattern string
+}
+
+func (e *PackageNotInModuleError) Error() string {
+	found := ""
+	if e.Query != e.Mod.Version {
+		found = fmt.Sprintf(" (%s)", e.Mod.Version)
+	}
+
+	if strings.Contains(e.Pattern, "...") {
+		return fmt.Sprintf("module %s@%s%s found, but does not contain packages matching %s", e.Mod.Path, e.Query, found, e.Pattern)
+	}
+	return fmt.Sprintf("module %s@%s%s found, but does not contain package %s", e.Mod.Path, e.Query, found, e.Pattern)
+}
+
+// ModuleHasRootPackage returns whether module m contains a package m.Path.
+func ModuleHasRootPackage(m module.Version) (bool, error) {
+	root, isLocal, err := fetch(m)
+	if err != nil {
+		return false, err
+	}
+	_, ok := dirInModule(m.Path, m.Path, root, isLocal)
+	return ok, nil
 }
diff --git a/src/cmd/go/internal/modload/query_test.go b/src/cmd/go/internal/modload/query_test.go
index 9b07383..b91cbb5 100644
--- a/src/cmd/go/internal/modload/query_test.go
+++ b/src/cmd/go/internal/modload/query_test.go
@@ -14,6 +14,7 @@
 	"strings"
 	"testing"
 
+	"cmd/go/internal/cfg"
 	"cmd/go/internal/modfetch"
 	"cmd/go/internal/modfetch/codehost"
 	"cmd/go/internal/module"
@@ -24,11 +25,16 @@
 }
 
 func testMain(m *testing.M) int {
+	cfg.GOPROXY = "direct"
+
 	dir, err := ioutil.TempDir("", "modload-test-")
 	if err != nil {
 		log.Fatal(err)
 	}
 	defer os.RemoveAll(dir)
+
+	os.Setenv("GOPATH", dir)
+	cfg.BuildContext.GOPATH = dir
 	modfetch.PkgMod = filepath.Join(dir, "pkg/mod")
 	codehost.WorkRoot = filepath.Join(dir, "codework")
 	return m.Run()
@@ -44,11 +50,12 @@
 )
 
 var queryTests = []struct {
-	path  string
-	query string
-	allow string
-	vers  string
-	err   string
+	path    string
+	query   string
+	current string
+	allow   string
+	vers    string
+	err     string
 }{
 	/*
 		git init
@@ -56,7 +63,7 @@
 		git add go.mod
 		git commit -m v1 go.mod
 		git tag start
-		for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1; do
+		for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1 v1.9.10-pre2+metadata; do
 			echo before $i >status
 			git add status
 			git commit -m "before $i" status
@@ -70,7 +77,7 @@
 		git checkout v2
 		echo module vcs-test.golang.org/git/querytest.git/v2 >go.mod
 		git commit -m v2 go.mod
-		for i in v2.0.0 v2.1.0 v2.2.0 v2.5.5; do
+		for i in v2.0.0 v2.1.0 v2.2.0 v2.5.5 v2.6.0-pre1; do
 			echo before $i >status
 			git add status
 			git commit -m "before $i" status
@@ -78,6 +85,7 @@
 			git commit -m "at $i" status
 			git tag $i
 		done
+		git checkout v2.5.5
 		echo after v2.5.5 >status
 		git commit -m 'after v2.5.5' status
 		git checkout master
@@ -92,28 +100,72 @@
 	{path: queryRepo, query: ">=v0.0.0", vers: "v0.0.0"},
 	{path: queryRepo, query: "v0.0.1", vers: "v0.0.1"},
 	{path: queryRepo, query: "v0.0.1+foo", vers: "v0.0.1"},
-	{path: queryRepo, query: "v0.0.99", err: `unknown revision v0.0.99`},
+	{path: queryRepo, query: "v0.0.99", err: `vcs-test.golang.org/git/querytest.git@v0.0.99: invalid version: unknown revision v0.0.99`},
 	{path: queryRepo, query: "v0", vers: "v0.3.0"},
 	{path: queryRepo, query: "v0.1", vers: "v0.1.2"},
 	{path: queryRepo, query: "v0.2", err: `no matching versions for query "v0.2"`},
 	{path: queryRepo, query: "v0.0", vers: "v0.0.3"},
+	{path: queryRepo, query: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
+
+	// golang.org/issue/29262: The major version for for a module without a suffix
+	// should be based on the most recent tag (v1 as appropriate, not v0
+	// unconditionally).
+	{path: queryRepo, query: "42abcb6df8ee", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
+
+	{path: queryRepo, query: "v1.9.10-pre2+wrongmetadata", err: `vcs-test.golang.org/git/querytest.git@v1.9.10-pre2+wrongmetadata: invalid version: unknown revision v1.9.10-pre2+wrongmetadata`},
+	{path: queryRepo, query: "v1.9.10-pre2", err: `vcs-test.golang.org/git/querytest.git@v1.9.10-pre2: invalid version: unknown revision v1.9.10-pre2`},
 	{path: queryRepo, query: "latest", vers: "v1.9.9"},
-	{path: queryRepo, query: "latest", allow: "NOMATCH", err: `no matching versions for query "latest"`},
+	{path: queryRepo, query: "latest", current: "v1.9.10-pre1", vers: "v1.9.9"},
+	{path: queryRepo, query: "upgrade", vers: "v1.9.9"},
+	{path: queryRepo, query: "upgrade", current: "v1.9.10-pre1", vers: "v1.9.10-pre1"},
+	{path: queryRepo, query: "upgrade", current: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
+	{path: queryRepo, query: "upgrade", current: "v0.0.0-20190513201126-42abcb6df8ee", vers: "v0.0.0-20190513201126-42abcb6df8ee"},
+	{path: queryRepo, query: "upgrade", allow: "NOMATCH", err: `no matching versions for query "upgrade"`},
+	{path: queryRepo, query: "upgrade", current: "v1.9.9", allow: "NOMATCH", err: `no matching versions for query "upgrade" (current version is v1.9.9)`},
+	{path: queryRepo, query: "upgrade", current: "v1.99.99", err: `vcs-test.golang.org/git/querytest.git@v1.99.99: invalid version: unknown revision v1.99.99`},
+	{path: queryRepo, query: "patch", current: "", vers: "v1.9.9"},
+	{path: queryRepo, query: "patch", current: "v0.1.0", vers: "v0.1.2"},
+	{path: queryRepo, query: "patch", current: "v1.9.0", vers: "v1.9.9"},
+	{path: queryRepo, query: "patch", current: "v1.9.10-pre1", vers: "v1.9.10-pre1"},
+	{path: queryRepo, query: "patch", current: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
+	{path: queryRepo, query: "patch", current: "v1.99.99", err: `no matching versions for query "patch" (current version is v1.99.99)`},
 	{path: queryRepo, query: ">v1.9.9", vers: "v1.9.10-pre1"},
 	{path: queryRepo, query: ">v1.10.0", err: `no matching versions for query ">v1.10.0"`},
 	{path: queryRepo, query: ">=v1.10.0", err: `no matching versions for query ">=v1.10.0"`},
 	{path: queryRepo, query: "6cf84eb", vers: "v0.0.2-0.20180704023347-6cf84ebaea54"},
+
+	// golang.org/issue/27173: A pseudo-version may be based on the highest tag on
+	// any parent commit, or any existing semantically-lower tag: a given commit
+	// could have been a pre-release for a backport tag at any point.
+	{path: queryRepo, query: "3ef0cec634e0", vers: "v0.1.2-0.20180704023347-3ef0cec634e0"},
+	{path: queryRepo, query: "v0.1.2-0.20180704023347-3ef0cec634e0", vers: "v0.1.2-0.20180704023347-3ef0cec634e0"},
+	{path: queryRepo, query: "v0.1.1-0.20180704023347-3ef0cec634e0", vers: "v0.1.1-0.20180704023347-3ef0cec634e0"},
+	{path: queryRepo, query: "v0.0.4-0.20180704023347-3ef0cec634e0", vers: "v0.0.4-0.20180704023347-3ef0cec634e0"},
+
+	// Invalid tags are tested in cmd/go/testdata/script/mod_pseudo_invalid.txt.
+
 	{path: queryRepo, query: "start", vers: "v0.0.0-20180704023101-5e9e31667ddf"},
+	{path: queryRepo, query: "5e9e31667ddf", vers: "v0.0.0-20180704023101-5e9e31667ddf"},
+	{path: queryRepo, query: "v0.0.0-20180704023101-5e9e31667ddf", vers: "v0.0.0-20180704023101-5e9e31667ddf"},
+
 	{path: queryRepo, query: "7a1b6bf", vers: "v0.1.0"},
 
 	{path: queryRepoV2, query: "<v0.0.0", err: `no matching versions for query "<v0.0.0"`},
 	{path: queryRepoV2, query: "<=v0.0.0", err: `no matching versions for query "<=v0.0.0"`},
 	{path: queryRepoV2, query: ">v0.0.0", vers: "v2.0.0"},
 	{path: queryRepoV2, query: ">=v0.0.0", vers: "v2.0.0"},
-	{path: queryRepoV2, query: "v0.0.1+foo", vers: "v2.0.0-20180704023347-179bc86b1be3"},
+
+	{path: queryRepoV2, query: "v2", vers: "v2.5.5"},
+	{path: queryRepoV2, query: "v2.5", vers: "v2.5.5"},
+	{path: queryRepoV2, query: "v2.6", err: `no matching versions for query "v2.6"`},
+	{path: queryRepoV2, query: "v2.6.0-pre1", vers: "v2.6.0-pre1"},
 	{path: queryRepoV2, query: "latest", vers: "v2.5.5"},
 
-	{path: queryRepoV3, query: "latest", vers: "v3.0.0-20180704024501-e0cf3de987e6"},
+	// e0cf3de987e6 is the latest commit on the master branch, and it's actually
+	// v1.19.10-pre1, not anything resembling v3: attempting to query it as such
+	// should fail.
+	{path: queryRepoV3, query: "e0cf3de987e6", err: `vcs-test.golang.org/git/querytest.git/v3@v3.0.0-20180704024501-e0cf3de987e6: invalid version: go.mod has non-.../v3 module path "vcs-test.golang.org/git/querytest.git" (and .../v3/go.mod does not exist) at revision e0cf3de987e6`},
+	{path: queryRepoV3, query: "latest", err: `no matching versions for query "latest"`},
 
 	{path: emptyRepo, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"},
 	{path: emptyRepo, query: ">v0.0.0", err: `no matching versions for query ">v0.0.0"`},
@@ -122,6 +174,7 @@
 
 func TestQuery(t *testing.T) {
 	testenv.MustHaveExternalNetwork(t)
+	testenv.MustHaveExecPath(t, "git")
 
 	for _, tt := range queryTests {
 		allow := tt.allow
@@ -132,13 +185,18 @@
 			ok, _ := path.Match(allow, m.Version)
 			return ok
 		}
-		t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.query+"/"+allow, func(t *testing.T) {
-			info, err := Query(tt.path, tt.query, allowed)
+		tt := tt
+		t.Run(strings.ReplaceAll(tt.path, "/", "_")+"/"+tt.query+"/"+tt.current+"/"+allow, func(t *testing.T) {
+			t.Parallel()
+
+			info, err := Query(tt.path, tt.query, tt.current, allowed)
 			if tt.err != "" {
-				if err != nil && err.Error() == tt.err {
-					return
+				if err == nil {
+					t.Errorf("Query(%q, %q, %v) = %v, want error %q", tt.path, tt.query, allow, info.Version, tt.err)
+				} else if err.Error() != tt.err {
+					t.Errorf("Query(%q, %q, %v): %v, want error %q", tt.path, tt.query, allow, err, tt.err)
 				}
-				t.Fatalf("Query(%q, %q, %v): %v, want error %q", tt.path, tt.query, allow, err, tt.err)
+				return
 			}
 			if err != nil {
 				t.Fatalf("Query(%q, %q, %v): %v", tt.path, tt.query, allow, err)
diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go
index 7d8852d..d82386e 100644
--- a/src/cmd/go/internal/modload/search.go
+++ b/src/cmd/go/internal/modload/search.go
@@ -35,12 +35,14 @@
 	}
 	var pkgs []string
 
-	walkPkgs := func(root, importPathRoot string) {
+	type pruning int8
+	const (
+		pruneVendor = pruning(1 << iota)
+		pruneGoMod
+	)
+
+	walkPkgs := func(root, importPathRoot string, prune pruning) {
 		root = filepath.Clean(root)
-		var cmd string
-		if root == cfg.GOROOTsrc {
-			cmd = filepath.Join(root, "cmd")
-		}
 		filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
 			if err != nil {
 				return nil
@@ -51,14 +53,6 @@
 				return nil
 			}
 
-			// GOROOT/src/cmd makes use of GOROOT/src/cmd/vendor,
-			// which module mode can't deal with. Eventually we'll stop using
-			// that vendor directory, and then we can remove this exclusion.
-			// golang.org/issue/26924.
-			if path == cmd {
-				return filepath.SkipDir
-			}
-
 			want := true
 			// Avoid .foo, _foo, and testdata directory trees.
 			_, elem := filepath.Split(path)
@@ -86,8 +80,9 @@
 			if !want {
 				return filepath.SkipDir
 			}
-			if path != root {
-				if _, err := os.Stat(filepath.Join(path, "go.mod")); err == nil {
+			// Stop at module boundaries.
+			if (prune&pruneGoMod != 0) && path != root {
+				if fi, err := os.Stat(filepath.Join(path, "go.mod")); err == nil && !fi.IsDir() {
 					return filepath.SkipDir
 				}
 			}
@@ -101,7 +96,7 @@
 				}
 			}
 
-			if elem == "vendor" {
+			if elem == "vendor" && (prune&pruneVendor != 0) {
 				return filepath.SkipDir
 			}
 			return nil
@@ -109,28 +104,51 @@
 	}
 
 	if useStd {
-		walkPkgs(cfg.GOROOTsrc, "")
+		walkPkgs(cfg.GOROOTsrc, "", pruneGoMod)
+		if treeCanMatch("cmd") {
+			walkPkgs(filepath.Join(cfg.GOROOTsrc, "cmd"), "cmd", pruneGoMod)
+		}
+	}
+
+	if cfg.BuildMod == "vendor" {
+		if HasModRoot() {
+			walkPkgs(ModRoot(), targetPrefix, pruneGoMod|pruneVendor)
+			walkPkgs(filepath.Join(ModRoot(), "vendor"), "", pruneVendor)
+		}
+		return pkgs
 	}
 
 	for _, mod := range modules {
 		if !treeCanMatch(mod.Path) {
 			continue
 		}
-		var root string
-		if mod.Version == "" {
+
+		var (
+			root, modPrefix string
+			isLocal         bool
+		)
+		if mod == Target {
 			if !HasModRoot() {
 				continue // If there is no main module, we can't search in it.
 			}
 			root = ModRoot()
+			modPrefix = targetPrefix
+			isLocal = true
 		} else {
 			var err error
-			root, _, err = fetch(mod)
+			root, isLocal, err = fetch(mod)
 			if err != nil {
 				base.Errorf("go: %v", err)
 				continue
 			}
+			modPrefix = mod.Path
 		}
-		walkPkgs(root, mod.Path)
+
+		prune := pruneVendor
+		if isLocal {
+			prune |= pruneGoMod
+		}
+		walkPkgs(root, modPrefix, prune)
 	}
 
 	return pkgs