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.