src/cmd/go/internal/modload/load.go GO 2,428 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,428.
1// Copyright 2018 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45package modload67// This file contains the module-mode package loader, as well as some accessory8// functions pertaining to the package import graph.9//10// There are two exported entry points into package loading — LoadPackages and11// ImportFromFiles — both implemented in terms of loadFromRoots, which itself12// manipulates an instance of the loader struct.13//14// Although most of the loading state is maintained in the loader struct,15// one key piece - the build list - is a global, so that it can be modified16// separate from the loading operation, such as during "go get"17// upgrades/downgrades or in "go mod" operations.18// TODO(#40775): It might be nice to make the loader take and return19// a buildList rather than hard-coding use of the global.20//21// Loading is an iterative process. On each iteration, we try to load the22// requested packages and their transitive imports, then try to resolve modules23// for any imported packages that are still missing.24//25// The first step of each iteration identifies a set of “root” packages.26// Normally the root packages are exactly those matching the named pattern27// arguments. However, for the "all" meta-pattern, the final set of packages is28// computed from the package import graph, and therefore cannot be an initial29// input to loading that graph. Instead, the root packages for the "all" pattern30// are those contained in the main module, and allPatternIsRoot parameter to the31// loader instructs it to dynamically expand those roots to the full "all"32// pattern as loading progresses.33//34// The pkgInAll flag on each loadPkg instance tracks whether that35// package is known to match the "all" meta-pattern.36// A package matches the "all" pattern if:37// 	- it is in the main module, or38// 	- it is imported by any test in the main module, or39// 	- it is imported by a tool of the main module, or40// 	- it is imported by another package in "all", or41// 	- the main module specifies a go version ≤ 1.15, and the package is imported42// 	  by a *test of* another package in "all".43//44// When graph pruning is in effect, we want to spot-check the graph-pruning45// invariants — which depend on which packages are known to be in "all" — even46// when we are only loading individual packages, so we set the pkgInAll flag47// regardless of the whether the "all" pattern is a root.48// (This is necessary to maintain the “import invariant” described in49// https://golang.org/design/36460-lazy-module-loading.)50//51// Because "go mod vendor" prunes out the tests of vendored packages, the52// behavior of the "all" pattern with -mod=vendor in Go 1.11–1.15 is the same53// as the "all" pattern (regardless of the -mod flag) in 1.16+.54// The loader uses the GoVersion parameter to determine whether the "all"55// pattern should close over tests (as in Go 1.11–1.15) or stop at only those56// packages transitively imported by the packages and tests in the main module57// ("all" in Go 1.16+ and "go mod vendor" in Go 1.11+).58//59// Note that it is possible for a loaded package NOT to be in "all" even when we60// are loading the "all" pattern. For example, packages that are transitive61// dependencies of other roots named on the command line must be loaded, but are62// not in "all". (The mod_notall test illustrates this behavior.)63// Similarly, if the LoadTests flag is set but the "all" pattern does not close64// over test dependencies, then when we load the test of a package that is in65// "all" but outside the main module, the dependencies of that test will not66// necessarily themselves be in "all". (That configuration does not arise in Go67// 1.11–1.15, but it will be possible in Go 1.16+.)68//69// Loading proceeds from the roots, using a parallel work-queue with a limit on70// the amount of active work (to avoid saturating disks, CPU cores, and/or71// network connections). Each package is added to the queue the first time it is72// imported by another package. When we have finished identifying the imports of73// a package, we add the test for that package if it is needed. A test may be74// needed if:75// 	- the package matches a root pattern and tests of the roots were requested, or76// 	- the package is in the main module and the "all" pattern is requested77// 	  (because the "all" pattern includes the dependencies of tests in the main78// 	  module), or79// 	- the package is in "all" and the definition of "all" we are using includes80// 	  dependencies of tests (as is the case in Go ≤1.15).81//82// After all available packages have been loaded, we examine the results to83// identify any requested or imported packages that are still missing, and if84// so, which modules we could add to the module graph in order to make the85// missing packages available. We add those to the module graph and iterate,86// until either all packages resolve successfully or we cannot identify any87// module that would resolve any remaining missing package.88//89// If the main module is “tidy” (that is, if "go mod tidy" is a no-op for it)90// and all requested packages are in "all", then loading completes in a single91// iteration.92// TODO(bcmills): We should also be able to load in a single iteration if the93// requested packages all come from modules that are themselves tidy, regardless94// of whether those packages are in "all". Today, that requires two iterations95// if those packages are not found in existing dependencies of the main module.9697import (98	"context"99	"errors"100	"fmt"101	"go/build"102	"internal/diff"103	"io/fs"104	"maps"105	"os"106	pathpkg "path"107	"path/filepath"108	"runtime"109	"slices"110	"sort"111	"strings"112	"sync"113	"sync/atomic"114115	"cmd/go/internal/base"116	"cmd/go/internal/cfg"117	"cmd/go/internal/fips140"118	"cmd/go/internal/fsys"119	"cmd/go/internal/gover"120	"cmd/go/internal/imports"121	"cmd/go/internal/modfetch"122	"cmd/go/internal/modindex"123	"cmd/go/internal/mvs"124	"cmd/go/internal/search"125	"cmd/go/internal/str"126	"cmd/internal/par"127128	"golang.org/x/mod/module"129)130131// PackageOpts control the behavior of the LoadPackages function.132type PackageOpts struct {133	// TidyGoVersion is the Go version to which the go.mod file should be updated134	// after packages have been loaded.135	//136	// An empty TidyGoVersion means to use the Go version already specified in the137	// main module's go.mod file, or the latest Go version if there is no main138	// module.139	TidyGoVersion string140141	// Tags are the build tags in effect (as interpreted by the142	// cmd/go/internal/imports package).143	// If nil, treated as equivalent to imports.Tags().144	Tags map[string]bool145146	// Tidy, if true, requests that the build list and go.sum file be reduced to147	// the minimal dependencies needed to reproducibly reload the requested148	// packages.149	Tidy bool150151	// TidyDiff, if true, causes tidy not to modify go.mod or go.sum but152	// instead print the necessary changes as a unified diff. It exits153	// with a non-zero code if the diff is not empty.154	TidyDiff bool155156	// TidyCompatibleVersion is the oldest Go version that must be able to157	// reproducibly reload the requested packages.158	//159	// If empty, the compatible version is the Go version immediately prior to the160	// 'go' version listed in the go.mod file.161	TidyCompatibleVersion string162163	// VendorModulesInGOROOTSrc indicates that if we are within a module in164	// GOROOT/src, packages in the module's vendor directory should be resolved as165	// actual module dependencies (instead of standard-library packages).166	VendorModulesInGOROOTSrc bool167168	// ResolveMissingImports indicates that we should attempt to add module169	// dependencies as needed to resolve imports of packages that are not found.170	//171	// For commands that support the -mod flag, resolving imports may still fail172	// if the flag is set to "readonly" (the default) or "vendor".173	ResolveMissingImports bool174175	// AssumeRootsImported indicates that the transitive dependencies of the root176	// packages should be treated as if those roots will be imported by the main177	// module.178	AssumeRootsImported bool179180	// AllowPackage, if non-nil, is called after identifying the module providing181	// each package. If AllowPackage returns a non-nil error, that error is set182	// for the package, and the imports and test of that package will not be183	// loaded.184	//185	// AllowPackage may be invoked concurrently by multiple goroutines,186	// and may be invoked multiple times for a given package path.187	AllowPackage func(ctx context.Context, path string, mod module.Version) error188189	// LoadTests loads the test dependencies of each package matching a requested190	// pattern. If ResolveMissingImports is also true, test dependencies will be191	// resolved if missing.192	LoadTests bool193194	// UseVendorAll causes the "all" package pattern to be interpreted as if195	// running "go mod vendor" (or building with "-mod=vendor").196	//197	// This is a no-op for modules that declare 'go 1.16' or higher, for which this198	// is the default (and only) interpretation of the "all" pattern in module mode.199	UseVendorAll bool200201	// AllowErrors indicates that LoadPackages should not terminate the process if202	// an error occurs.203	AllowErrors bool204205	// SilencePackageErrors indicates that LoadPackages should not print errors206	// that occur while matching or loading packages, and should not terminate the207	// process if such an error occurs.208	//209	// Errors encountered in the module graph will still be reported.210	//211	// The caller may retrieve the silenced package errors using the Lookup212	// function, and matching errors are still populated in the Errs field of the213	// associated search.Match.)214	SilencePackageErrors bool215216	// SilenceMissingStdImports indicates that LoadPackages should not print217	// errors or terminate the process if an imported package is missing, and the218	// import path looks like it might be in the standard library (perhaps in a219	// future version).220	SilenceMissingStdImports bool221222	// SilenceNoGoErrors indicates that LoadPackages should not print223	// imports.ErrNoGo errors.224	// This allows the caller to invoke LoadPackages (and report other errors)225	// without knowing whether the requested packages exist for the given tags.226	//227	// Note that if a requested package does not exist *at all*, it will fail228	// during module resolution and the error will not be suppressed.229	SilenceNoGoErrors bool230231	// SilenceUnmatchedWarnings suppresses the warnings normally emitted for232	// patterns that did not match any packages.233	SilenceUnmatchedWarnings bool234235	// Resolve the query against this module.236	MainModule module.Version237238	// If Switcher is non-nil, then LoadPackages passes all encountered errors239	// to Switcher.Error and tries Switcher.Switch before base.ExitIfErrors.240	Switcher gover.Switcher241}242243// LoadPackages identifies the set of packages matching the given patterns and244// loads the packages in the import graph rooted at that set.245func LoadPackages(ld *Loader, ctx context.Context, opts PackageOpts, patterns ...string) (matches []*search.Match, loadedPackages []string) {246	if opts.Tags == nil {247		opts.Tags = imports.Tags()248	}249250	patterns = search.CleanPatterns(patterns)251	matches = make([]*search.Match, 0, len(patterns))252	allPatternIsRoot := false253	for _, pattern := range patterns {254		matches = append(matches, search.NewMatch(pattern))255		if pattern == "all" {256			allPatternIsRoot = true257		}258	}259260	updateMatches := func(rs *Requirements, pld *packageLoader) {261		for _, m := range matches {262			switch {263			case m.IsLocal():264				// Evaluate list of file system directories on first iteration.265				if m.Dirs == nil {266					matchModRoots := ld.modRoots267					if opts.MainModule != (module.Version{}) {268						matchModRoots = []string{ld.MainModules.ModRoot(opts.MainModule)}269					}270					matchLocalDirs(ld, ctx, matchModRoots, m, rs)271				}272273				// Make a copy of the directory list and translate to import paths.274				// Note that whether a directory corresponds to an import path275				// changes as the build list is updated, and a directory can change276				// from not being in the build list to being in it and back as277				// the exact version of a particular module increases during278				// the loader iterations.279				m.Pkgs = m.Pkgs[:0]280				for _, dir := range m.Dirs {281					var (282						pkg string283						err error284					)285					absDir := mkAbs(base.Cwd(), dir)286					if m.IsLiteral() {287						pkg, err = resolveLocalPackage(ld, ctx, absDir, rs)288					} else {289						// Wildcard matches have already been filtered to directories290						// that contain packages. Avoid re-reading package files on291						// every loader iteration just to map directory to import path.292						pkg, err = localPackagePath(ld, ctx, absDir, rs)293					}294					if err != nil {295						if !m.IsLiteral() && (err == errPkgIsBuiltin || err == errPkgIsGorootSrc) {296							continue // Don't include "builtin" or GOROOT/src in wildcard patterns.297						}298299						// If we're outside of a module, ensure that the failure mode300						// indicates that.301						if !ld.HasModRoot() {302							die(ld)303						}304305						if pld != nil {306							m.AddError(err)307						}308						continue309					}310					m.Pkgs = append(m.Pkgs, pkg)311				}312313			case m.IsLiteral():314				m.Pkgs = []string{m.Pattern()}315316			case strings.Contains(m.Pattern(), "..."):317				m.Errs = m.Errs[:0]318				mg, err := rs.Graph(ld, ctx)319				if err != nil {320					// The module graph is (or may be) incomplete — perhaps we failed to321					// load the requirements of some module. This is an error in matching322					// the patterns to packages, because we may be missing some packages323					// or we may erroneously match packages in the wrong versions of324					// modules. However, for cases like 'go list -e', the error should not325					// necessarily prevent us from loading the packages we could find.326					m.Errs = append(m.Errs, err)327				}328				matchPackages(ld, ctx, m, opts.Tags, includeStd, mg.BuildList())329330			case m.Pattern() == "work":331				matchModules := ld.MainModules.Versions()332				if opts.MainModule != (module.Version{}) {333					matchModules = []module.Version{opts.MainModule}334				}335				matchPackages(ld, ctx, m, opts.Tags, omitStd, matchModules)336337			case m.Pattern() == "all":338				if pld == nil {339					// The initial roots are the packages and tools in the main module.340					// loadFromRoots will expand that to "all".341					m.Errs = m.Errs[:0]342					matchModules := ld.MainModules.Versions()343					if opts.MainModule != (module.Version{}) {344						matchModules = []module.Version{opts.MainModule}345					}346					matchPackages(ld, ctx, m, opts.Tags, omitStd, matchModules)347					for tool := range ld.MainModules.Tools() {348						m.Pkgs = append(m.Pkgs, tool)349					}350				} else {351					// Starting with the packages in the main module,352					// enumerate the full list of "all".353					m.Pkgs = pld.computePatternAll()354				}355356			case m.Pattern() == "std" || m.Pattern() == "cmd":357				if m.Pkgs == nil {358					m.MatchPackages() // Locate the packages within GOROOT/src.359				}360361			case m.Pattern() == "tool":362				for tool := range ld.MainModules.Tools() {363					m.Pkgs = append(m.Pkgs, tool)364				}365			default:366				panic(fmt.Sprintf("internal error: modload missing case for pattern %s", m.Pattern()))367			}368		}369	}370371	initialRS, err := loadModFile(ld, ctx, &opts)372	if err != nil {373		base.Fatal(err)374	}375376	pld := loadFromRoots(ld, ctx, loaderParams{377		PackageOpts:  opts,378		requirements: initialRS,379380		allPatternIsRoot: allPatternIsRoot,381382		listRoots: func(rs *Requirements) (roots []string) {383			updateMatches(rs, nil)384			for _, m := range matches {385				roots = append(roots, m.Pkgs...)386			}387			return roots388		},389	})390391	// One last pass to finalize wildcards.392	updateMatches(pld.requirements, pld)393394	// List errors in matching patterns (such as directory permission395	// errors for wildcard patterns).396	if !pld.SilencePackageErrors {397		for _, match := range matches {398			for _, err := range match.Errs {399				pld.error(err)400			}401		}402	}403	pld.exitIfErrors(ctx)404405	if !opts.SilenceUnmatchedWarnings {406		search.WarnUnmatched(matches)407	}408409	if opts.Tidy {410		if cfg.BuildV {411			mg, _ := pld.requirements.Graph(ld, ctx)412			for _, m := range initialRS.rootModules {413				var unused bool414				if pld.requirements.pruning == unpruned {415					// m is unused if it was dropped from the module graph entirely. If it416					// was only demoted from direct to indirect, it may still be in use via417					// a transitive import.418					unused = mg.Selected(m.Path) == "none"419				} else {420					// m is unused if it was dropped from the roots. If it is still present421					// as a transitive dependency, that transitive dependency is not needed422					// by any package or test in the main module.423					_, ok := pld.requirements.rootSelected(ld, m.Path)424					unused = !ok425				}426				if unused {427					fmt.Fprintf(os.Stderr, "unused %s\n", m.Path)428				}429			}430		}431432		keep := keepSums(ld, ctx, pld, pld.requirements, loadedZipSumsOnly)433		compatVersion := pld.TidyCompatibleVersion434		goVersion := pld.requirements.GoVersion(ld)435		if compatVersion == "" {436			if gover.Compare(goVersion, gover.GoStrictVersion) < 0 {437				compatVersion = gover.Prev(goVersion)438			} else {439				// Starting at GoStrictVersion, we no longer maintain compatibility with440				// versions older than what is listed in the go.mod file.441				compatVersion = goVersion442			}443		}444		if gover.Compare(compatVersion, goVersion) > 0 {445			// Each version of the Go toolchain knows how to interpret go.mod and446			// go.sum files produced by all previous versions, so a compatibility447			// version higher than the go.mod version adds nothing.448			compatVersion = goVersion449		}450		if compatPruning := pruningForGoVersion(compatVersion); compatPruning != pld.requirements.pruning {451			compatRS := newRequirements(ld, compatPruning, pld.requirements.rootModules, pld.requirements.direct)452			pld.checkTidyCompatibility(ld, ctx, compatRS, compatVersion)453454			for m := range keepSums(ld, ctx, pld, compatRS, loadedZipSumsOnly) {455				keep[m] = true456			}457		}458459		if opts.TidyDiff {460			cfg.BuildMod = "readonly"461			ld.pkgLoader = pld462			ld.requirements = ld.pkgLoader.requirements463			currentGoMod, updatedGoMod, _, err := UpdateGoModFromReqs(ld, ctx, WriteOpts{})464			if err != nil {465				base.Fatal(err)466			}467			goModDiff := diff.Diff("current/go.mod", currentGoMod, "tidy/go.mod", updatedGoMod)468469			ld.Fetcher().TrimGoSum(keep)470			// Dropping compatibility for 1.16 may result in a strictly smaller go.sum.471			// Update the keep map with only the loaded.requirements.472			if gover.Compare(compatVersion, "1.16") > 0 {473				keep = keepSums(ld, ctx, ld.pkgLoader, ld.requirements, addBuildListZipSums)474			}475			currentGoSum, tidyGoSum := ld.fetcher.TidyGoSum(keep)476			goSumDiff := diff.Diff("current/go.sum", currentGoSum, "tidy/go.sum", tidyGoSum)477478			if len(goModDiff) > 0 {479				fmt.Println(string(goModDiff))480				base.SetExitStatus(1)481			}482			if len(goSumDiff) > 0 {483				fmt.Println(string(goSumDiff))484				base.SetExitStatus(1)485			}486			base.Exit()487		}488489		if !ExplicitWriteGoMod {490			ld.Fetcher().TrimGoSum(keep)491492			// commitRequirements below will also call WriteGoSum, but the "keep" map493			// we have here could be strictly larger: commitRequirements only commits494			// loaded.requirements, but here we may have also loaded (and want to495			// preserve checksums for) additional entities from compatRS, which are496			// only needed for compatibility with ld.TidyCompatibleVersion.497			if err := ld.Fetcher().WriteGoSum(ctx, keep, mustHaveCompleteRequirements(ld)); err != nil {498				base.Fatal(err)499			}500		}501	}502503	if opts.TidyDiff && !opts.Tidy {504		panic("TidyDiff is set but Tidy is not.")505	}506507	// Success! Update go.mod and go.sum (if needed) and return the results.508	// We'll skip updating if ExplicitWriteGoMod is true (the caller has opted509	// to call WriteGoMod itself) or if ResolveMissingImports is false (the510	// command wants to examine the package graph as-is).511	ld.pkgLoader = pld512	ld.requirements = ld.pkgLoader.requirements513514	for _, pkg := range pld.pkgs {515		if !pkg.isTest() {516			loadedPackages = append(loadedPackages, pkg.path)517		}518	}519	sort.Strings(loadedPackages)520521	if !ExplicitWriteGoMod && opts.ResolveMissingImports {522		if err := commitRequirements(ld, ctx, WriteOpts{}); err != nil {523			base.Fatal(err)524		}525	}526527	return matches, loadedPackages528}529530// matchLocalDirs is like m.MatchDirs, but tries to avoid scanning directories531// outside of the standard library and active modules.532func matchLocalDirs(ld *Loader, ctx context.Context, modRoots []string, m *search.Match, rs *Requirements) {533	if !m.IsLocal() {534		panic(fmt.Sprintf("internal error: resolveLocalDirs on non-local pattern %s", m.Pattern()))535	}536537	if i := strings.Index(m.Pattern(), "..."); i >= 0 {538		// The pattern is local, but it is a wildcard. Its packages will539		// only resolve to paths if they are inside of the standard540		// library, the main module, or some dependency of the main541		// module. Verify that before we walk the filesystem: a filesystem542		// walk in a directory like /var or /etc can be very expensive!543		dir := filepath.Dir(filepath.Clean(m.Pattern()[:i+3]))544		absDir := mkAbs(base.Cwd(), dir)545546		modRoot := findModuleRoot(absDir)547		if !slices.Contains(modRoots, modRoot) && search.InDir(absDir, cfg.GOROOTsrc) == "" && pathInModuleCache(ld, ctx, absDir, rs) == "" {548			m.Dirs = []string{}549			scope := "main module or its selected dependencies"550			if ld.inWorkspaceMode() {551				scope = "modules listed in go.work or their selected dependencies"552			}553			m.AddError(fmt.Errorf("directory prefix %s does not contain %s", base.ShortPath(absDir), scope))554			return555		}556	}557558	m.MatchDirs(modRoots)559}560561// resolveLocalPackage resolves a filesystem path to a package path.562func resolveLocalPackage(ld *Loader, ctx context.Context, absDir string, rs *Requirements) (string, error) {563	bp, err := cfg.BuildContext.ImportDir(absDir, 0)564	if err != nil && (bp == nil || len(bp.IgnoredGoFiles) == 0) {565		// golang.org/issue/32917: We should resolve a relative path to a566		// package path only if the relative path actually contains the code567		// for that package.568		//569		// If the named directory does not exist or contains no Go files,570		// the package does not exist.571		// Other errors may affect package loading, but not resolution.572		if _, err := fsys.Stat(absDir); err != nil {573			if os.IsNotExist(err) {574				// Canonicalize OS-specific errors to errDirectoryNotFound so that error575				// messages will be easier for users to search for.576				return "", &fs.PathError{Op: "stat", Path: absDir, Err: errDirectoryNotFound}577			}578			return "", err579		}580		if _, noGo := err.(*build.NoGoError); noGo {581			// A directory that does not contain any Go source files — even ignored582			// ones! — is not a Go package, and we can't resolve it to a package583			// path because that path could plausibly be provided by some other584			// module.585			//586			// Any other error indicates that the package “exists” (at least in the587			// sense that it cannot exist in any other module), but has some other588			// problem (such as a syntax error).589			return "", err590		}591	}592593	return localPackagePath(ld, ctx, absDir, rs)594}595596func mkAbs(wd, path string) string {597	if filepath.IsAbs(path) {598		return filepath.Clean(path)599	}600	return filepath.Join(wd, path)601}602603// localPackagePath resolves an absolute filesystem path to a package path.604// The caller must have already verified that absDir contains a package.605func localPackagePath(ld *Loader, ctx context.Context, absDir string, rs *Requirements) (string, error) {606	for _, mod := range ld.MainModules.Versions() {607		modRoot := ld.MainModules.ModRoot(mod)608		if modRoot != "" && absDir == modRoot {609			if absDir == cfg.GOROOTsrc {610				return "", errPkgIsGorootSrc611			}612			return ld.MainModules.PathPrefix(mod), nil613		}614	}615616	// Note: The checks for @ here are just to avoid misinterpreting617	// the module cache directories (formerly GOPATH/src/mod/foo@v1.5.2/bar).618	// It's not strictly necessary but helpful to keep the checks.619	var pkgNotFoundErr error620	pkgNotFoundLongestPrefix := ""621	for _, mainModule := range ld.MainModules.Versions() {622		modRoot := ld.MainModules.ModRoot(mainModule)623		if modRoot != "" && str.HasFilePathPrefix(absDir, modRoot) && !strings.Contains(absDir[len(modRoot):], "@") {624			suffix := filepath.ToSlash(str.TrimFilePathPrefix(absDir, modRoot))625			if pkg, found := strings.CutPrefix(suffix, "vendor/"); found {626				if cfg.BuildMod != "vendor" {627					return "", fmt.Errorf("without -mod=vendor, directory %s has no package path", absDir)628				}629630				readVendorList(VendorDir(ld))631				if _, ok := vendorPkgModule[pkg]; !ok {632					return "", fmt.Errorf("directory %s is not a package listed in vendor/modules.txt", absDir)633				}634				return pkg, nil635			}636637			mainModulePrefix := ld.MainModules.PathPrefix(mainModule)638			if mainModulePrefix == "" {639				pkg := suffix640				if pkg == "builtin" {641					// "builtin" is a pseudo-package with a real source file.642					// It's not included in "std", so it shouldn't resolve from "."643					// within module "std" either.644					return "", errPkgIsBuiltin645				}646				return pkg, nil647			}648649			pkg := pathpkg.Join(mainModulePrefix, suffix)650			if _, ok, err := dirInModule(pkg, mainModulePrefix, modRoot, true); err != nil {651				return "", err652			} else if !ok {653				// This main module could contain the directory but doesn't. Other main654				// modules might contain the directory, so wait till we finish the loop655				// to see if another main module contains directory. But if not,656				// return an error.657				if len(mainModulePrefix) > len(pkgNotFoundLongestPrefix) {658					pkgNotFoundLongestPrefix = mainModulePrefix659					pkgNotFoundErr = &PackageNotInModuleError{MainModules: []module.Version{mainModule}, Pattern: pkg}660				}661				continue662			}663			return pkg, nil664		}665	}666	if pkgNotFoundErr != nil {667		return "", pkgNotFoundErr668	}669670	if sub := search.InDir(absDir, cfg.GOROOTsrc); sub != "" && sub != "." && !strings.Contains(sub, "@") {671		pkg := filepath.ToSlash(sub)672		if pkg == "builtin" {673			return "", errPkgIsBuiltin674		}675		return pkg, nil676	}677678	pkg := pathInModuleCache(ld, ctx, absDir, rs)679	if pkg == "" {680		dirstr := fmt.Sprintf("directory %s", base.ShortPath(absDir))681		if dirstr == "directory ." {682			dirstr = "current directory"683		}684		if ld.inWorkspaceMode() {685			if mr := findModuleRoot(absDir); mr != "" {686				return "", fmt.Errorf("%s is contained in a module that is not one of the workspace modules listed in go.work. You can add the module to the workspace using:\n\tgo work use %s", dirstr, base.ShortPath(mr))687			}688			return "", fmt.Errorf("%s outside modules listed in go.work or their selected dependencies", dirstr)689		}690		return "", fmt.Errorf("%s outside main module or its selected dependencies", dirstr)691	}692	return pkg, nil693}694695var (696	errDirectoryNotFound = errors.New("directory not found")697	errPkgIsGorootSrc    = errors.New("GOROOT/src is not an importable package")698	errPkgIsBuiltin      = errors.New(`"builtin" is a pseudo-package, not an importable package`)699)700701// pathInModuleCache returns the import path of the directory dir,702// if dir is in the module cache copy of a module in our build list.703func pathInModuleCache(ld *Loader, ctx context.Context, dir string, rs *Requirements) string {704	tryMod := func(m module.Version) (string, bool) {705		if gover.IsToolchain(m.Path) {706			return "", false707		}708		var root string709		var err error710		if repl := Replacement(ld, m); repl.Path != "" && repl.Version == "" {711			root = repl.Path712			if !filepath.IsAbs(root) {713				root = filepath.Join(replaceRelativeTo(ld), root)714			}715		} else if repl.Path != "" {716			root, err = modfetch.DownloadDir(ctx, repl)717		} else {718			root, err = modfetch.DownloadDir(ctx, m)719		}720		if err != nil {721			return "", false722		}723724		sub := search.InDir(dir, root)725		if sub == "" {726			return "", false727		}728		sub = filepath.ToSlash(sub)729		if strings.Contains(sub, "/vendor/") || strings.HasPrefix(sub, "vendor/") || strings.Contains(sub, "@") {730			return "", false731		}732733		return pathpkg.Join(m.Path, filepath.ToSlash(sub)), true734	}735736	if rs.pruning == pruned {737		for _, m := range rs.rootModules {738			if v, _ := rs.rootSelected(ld, m.Path); v != m.Version {739				continue // m is a root, but we have a higher root for the same path.740			}741			if importPath, ok := tryMod(m); ok {742				// checkMultiplePaths ensures that a module can be used for at most one743				// requirement, so this must be it.744				return importPath745			}746		}747	}748749	// None of the roots contained dir, or the graph is unpruned (so we don't want750	// to distinguish between roots and transitive dependencies). Either way,751	// check the full graph to see if the directory is a non-root dependency.752	//753	// If the roots are not consistent with the full module graph, the selected754	// versions of root modules may differ from what we already checked above.755	// Re-check those paths too.756757	mg, _ := rs.Graph(ld, ctx)758	var importPath string759	for _, m := range mg.BuildList() {760		var found bool761		importPath, found = tryMod(m)762		if found {763			break764		}765	}766	return importPath767}768769// ImportFromFiles adds modules to the build list as needed770// to satisfy the imports in the named Go source files.771//772// Errors in missing dependencies are silenced.773//774// TODO(bcmills): Silencing errors seems off. Take a closer look at this and775// figure out what the error-reporting actually ought to be.776func ImportFromFiles(ld *Loader, ctx context.Context, gofiles []string) {777	rs := LoadModFile(ld, ctx)778779	tags := imports.Tags()780	imports, testImports, err := imports.ScanFiles(gofiles, tags)781	if err != nil {782		base.Fatal(err)783	}784785	ld.pkgLoader = loadFromRoots(ld, ctx, loaderParams{786		PackageOpts: PackageOpts{787			Tags:                  tags,788			ResolveMissingImports: true,789			SilencePackageErrors:  true,790		},791		requirements: rs,792		listRoots: func(*Requirements) (roots []string) {793			roots = append(roots, imports...)794			roots = append(roots, testImports...)795			return roots796		},797	})798	ld.requirements = ld.pkgLoader.requirements799800	if !ExplicitWriteGoMod {801		if err := commitRequirements(ld, ctx, WriteOpts{}); err != nil {802			base.Fatal(err)803		}804	}805}806807// DirImportPath returns the effective import path for dir,808// provided it is within a main module, or else returns ".".809func (mms *MainModuleSet) DirImportPath(ld *Loader, ctx context.Context, dir string) (path string, m module.Version) {810	if !ld.HasModRoot() {811		return ".", module.Version{}812	}813	LoadModFile(ld, ctx) // Sets targetPrefix.814815	if !filepath.IsAbs(dir) {816		dir = filepath.Join(base.Cwd(), dir)817	} else {818		dir = filepath.Clean(dir)819	}820821	var longestPrefix string822	var longestPrefixPath string823	var longestPrefixVersion module.Version824	for _, v := range mms.Versions() {825		modRoot := mms.ModRoot(v)826		if dir == modRoot {827			return mms.PathPrefix(v), v828		}829		if str.HasFilePathPrefix(dir, modRoot) {830			pathPrefix := ld.MainModules.PathPrefix(v)831			if pathPrefix > longestPrefix {832				longestPrefix = pathPrefix833				longestPrefixVersion = v834				suffix := filepath.ToSlash(str.TrimFilePathPrefix(dir, modRoot))835				if strings.HasPrefix(suffix, "vendor/") {836					longestPrefixPath = suffix[len("vendor/"):]837					continue838				}839				longestPrefixPath = pathpkg.Join(mms.PathPrefix(v), suffix)840			}841		}842	}843	if len(longestPrefix) > 0 {844		return longestPrefixPath, longestPrefixVersion845	}846847	return ".", module.Version{}848}849850// PackageModule returns the module providing the package named by the import path.851func (ld *Loader) PackageModule(path string) module.Version {852	pkg, ok := ld.pkgLoader.pkgCache.Get(path)853	if !ok {854		return module.Version{}855	}856	return pkg.mod857}858859// Lookup returns the source directory, import path, and any loading error for860// the package at path as imported from the package in parentDir.861// Lookup requires that one of the Load functions in this package has already862// been called.863func Lookup(ld *Loader, parentPath string, parentIsStd bool, path string) (dir, realPath string, err error) {864	if path == "" {865		panic("Lookup called with empty package path")866	}867868	if parentIsStd {869		path = ld.pkgLoader.stdVendor(ld, parentPath, path)870	}871	pkg, ok := ld.pkgLoader.pkgCache.Get(path)872	if !ok {873		// The loader should have found all the relevant paths.874		// There are a few exceptions, though:875		//	- during go list without -test, the p.Resolve calls to process p.TestImports and p.XTestImports876		//	  end up here to canonicalize the import paths.877		//	- during any load, non-loaded packages like "unsafe" end up here.878		//	- during any load, build-injected dependencies like "runtime/cgo" end up here.879		//	- because we ignore appengine/* in the module loader,880		//	  the dependencies of any actual appengine/* library end up here.881		dir := findStandardImportPath(path)882		if dir != "" {883			return dir, path, nil884		}885		return "", "", errMissing886	}887	return pkg.dir, pkg.path, pkg.err888}889890// A packageLoader manages the process of loading information about891// the required packages for a particular build,892// checking that the packages are available in the module set,893// and updating the module set if needed.894type packageLoader struct {895	loaderParams896897	// allClosesOverTests indicates whether the "all" pattern includes898	// dependencies of tests outside the main module (as in Go 1.11–1.15).899	// (Otherwise — as in Go 1.16+ — the "all" pattern includes only the packages900	// transitively *imported by* the packages and tests in the main module.)901	allClosesOverTests bool902903	// skipImportModFiles indicates whether we may skip loading go.mod files904	// for imported packages (as in 'go mod tidy' in Go 1.17–1.20).905	skipImportModFiles bool906907	work *par.Queue908909	// reset on each iteration910	roots    []*loadPkg911	pkgCache *par.Cache[string, *loadPkg]912	pkgs     []*loadPkg // transitive closure of loaded packages and tests; populated in buildStacks913}914915// loaderParams configure the packages loaded by, and the properties reported916// by, a loader instance.917type loaderParams struct {918	PackageOpts919	requirements *Requirements920921	allPatternIsRoot bool // Is the "all" pattern an additional root?922923	listRoots func(rs *Requirements) []string924}925926func (pld *packageLoader) reset() {927	select {928	case <-pld.work.Idle():929	default:930		panic("loader.reset when not idle")931	}932933	pld.roots = nil934	pld.pkgCache = new(par.Cache[string, *loadPkg])935	pld.pkgs = nil936}937938// error reports an error via either os.Stderr or base.Error,939// according to whether ld.AllowErrors is set.940func (pld *packageLoader) error(err error) {941	if pld.AllowErrors {942		fmt.Fprintf(os.Stderr, "go: %v\n", err)943	} else if pld.Switcher != nil {944		pld.Switcher.Error(err)945	} else {946		base.Error(err)947	}948}949950// switchIfErrors switches toolchains if a switch is needed.951func (pld *packageLoader) switchIfErrors(ctx context.Context) {952	if pld.Switcher != nil {953		pld.Switcher.Switch(ctx)954	}955}956957// exitIfErrors switches toolchains if a switch is needed958// or else exits if any errors have been reported.959func (pld *packageLoader) exitIfErrors(ctx context.Context) {960	pld.switchIfErrors(ctx)961	base.ExitIfErrors()962}963964// goVersion reports the Go version that should be used for the loader's965// requirements: ld.TidyGoVersion if set, or ld.requirements.GoVersion()966// otherwise.967func (pld *packageLoader) goVersion(ld *Loader) string {968	if pld.TidyGoVersion != "" {969		return pld.TidyGoVersion970	}971	return pld.requirements.GoVersion(ld)972}973974// A loadPkg records information about a single loaded package.975type loadPkg struct {976	// Populated at construction time:977	path   string // import path978	testOf *loadPkg979980	// Populated at construction time and updated by (*packageLoader).applyPkgFlags:981	flags atomicLoadPkgFlags982983	// Populated by (*packageLoader).load:984	mod         module.Version // module providing package985	dir         string         // directory containing source code986	err         error          // error loading package987	imports     []*loadPkg     // packages imported by this one988	testImports []string       // test-only imports, saved for use by pkg.test.989	inStd       bool990	altMods     []module.Version // modules that could have contained the package but did not991992	// Populated by (*packageLoader).pkgTest:993	testOnce sync.Once994	test     *loadPkg995996	// Populated by postprocessing in (*packageLoader).buildStacks:997	stack *loadPkg // package importing this one in minimal import stack for this pkg998}9991000// loadPkgFlags is a set of flags tracking metadata about a package.1001type loadPkgFlags int810021003const (1004	// pkgInAll indicates that the package is in the "all" package pattern,1005	// regardless of whether we are loading the "all" package pattern.1006	//1007	// When the pkgInAll flag and pkgImportsLoaded flags are both set, the caller1008	// who set the last of those flags must propagate the pkgInAll marking to all1009	// of the imports of the marked package.1010	//1011	// A test is marked with pkgInAll if that test would promote the packages it1012	// imports to be in "all" (such as when the test is itself within the main1013	// module, or when ld.allClosesOverTests is true).1014	pkgInAll loadPkgFlags = 1 << iota10151016	// pkgIsRoot indicates that the package matches one of the root package1017	// patterns requested by the caller.1018	//1019	// If LoadTests is set, then when pkgIsRoot and pkgImportsLoaded are both set,1020	// the caller who set the last of those flags must populate a test for the1021	// package (in the pkg.test field).1022	//1023	// If the "all" pattern is included as a root, then non-test packages in "all"1024	// are also roots (and must be marked pkgIsRoot).1025	pkgIsRoot10261027	// pkgFromRoot indicates that the package is in the transitive closure of1028	// imports starting at the roots. (Note that every package marked as pkgIsRoot1029	// is also trivially marked pkgFromRoot.)1030	pkgFromRoot10311032	// pkgImportsLoaded indicates that the imports and testImports fields of a1033	// loadPkg have been populated.1034	pkgImportsLoaded1035)10361037// has reports whether all of the flags in cond are set in f.1038func (f loadPkgFlags) has(cond loadPkgFlags) bool {1039	return f&cond == cond1040}10411042// An atomicLoadPkgFlags stores a loadPkgFlags for which individual flags can be1043// added atomically.1044type atomicLoadPkgFlags struct {1045	bits atomic.Int321046}10471048// update sets the given flags in af (in addition to any flags already set).1049//1050// update returns the previous flag state so that the caller may determine which1051// flags were newly-set.1052func (af *atomicLoadPkgFlags) update(flags loadPkgFlags) (old loadPkgFlags) {1053	for {1054		old := af.bits.Load()1055		new := old | int32(flags)1056		if new == old || af.bits.CompareAndSwap(old, new) {1057			return loadPkgFlags(old)1058		}1059	}1060}10611062// has reports whether all of the flags in cond are set in af.1063func (af *atomicLoadPkgFlags) has(cond loadPkgFlags) bool {1064	return loadPkgFlags(af.bits.Load())&cond == cond1065}10661067// isTest reports whether pkg is a test of another package.1068func (pkg *loadPkg) isTest() bool {1069	return pkg.testOf != nil1070}10711072// fromExternalModule reports whether pkg was loaded from a module other than1073// the main module.1074func (pkg *loadPkg) fromExternalModule(ld *Loader) bool {1075	if pkg.mod.Path == "" {1076		return false // loaded from the standard library, not a module1077	}1078	return !ld.MainModules.Contains(pkg.mod.Path)1079}10801081var errMissing = errors.New("cannot find package")10821083// loadFromRoots attempts to load the build graph needed to process a set of1084// root packages and their dependencies.1085//1086// The set of root packages is returned by the params.listRoots function, and1087// expanded to the full set of packages by tracing imports (and possibly tests)1088// as needed.1089func loadFromRoots(ld *Loader, ctx context.Context, params loaderParams) *packageLoader {1090	pld := &packageLoader{1091		loaderParams: params,1092		work:         par.NewQueue(runtime.GOMAXPROCS(0)),1093	}10941095	if pld.requirements.pruning == unpruned {1096		// If the module graph does not support pruning, we assume that we will need1097		// the full module graph in order to load package dependencies.1098		//1099		// This might not be strictly necessary, but it matches the historical1100		// behavior of the 'go' command and keeps the go.mod file more consistent in1101		// case of erroneous hand-edits — which are less likely to be detected by1102		// spot-checks in modules that do not maintain the expanded go.mod1103		// requirements needed for graph pruning.1104		var err error1105		pld.requirements, _, err = expandGraph(ld, ctx, pld.requirements)1106		if err != nil {1107			pld.error(err)1108		}1109	}1110	pld.exitIfErrors(ctx)11111112	updateGoVersion := func() {1113		goVersion := pld.goVersion(ld)11141115		if pld.requirements.pruning != workspace {1116			var err error1117			pld.requirements, err = convertPruning(ld, ctx, pld.requirements, pruningForGoVersion(goVersion))1118			if err != nil {1119				pld.error(err)1120				pld.exitIfErrors(ctx)1121			}1122		}11231124		// If the module's Go version omits go.sum entries for go.mod files for test1125		// dependencies of external packages, avoid loading those files in the first1126		// place.1127		pld.skipImportModFiles = pld.Tidy && gover.Compare(goVersion, gover.TidyGoModSumVersion) < 011281129		// If the module's go version explicitly predates the change in "all" for1130		// graph pruning, continue to use the older interpretation.1131		pld.allClosesOverTests = gover.Compare(goVersion, gover.NarrowAllVersion) < 0 && !pld.UseVendorAll1132	}11331134	for {1135		pld.reset()1136		updateGoVersion()11371138		// Load the root packages and their imports.1139		// Note: the returned roots can change on each iteration,1140		// since the expansion of package patterns depends on the1141		// build list we're using.1142		rootPkgs := pld.listRoots(pld.requirements)11431144		if pld.requirements.pruning == pruned && cfg.BuildMod == "mod" {1145			// Before we start loading transitive imports of packages, locate all of1146			// the root packages and promote their containing modules to root modules1147			// dependencies. If their go.mod files are tidy (the common case) and the1148			// set of root packages does not change then we can select the correct1149			// versions of all transitive imports on the first try and complete1150			// loading in a single iteration.1151			changedBuildList := pld.preloadRootModules(ld, ctx, rootPkgs)1152			if changedBuildList {1153				// The build list has changed, so the set of root packages may have also1154				// changed. Start over to pick up the changes. (Preloading roots is much1155				// cheaper than loading the full import graph, so we would rather pay1156				// for an extra iteration of preloading than potentially end up1157				// discarding the result of a full iteration of loading.)1158				continue1159			}1160		}11611162		inRoots := map[*loadPkg]bool{}1163		for _, path := range rootPkgs {1164			root := pld.pkg(ld, ctx, path, pkgIsRoot)1165			if !inRoots[root] {1166				pld.roots = append(pld.roots, root)1167				inRoots[root] = true1168			}1169		}11701171		// ld.pkg adds imported packages to the work queue and calls applyPkgFlags,1172		// which adds tests (and test dependencies) as needed.1173		//1174		// When all of the work in the queue has completed, we'll know that the1175		// transitive closure of dependencies has been loaded.1176		<-pld.work.Idle()11771178		pld.buildStacks()11791180		changed, err := pld.updateRequirements(ld, ctx)1181		if err != nil {1182			pld.error(err)1183			break1184		}1185		if changed {1186			// Don't resolve missing imports until the module graph has stabilized.1187			// If the roots are still changing, they may turn out to specify a1188			// requirement on the missing package(s), and we would rather use a1189			// version specified by a new root than add a new dependency on an1190			// unrelated version.1191			continue1192		}11931194		if !pld.ResolveMissingImports || (!ld.HasModRoot() && !ld.allowMissingModuleImports) {1195			// We've loaded as much as we can without resolving missing imports.1196			break1197		}11981199		modAddedBy, err := pld.resolveMissingImports(ld, ctx)1200		if err != nil {1201			pld.error(err)1202			break1203		}1204		if len(modAddedBy) == 0 {1205			// The roots are stable, and we've resolved all of the missing packages1206			// that we can.1207			break1208		}12091210		toAdd := make([]module.Version, 0, len(modAddedBy))1211		for m := range modAddedBy {1212			toAdd = append(toAdd, m)1213		}1214		gover.ModSort(toAdd) // to make errors deterministic12151216		// We ran updateRequirements before resolving missing imports and it didn't1217		// make any changes, so we know that the requirement graph is already1218		// consistent with ld.pkgs: we don't need to pass ld.pkgs to updateRoots1219		// again. (That would waste time looking for changes that we have already1220		// applied.)1221		var noPkgs []*loadPkg1222		// We also know that we're going to call updateRequirements again next1223		// iteration so we don't need to also update it here. (That would waste time1224		// computing a "direct" map that we'll have to recompute later anyway.)1225		direct := pld.requirements.direct1226		rs, err := updateRoots(ld, ctx, direct, pld.requirements, noPkgs, toAdd, pld.AssumeRootsImported)1227		if err != nil {1228			// If an error was found in a newly added module, report the package1229			// import stack instead of the module requirement stack. Packages1230			// are more descriptive.1231			if err, ok := err.(*mvs.BuildListError); ok {1232				if pkg := modAddedBy[err.Module()]; pkg != nil {1233					pld.error(fmt.Errorf("%s: %w", pkg.stackText(), err.Err))1234					break1235				}1236			}1237			pld.error(err)1238			break1239		}1240		if slices.Equal(rs.rootModules, pld.requirements.rootModules) {1241			// Something is deeply wrong. resolveMissingImports gave us a non-empty1242			// set of modules to add to the graph, but adding those modules had no1243			// effect — either they were already in the graph, or updateRoots did not1244			// add them as requested.1245			panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules))1246		}1247		pld.requirements = rs1248	}1249	pld.exitIfErrors(ctx)12501251	// Tidy the build list, if applicable, before we report errors.1252	// (The process of tidying may remove errors from irrelevant dependencies.)1253	if pld.Tidy {1254		rs, err := tidyRoots(ld, ctx, pld.requirements, pld.pkgs)1255		if err != nil {1256			pld.error(err)1257		} else {1258			if pld.TidyGoVersion != "" {1259				// Attempt to switch to the requested Go version. We have been using its1260				// pruning and semantics all along, but there may have been — and may1261				// still be — requirements on higher versions in the graph.1262				tidy := overrideRoots(ld, ctx, rs, []module.Version{{Path: "go", Version: pld.TidyGoVersion}})1263				mg, err := tidy.Graph(ld, ctx)1264				if err != nil {1265					pld.error(err)1266				}1267				if v := mg.Selected("go"); v == pld.TidyGoVersion {1268					rs = tidy1269				} else {1270					conflict := Conflict{1271						Path: mg.g.FindPath(func(m module.Version) bool {1272							return m.Path == "go" && m.Version == v1273						})[1:],1274						Constraint: module.Version{Path: "go", Version: pld.TidyGoVersion},1275					}1276					msg := conflict.Summary()1277					if cfg.BuildV {1278						msg = conflict.String()1279					}1280					pld.error(errors.New(msg))1281				}1282			}12831284			if pld.requirements.pruning == pruned {1285				// We continuously add tidy roots to ld.requirements during loading, so1286				// at this point the tidy roots (other than possibly the "go" version1287				// edited above) should be a subset of the roots of ld.requirements,1288				// ensuring that no new dependencies are brought inside the1289				// graph-pruning horizon.1290				// If that is not the case, there is a bug in the loading loop above.1291				for _, m := range rs.rootModules {1292					if m.Path == "go" && pld.TidyGoVersion != "" {1293						continue1294					}1295					if v, ok := pld.requirements.rootSelected(ld, m.Path); !ok || v != m.Version {1296						pld.error(fmt.Errorf("internal error: a requirement on %v is needed but was not added during package loading (selected %s)", m, v))1297					}1298				}1299			}13001301			pld.requirements = rs1302		}13031304		pld.exitIfErrors(ctx)1305	}13061307	// Report errors, if any.1308	for _, pkg := range pld.pkgs {1309		if pkg.err == nil {1310			continue1311		}13121313		// Add importer information to checksum errors.1314		if sumErr, ok := errors.AsType[*ImportMissingSumError](pkg.err); ok {1315			if importer := pkg.stack; importer != nil {1316				sumErr.importer = importer.path1317				sumErr.importerVersion = importer.mod.Version1318				sumErr.importerIsTest = importer.testOf != nil1319			}1320		}13211322		if stdErr, ok := errors.AsType[*ImportMissingError](pkg.err); ok && stdErr.isStd {1323			// Add importer go version information to import errors of standard1324			// library packages arising from newer releases.1325			if importer := pkg.stack; importer != nil {1326				if v, ok := rawGoVersion.Load(importer.mod); ok && gover.Compare(gover.Local(), v.(string)) < 0 {1327					stdErr.importerGoVersion = v.(string)1328				}1329			}1330			if pld.SilenceMissingStdImports {1331				continue1332			}1333		}1334		if pld.SilencePackageErrors {1335			continue1336		}1337		if pld.SilenceNoGoErrors && errors.Is(pkg.err, imports.ErrNoGo) {1338			continue1339		}13401341		pld.error(fmt.Errorf("%s: %w", pkg.stackText(), pkg.err))1342	}13431344	pld.checkMultiplePaths(ld)1345	return pld1346}13471348// updateRequirements ensures that ld.requirements is consistent with the1349// information gained from ld.pkgs.1350//1351// In particular:1352//1353//   - Modules that provide packages directly imported from the main module are1354//     marked as direct, and are promoted to explicit roots. If a needed root1355//     cannot be promoted due to -mod=readonly or -mod=vendor, the importing1356//     package is marked with an error.1357//1358//   - If ld scanned the "all" pattern independent of build constraints, it is1359//     guaranteed to have seen every direct import. Module dependencies that did1360//     not provide any directly-imported package are then marked as indirect.1361//1362//   - Root dependencies are updated to their selected versions.1363//1364// The "changed" return value reports whether the update changed the selected1365// version of any module that either provided a loaded package or may now1366// provide a package that was previously unresolved.1367func (pld *packageLoader) updateRequirements(ld *Loader, ctx context.Context) (changed bool, err error) {1368	rs := pld.requirements13691370	// direct contains the set of modules believed to provide packages directly1371	// imported by the main module.1372	var direct map[string]bool13731374	// If we didn't scan all of the imports from the main module, or didn't use1375	// imports.AnyTags, then we didn't necessarily load every package that1376	// contributes “direct” imports — so we can't safely mark existing direct1377	// dependencies in ld.requirements as indirect-only. Propagate them as direct.1378	loadedDirect := pld.allPatternIsRoot && maps.Equal(pld.Tags, imports.AnyTags())1379	if loadedDirect {1380		direct = make(map[string]bool)1381	} else {1382		// TODO(bcmills): It seems like a shame to allocate and copy a map here when1383		// it will only rarely actually vary from rs.direct. Measure this cost and1384		// maybe avoid the copy.1385		direct = make(map[string]bool, len(rs.direct))1386		for mPath := range rs.direct {1387			direct[mPath] = true1388		}1389	}13901391	var maxTooNew *gover.TooNewError1392	for _, pkg := range pld.pkgs {1393		if pkg.err != nil {1394			if tooNew, ok := errors.AsType[*gover.TooNewError](pkg.err); ok {1395				if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 {1396					maxTooNew = tooNew1397				}1398			}1399		}1400		if pkg.mod.Version != "" || !ld.MainModules.Contains(pkg.mod.Path) {1401			continue1402		}14031404		for _, dep := range pkg.imports {1405			if !dep.fromExternalModule(ld) {1406				continue1407			}14081409			if ld.inWorkspaceMode() {1410				// In workspace mode / workspace pruning mode, the roots are the main modules1411				// rather than the main module's direct dependencies. The check below on the selected1412				// roots does not apply.1413				if cfg.BuildMod == "vendor" {1414					// In workspace vendor mode, we don't need to load the requirements of the workspace1415					// modules' dependencies so the check below doesn't work. But that's okay, because1416					// checking whether modules are required directly for the purposes of pruning is1417					// less important in vendor mode: if we were able to load the package, we have1418					// everything we need  to build the package, and dependencies' tests are pruned out1419					// of the vendor directory anyway.1420					continue1421				}1422				if mg, err := rs.Graph(ld, ctx); err != nil {1423					return false, err1424				} else if _, ok := mg.RequiredBy(dep.mod); !ok {1425					// dep.mod is not an explicit dependency, but needs to be.1426					// See comment on error returned below.1427					pkg.err = &DirectImportFromImplicitDependencyError{1428						ImporterPath: pkg.path,1429						ImportedPath: dep.path,1430						Module:       dep.mod,1431					}1432				}1433			} else if pkg.err == nil && cfg.BuildMod != "mod" {1434				if v, ok := rs.rootSelected(ld, dep.mod.Path); !ok || v != dep.mod.Version {1435					// dep.mod is not an explicit dependency, but needs to be.1436					// Because we are not in "mod" mode, we will not be able to update it.1437					// Instead, mark the importing package with an error.1438					//1439					// TODO(#41688): The resulting error message fails to include the file1440					// position of the import statement (because that information is not1441					// tracked by the module loader). Figure out how to plumb the import1442					// position through.1443					pkg.err = &DirectImportFromImplicitDependencyError{1444						ImporterPath: pkg.path,1445						ImportedPath: dep.path,1446						Module:       dep.mod,1447					}1448					// cfg.BuildMod does not allow us to change dep.mod to be a direct1449					// dependency, so don't mark it as such.1450					continue1451				}1452			}14531454			// dep is a package directly imported by a package or test in the main1455			// module and loaded from some other module (not the standard library).1456			// Mark its module as a direct dependency.1457			direct[dep.mod.Path] = true1458		}1459	}1460	if maxTooNew != nil {1461		return false, maxTooNew1462	}14631464	var addRoots []module.Version1465	if pld.Tidy {1466		// When we are tidying a module with a pruned dependency graph, we may need1467		// to add roots to preserve the versions of indirect, test-only dependencies1468		// that are upgraded above or otherwise missing from the go.mod files of1469		// direct dependencies. (For example, the direct dependency might be a very1470		// stable codebase that predates modules and thus lacks a go.mod file, or1471		// the author of the direct dependency may have forgotten to commit a change1472		// to the go.mod file, or may have made an erroneous hand-edit that causes1473		// it to be untidy.)1474		//1475		// Promoting an indirect dependency to a root adds the next layer of its1476		// dependencies to the module graph, which may increase the selected1477		// versions of other modules from which we have already loaded packages.1478		// So after we promote an indirect dependency to a root, we need to reload1479		// packages, which means another iteration of loading.1480		//1481		// As an extra wrinkle, the upgrades due to promoting a root can cause1482		// previously-resolved packages to become unresolved. For example, the1483		// module providing an unstable package might be upgraded to a version1484		// that no longer contains that package. If we then resolve the missing1485		// package, we might add yet another root that upgrades away some other1486		// dependency. (The tests in mod_tidy_convergence*.txt illustrate some1487		// particularly worrisome cases.)1488		//1489		// To ensure that this process of promoting, adding, and upgrading roots1490		// eventually terminates, during iteration we only ever add modules to the1491		// root set — we only remove irrelevant roots at the very end of1492		// iteration, after we have already added every root that we plan to need1493		// in the (eventual) tidy root set.1494		//1495		// Since we do not remove any roots during iteration, even if they no1496		// longer provide any imported packages, the selected versions of the1497		// roots can only increase and the set of roots can only expand. The set1498		// of extant root paths is finite and the set of versions of each path is1499		// finite, so the iteration *must* reach a stable fixed-point.1500		tidy, err := tidyRoots(ld, ctx, rs, pld.pkgs)1501		if err != nil {1502			return false, err1503		}1504		addRoots = tidy.rootModules1505	}15061507	rs, err = updateRoots(ld, ctx, direct, rs, pld.pkgs, addRoots, pld.AssumeRootsImported)1508	if err != nil {1509		// We don't actually know what even the root requirements are supposed to be,1510		// so we can't proceed with loading. Return the error to the caller1511		return false, err1512	}15131514	if rs.GoVersion(ld) != pld.requirements.GoVersion(ld) {1515		// A change in the selected Go version may or may not affect the set of1516		// loaded packages, but in some cases it can change the meaning of the "all"1517		// pattern, the level of pruning in the module graph, and even the set of1518		// packages present in the standard library. If it has changed, it's best to1519		// reload packages once more to be sure everything is stable.1520		changed = true1521	} else if rs != pld.requirements && !slices.Equal(rs.rootModules, pld.requirements.rootModules) {1522		// The roots of the module graph have changed in some way (not just the1523		// "direct" markings). Check whether the changes affected any of the loaded1524		// packages.1525		mg, err := rs.Graph(ld, ctx)1526		if err != nil {1527			return false, err1528		}1529		for _, pkg := range pld.pkgs {1530			if pkg.fromExternalModule(ld) && mg.Selected(pkg.mod.Path) != pkg.mod.Version {1531				changed = true1532				break1533			}1534			if pkg.err != nil {1535				// Promoting a module to a root may resolve an import that was1536				// previously missing (by pulling in a previously-prune dependency that1537				// provides it) or ambiguous (by promoting exactly one of the1538				// alternatives to a root and ignoring the second-level alternatives) or1539				// otherwise errored out (by upgrading from a version that cannot be1540				// fetched to one that can be).1541				//1542				// Instead of enumerating all of the possible errors, we'll just check1543				// whether importFromModules returns nil for the package.1544				// False-positives are ok: if we have a false-positive here, we'll do an1545				// extra iteration of package loading this time, but we'll still1546				// converge when the root set stops changing.1547				//1548				// In some sense, we can think of this as ‘upgraded the module providing1549				// pkg.path from "none" to a version higher than "none"’.1550				if _, _, _, _, err = importFromModules(ld, ctx, pkg.path, rs, nil, pld.skipImportModFiles); err == nil {1551					changed = true1552					break1553				}1554			}1555		}1556	}15571558	pld.requirements = rs1559	return changed, nil1560}15611562// resolveMissingImports returns a set of modules that could be added as1563// dependencies in order to resolve missing packages from pkgs.1564//1565// The newly-resolved packages are added to the addedModuleFor map, and1566// resolveMissingImports returns a map from each new module version to1567// the first missing package that module would resolve.1568func (pld *packageLoader) resolveMissingImports(ld *Loader, ctx context.Context) (modAddedBy map[module.Version]*loadPkg, err error) {1569	type pkgMod struct {1570		pkg *loadPkg1571		mod *module.Version1572	}1573	var pkgMods []pkgMod1574	for _, pkg := range pld.pkgs {1575		if pkg.err == nil {1576			continue1577		}1578		if pkg.isTest() {1579			// If we are missing a test, we are also missing its non-test version, and1580			// we should only add the missing import once.1581			continue1582		}1583		if _, ok := errors.AsType[*ImportMissingError](pkg.err); !ok {1584			// Leave other errors for Import or load.Packages to report.1585			continue1586		}15871588		pkg := pkg1589		var mod module.Version1590		pld.work.Add(func() {1591			var err error1592			mod, err = queryImport(ld, ctx, pkg.path, pld.requirements)1593			if err != nil {1594				if ime, ok := errors.AsType[*ImportMissingError](err); ok {1595					for curstack := pkg.stack; curstack != nil; curstack = curstack.stack {1596						if ld.MainModules.Contains(curstack.mod.Path) {1597							ime.ImportingMainModule = curstack.mod1598							ime.modRoot = ld.MainModules.ModRoot(ime.ImportingMainModule)1599							break1600						}1601					}1602				}1603				// pkg.err was already non-nil, so we can reasonably attribute the error1604				// for pkg to either the original error or the one returned by1605				// queryImport. The existing error indicates only that we couldn't find1606				// the package, whereas the query error also explains why we didn't fix1607				// the problem — so we prefer the latter.1608				pkg.err = err1609			}16101611			// err is nil, but we intentionally leave pkg.err non-nil and pkg.mod1612			// unset: we still haven't satisfied other invariants of a1613			// successfully-loaded package, such as scanning and loading the imports1614			// of that package. If we succeed in resolving the new dependency graph,1615			// the caller can reload pkg and update the error at that point.1616			//1617			// Even then, the package might not be loaded from the version we've1618			// identified here. The module may be upgraded by some other dependency,1619			// or by a transitive dependency of mod itself, or — less likely — the1620			// package may be rejected by an AllowPackage hook or rendered ambiguous1621			// by some other newly-added or newly-upgraded dependency.1622		})16231624		pkgMods = append(pkgMods, pkgMod{pkg: pkg, mod: &mod})1625	}1626	<-pld.work.Idle()16271628	modAddedBy = map[module.Version]*loadPkg{}16291630	var (1631		maxTooNew    *gover.TooNewError1632		maxTooNewPkg *loadPkg1633	)1634	for _, pm := range pkgMods {1635		if tooNew, ok := errors.AsType[*gover.TooNewError](pm.pkg.err); ok {1636			if maxTooNew == nil || gover.Compare(tooNew.GoVersion, maxTooNew.GoVersion) > 0 {1637				maxTooNew = tooNew1638				maxTooNewPkg = pm.pkg1639			}1640		}1641	}1642	if maxTooNew != nil {1643		fmt.Fprintf(os.Stderr, "go: toolchain upgrade needed to resolve %s\n", maxTooNewPkg.path)1644		return nil, maxTooNew1645	}16461647	for _, pm := range pkgMods {1648		pkg, mod := pm.pkg, *pm.mod1649		if mod.Path == "" {1650			continue1651		}16521653		fmt.Fprintf(os.Stderr, "go: found %s in %s %s\n", pkg.path, mod.Path, mod.Version)1654		if modAddedBy[mod] == nil {1655			modAddedBy[mod] = pkg1656		}1657	}16581659	return modAddedBy, nil1660}16611662// pkg locates the *loadPkg for path, creating and queuing it for loading if1663// needed, and updates its state to reflect the given flags.1664//1665// The imports of the returned *loadPkg will be loaded asynchronously in the1666// ld.work queue, and its test (if requested) will also be populated once1667// imports have been resolved. When ld.work goes idle, all transitive imports of1668// the requested package (and its test, if requested) will have been loaded.1669func (pld *packageLoader) pkg(ld *Loader, ctx context.Context, path string, flags loadPkgFlags) *loadPkg {1670	if flags.has(pkgImportsLoaded) {1671		panic("internal error: (*packageLoader).pkg called with pkgImportsLoaded flag set")1672	}16731674	pkg := pld.pkgCache.Do(path, func() *loadPkg {1675		pkg := &loadPkg{1676			path: path,1677		}1678		pld.applyPkgFlags(ld, ctx, pkg, flags)16791680		pld.work.Add(func() { pld.load(ld, ctx, pkg) })1681		return pkg1682	})16831684	pld.applyPkgFlags(ld, ctx, pkg, flags)1685	return pkg1686}16871688// applyPkgFlags updates pkg.flags to set the given flags and propagate the1689// (transitive) effects of those flags, possibly loading or enqueueing further1690// packages as a result.1691func (pld *packageLoader) applyPkgFlags(ld *Loader, ctx context.Context, pkg *loadPkg, flags loadPkgFlags) {1692	if flags == 0 {1693		return1694	}16951696	if flags.has(pkgInAll) && pld.allPatternIsRoot && !pkg.isTest() {1697		// This package matches a root pattern by virtue of being in "all".1698		flags |= pkgIsRoot1699	}1700	if flags.has(pkgIsRoot) {1701		flags |= pkgFromRoot1702	}17031704	old := pkg.flags.update(flags)1705	new := old | flags1706	if new == old || !new.has(pkgImportsLoaded) {1707		// We either didn't change the state of pkg, or we don't know anything about1708		// its dependencies yet. Either way, we can't usefully load its test or1709		// update its dependencies.1710		return1711	}17121713	if !pkg.isTest() {1714		// Check whether we should add (or update the flags for) a test for pkg.1715		// ld.pkgTest is idempotent and extra invocations are inexpensive,1716		// so it's ok if we call it more than is strictly necessary.1717		wantTest := false1718		switch {1719		case pld.allPatternIsRoot && ld.MainModules.Contains(pkg.mod.Path):1720			// We are loading the "all" pattern, which includes packages imported by1721			// tests in the main module. This package is in the main module, so we1722			// need to identify the imports of its test even if LoadTests is not set.1723			//1724			// (We will filter out the extra tests explicitly in computePatternAll.)1725			wantTest = true17261727		case pld.allPatternIsRoot && pld.allClosesOverTests && new.has(pkgInAll):1728			// This variant of the "all" pattern includes imports of tests of every1729			// package that is itself in "all", and pkg is in "all", so its test is1730			// also in "all" (as above).1731			wantTest = true17321733		case pld.LoadTests && new.has(pkgIsRoot):1734			// LoadTest explicitly requests tests of “the root packages”.1735			wantTest = true1736		}17371738		if wantTest {1739			var testFlags loadPkgFlags1740			if ld.MainModules.Contains(pkg.mod.Path) || (pld.allClosesOverTests && new.has(pkgInAll)) {1741				// Tests of packages in the main module are in "all", in the sense that1742				// they cause the packages they import to also be in "all". So are tests1743				// of packages in "all" if "all" closes over test dependencies.1744				testFlags |= pkgInAll1745			}1746			pld.pkgTest(ld, ctx, pkg, testFlags)1747		}1748	}17491750	if new.has(pkgInAll) && !old.has(pkgInAll|pkgImportsLoaded) {1751		// We have just marked pkg with pkgInAll, or we have just loaded its1752		// imports, or both. Now is the time to propagate pkgInAll to the imports.1753		for _, dep := range pkg.imports {1754			pld.applyPkgFlags(ld, ctx, dep, pkgInAll)1755		}1756	}17571758	if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) {1759		for _, dep := range pkg.imports {1760			pld.applyPkgFlags(ld, ctx, dep, pkgFromRoot)1761		}1762	}1763}17641765// preloadRootModules loads the module requirements needed to identify the1766// selected version of each module providing a package in rootPkgs,1767// adding new root modules to the module graph if needed.1768func (pld *packageLoader) preloadRootModules(ld *Loader, ctx context.Context, rootPkgs []string) (changedBuildList bool) {1769	needc := make(chan map[module.Version]bool, 1)1770	needc <- map[module.Version]bool{}1771	for _, path := range rootPkgs {1772		path := path1773		pld.work.Add(func() {1774			// First, try to identify the module containing the package using only roots.1775			//1776			// If the main module is tidy and the package is in "all" — or if we're1777			// lucky — we can identify all of its imports without actually loading the1778			// full module graph.1779			m, _, _, _, err := importFromModules(ld, ctx, path, pld.requirements, nil, pld.skipImportModFiles)1780			if err != nil {1781				if _, ok := errors.AsType[*ImportMissingError](err); ok && pld.ResolveMissingImports {1782					// This package isn't provided by any selected module.1783					// If we can find it, it will be a new root dependency.1784					m, err = queryImport(ld, ctx, path, pld.requirements)1785				}1786				if err != nil {1787					// We couldn't identify the root module containing this package.1788					// Leave it unresolved; we will report it during loading.1789					return1790				}1791			}1792			if m.Path == "" {1793				// The package is in std or cmd. We don't need to change the root set.1794				return1795			}17961797			v, ok := pld.requirements.rootSelected(ld, m.Path)1798			if !ok || v != m.Version {1799				// We found the requested package in m, but m is not a root, so1800				// loadModGraph will not load its requirements. We need to promote the1801				// module to a root to ensure that any other packages this package1802				// imports are resolved from correct dependency versions.1803				//1804				// (This is the “argument invariant” from1805				// https://golang.org/design/36460-lazy-module-loading.)1806				need := <-needc1807				need[m] = true1808				needc <- need1809			}1810		})1811	}1812	<-pld.work.Idle()18131814	need := <-needc1815	if len(need) == 0 {1816		return false // No roots to add.1817	}18181819	toAdd := make([]module.Version, 0, len(need))1820	for m := range need {1821		toAdd = append(toAdd, m)1822	}1823	gover.ModSort(toAdd)18241825	rs, err := updateRoots(ld, ctx, pld.requirements.direct, pld.requirements, nil, toAdd, pld.AssumeRootsImported)1826	if err != nil {1827		// We are missing some root dependency, and for some reason we can't load1828		// enough of the module dependency graph to add the missing root. Package1829		// loading is doomed to fail, so fail quickly.1830		pld.error(err)1831		pld.exitIfErrors(ctx)1832		return false1833	}1834	if slices.Equal(rs.rootModules, pld.requirements.rootModules) {1835		// Something is deeply wrong. resolveMissingImports gave us a non-empty1836		// set of modules to add to the graph, but adding those modules had no1837		// effect — either they were already in the graph, or updateRoots did not1838		// add them as requested.1839		panic(fmt.Sprintf("internal error: adding %v to module graph had no effect on root requirements (%v)", toAdd, rs.rootModules))1840	}18411842	pld.requirements = rs1843	return true1844}18451846// load loads an individual package.1847func (pld *packageLoader) load(ld *Loader, ctx context.Context, pkg *loadPkg) {1848	var mg *ModuleGraph1849	if pld.requirements.pruning == unpruned {1850		var err error1851		mg, err = pld.requirements.Graph(ld, ctx)1852		if err != nil {1853			// We already checked the error from Graph in loadFromRoots and/or1854			// updateRequirements, so we ignored the error on purpose and we should1855			// keep trying to push past it.1856			//1857			// However, because mg may be incomplete (and thus may select inaccurate1858			// versions), we shouldn't use it to load packages. Instead, we pass a nil1859			// *ModuleGraph, which will cause mg to first try loading from only the1860			// main module and root dependencies.1861			mg = nil1862		}1863	}18641865	var modroot string1866	pkg.mod, modroot, pkg.dir, pkg.altMods, pkg.err = importFromModules(ld, ctx, pkg.path, pld.requirements, mg, pld.skipImportModFiles)1867	if ld.MainModules.Tools()[pkg.path] {1868		// Tools declared by main modules are always in "all".1869		// We apply the package flags before returning so that missing1870		// tool dependencies report an error https://go.dev/issue/705821871		pld.applyPkgFlags(ld, ctx, pkg, pkgInAll)1872	}1873	if pkg.dir == "" {1874		return1875	}1876	if ld.MainModules.Contains(pkg.mod.Path) {1877		// Go ahead and mark pkg as in "all". This provides the invariant that a1878		// package that is *only* imported by other packages in "all" is always1879		// marked as such before loading its imports.1880		//1881		// We don't actually rely on that invariant at the moment, but it may1882		// improve efficiency somewhat and makes the behavior a bit easier to reason1883		// about (by reducing churn on the flag bits of dependencies), and costs1884		// essentially nothing (these atomic flag ops are essentially free compared1885		// to scanning source code for imports).1886		pld.applyPkgFlags(ld, ctx, pkg, pkgInAll)1887	}1888	if pld.AllowPackage != nil {1889		if err := pld.AllowPackage(ctx, pkg.path, pkg.mod); err != nil {1890			pkg.err = err1891		}1892	}18931894	pkg.inStd = (search.IsStandardImportPath(pkg.path) && search.InDir(pkg.dir, cfg.GOROOTsrc) != "")18951896	var imports, testImports []string18971898	if cfg.BuildContext.Compiler == "gccgo" && pkg.inStd {1899		// We can't scan standard packages for gccgo.1900	} else {1901		var err error1902		imports, testImports, err = scanDir(modroot, pkg.dir, pld.Tags)1903		if err != nil {1904			pkg.err = err1905			return1906		}1907	}19081909	pkg.imports = make([]*loadPkg, 0, len(imports))1910	var importFlags loadPkgFlags1911	if pkg.flags.has(pkgInAll) {1912		importFlags = pkgInAll1913	}1914	for _, path := range imports {1915		if pkg.inStd {1916			// Imports from packages in "std" and "cmd" should resolve using1917			// GOROOT/src/vendor even when "std" is not the main module.1918			path = pld.stdVendor(ld, pkg.path, path)1919		}1920		pkg.imports = append(pkg.imports, pld.pkg(ld, ctx, path, importFlags))1921	}1922	pkg.testImports = testImports19231924	pld.applyPkgFlags(ld, ctx, pkg, pkgImportsLoaded)1925}19261927// pkgTest locates the test of pkg, creating it if needed, and updates its state1928// to reflect the given flags.1929//1930// pkgTest requires that the imports of pkg have already been loaded (flagged1931// with pkgImportsLoaded).1932func (pld *packageLoader) pkgTest(ld *Loader, ctx context.Context, pkg *loadPkg, testFlags loadPkgFlags) *loadPkg {1933	if pkg.isTest() {1934		panic("pkgTest called on a test package")1935	}19361937	createdTest := false1938	pkg.testOnce.Do(func() {1939		pkg.test = &loadPkg{1940			path:   pkg.path,1941			testOf: pkg,1942			mod:    pkg.mod,1943			dir:    pkg.dir,1944			err:    pkg.err,1945			inStd:  pkg.inStd,1946		}1947		pld.applyPkgFlags(ld, ctx, pkg.test, testFlags)1948		createdTest = true1949	})19501951	test := pkg.test1952	if createdTest {1953		test.imports = make([]*loadPkg, 0, len(pkg.testImports))1954		var importFlags loadPkgFlags1955		if test.flags.has(pkgInAll) {1956			importFlags = pkgInAll1957		}1958		for _, path := range pkg.testImports {1959			if pkg.inStd {1960				path = pld.stdVendor(ld, test.path, path)1961			}1962			test.imports = append(test.imports, pld.pkg(ld, ctx, path, importFlags))1963		}1964		pkg.testImports = nil1965		pld.applyPkgFlags(ld, ctx, test, pkgImportsLoaded)1966	} else {1967		pld.applyPkgFlags(ld, ctx, test, testFlags)1968	}19691970	return test1971}19721973// stdVendor returns the canonical import path for the package with the given1974// path when imported from the standard-library package at parentPath.1975func (pld *packageLoader) stdVendor(ld *Loader, parentPath, path string) string {1976	if p, _, ok := fips140.ResolveImport(path); ok {1977		return p1978	}1979	if search.IsStandardImportPath(path) {1980		return path1981	}19821983	if str.HasPathPrefix(parentPath, "cmd") {1984		if !pld.VendorModulesInGOROOTSrc || !ld.MainModules.Contains("cmd") {1985			vendorPath := pathpkg.Join("cmd", "vendor", path)19861987			if _, err := os.Stat(filepath.Join(cfg.GOROOTsrc, filepath.FromSlash(vendorPath))); err == nil {1988				return vendorPath1989			}1990		}1991	} else if !pld.VendorModulesInGOROOTSrc || !ld.MainModules.Contains("std") || str.HasPathPrefix(parentPath, "vendor") {1992		// If we are outside of the 'std' module, resolve imports from within 'std'1993		// to the vendor directory.1994		//1995		// Do the same for importers beginning with the prefix 'vendor/' even if we1996		// are *inside* of the 'std' module: the 'vendor/' packages that resolve1997		// globally from GOROOT/src/vendor (and are listed as part of 'go list std')1998		// are distinct from the real module dependencies, and cannot import1999		// internal packages from the real module.2000		//

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.