go/loader: fix race

Fixes golang/go#36415.

Change-Id: I1bdec3da8e2a4f185e039a0046731a3300ee1153
Reviewed-on: https://go-review.googlesource.com/c/tools/+/293836
gopls-CI: kokoro <noreply+kokoro@google.com>
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
diff --git a/go/loader/loader.go b/go/loader/loader.go
index bc12ca3..508a1fd 100644
--- a/go/loader/loader.go
+++ b/go/loader/loader.go
@@ -869,21 +869,6 @@
 // caused these imports.
 //
 func (imp *importer) importAll(fromPath, fromDir string, imports map[string]bool, mode build.ImportMode) (infos []*PackageInfo, errors []importError) {
-	// TODO(adonovan): opt: do the loop in parallel once
-	// findPackage is non-blocking.
-	var pending []*importInfo
-	for importPath := range imports {
-		bp, err := imp.findPackage(importPath, fromDir, mode)
-		if err != nil {
-			errors = append(errors, importError{
-				path: importPath,
-				err:  err,
-			})
-			continue
-		}
-		pending = append(pending, imp.startLoad(bp))
-	}
-
 	if fromPath != "" {
 		// We're loading a set of imports.
 		//
@@ -895,29 +880,36 @@
 			deps = make(map[string]bool)
 			imp.graph[fromPath] = deps
 		}
-		for _, ii := range pending {
-			deps[ii.path] = true
+		for importPath := range imports {
+			deps[importPath] = true
 		}
 		imp.graphMu.Unlock()
 	}
 
-	for _, ii := range pending {
+	var pending []*importInfo
+	for importPath := range imports {
 		if fromPath != "" {
-			if cycle := imp.findPath(ii.path, fromPath); cycle != nil {
-				// Cycle-forming import: we must not await its
-				// completion since it would deadlock.
-				//
-				// We don't record the error in ii since
-				// the error is really associated with the
-				// cycle-forming edge, not the package itself.
-				// (Also it would complicate the
-				// invariants of importPath completion.)
+			if cycle := imp.findPath(importPath, fromPath); cycle != nil {
+				// Cycle-forming import: we must not check it
+				// since it would deadlock.
 				if trace {
 					fmt.Fprintf(os.Stderr, "import cycle: %q\n", cycle)
 				}
 				continue
 			}
 		}
+		bp, err := imp.findPackage(importPath, fromDir, mode)
+		if err != nil {
+			errors = append(errors, importError{
+				path: importPath,
+				err:  err,
+			})
+			continue
+		}
+		pending = append(pending, imp.startLoad(bp))
+	}
+
+	for _, ii := range pending {
 		ii.awaitCompletion()
 		infos = append(infos, ii.info)
 	}