gopls/internal/lsp/cache: remove baseCtx from the View

Views don't do work, so should have no need of a context. Instead, chain
the contexts inside of clone.

Also, fix a latent bug where the context used in the view importsState
is the snapshot backgroundCtx rather than view baseCtx: the importsState
outlives the snapshot, so should not reference the snapshot context.
Fortunately, the context was thus far only used for logging.

For golang/go#57979

Change-Id: Icf55d69e82f19b3fd52ca7d9266df2b5589bb36e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/539676
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/gopls/internal/lsp/cache/session.go b/gopls/internal/lsp/cache/session.go
index 47b69af..e565f19 100644
--- a/gopls/internal/lsp/cache/session.go
+++ b/gopls/internal/lsp/cache/session.go
@@ -118,7 +118,6 @@
 		folder:               folder,
 		initialWorkspaceLoad: make(chan struct{}),
 		initializationSema:   make(chan struct{}, 1),
-		baseCtx:              baseCtx,
 		moduleUpgrades:       map[span.URI]map[string]string{},
 		vulns:                map[span.URI]*vulncheck.Result{},
 		parseCache:           s.parseCache,
@@ -126,7 +125,7 @@
 		workspaceInformation: info,
 	}
 	v.importsState = &importsState{
-		ctx: backgroundCtx,
+		ctx: baseCtx,
 		processEnv: &imports.ProcessEnv{
 			GocmdRunner: s.gocmdRunner,
 			SkipPathInScan: func(dir string) bool {
diff --git a/gopls/internal/lsp/cache/snapshot.go b/gopls/internal/lsp/cache/snapshot.go
index ba1322d..47dd1ab 100644
--- a/gopls/internal/lsp/cache/snapshot.go
+++ b/gopls/internal/lsp/cache/snapshot.go
@@ -45,6 +45,7 @@
 	"golang.org/x/tools/internal/packagesinternal"
 	"golang.org/x/tools/internal/persistent"
 	"golang.org/x/tools/internal/typesinternal"
+	"golang.org/x/tools/internal/xcontext"
 )
 
 type snapshot struct {
@@ -1813,20 +1814,20 @@
 	return found && strings.Contains(after, "/")
 }
 
-func (s *snapshot) clone(ctx, bgCtx context.Context, changes map[span.URI]source.FileHandle) (*snapshot, func()) {
+func (s *snapshot) clone(ctx context.Context, changes map[span.URI]source.FileHandle) (*snapshot, func()) {
 	ctx, done := event.Start(ctx, "cache.snapshot.clone")
 	defer done()
 
 	s.mu.Lock()
 	defer s.mu.Unlock()
 
-	bgCtx, cancel := context.WithCancel(bgCtx)
+	backgroundCtx, cancel := context.WithCancel(event.Detach(xcontext.Detach(s.backgroundCtx)))
 	result := &snapshot{
 		sequenceID:           s.sequenceID + 1,
 		globalID:             nextSnapshotID(),
 		store:                s.store,
 		view:                 s.view,
-		backgroundCtx:        bgCtx,
+		backgroundCtx:        backgroundCtx,
 		cancel:               cancel,
 		builtin:              s.builtin,
 		initialized:          s.initialized,
diff --git a/gopls/internal/lsp/cache/view.go b/gopls/internal/lsp/cache/view.go
index 2565151..246669c 100644
--- a/gopls/internal/lsp/cache/view.go
+++ b/gopls/internal/lsp/cache/view.go
@@ -52,10 +52,6 @@
 
 	gocmdRunner *gocommand.Runner // limits go command concurrency
 
-	// baseCtx is the context handed to NewView. This is the parent of all
-	// background contexts created for this view.
-	baseCtx context.Context
-
 	folder *Folder
 
 	// Workspace information. The fields below are immutable, and together with
@@ -893,7 +889,7 @@
 	prevSnapshot.AwaitInitialized(ctx)
 
 	// Save one lease of the cloned snapshot in the view.
-	v.snapshot, v.releaseSnapshot = prevSnapshot.clone(ctx, v.baseCtx, changes)
+	v.snapshot, v.releaseSnapshot = prevSnapshot.clone(ctx, changes)
 
 	prevReleaseSnapshot()
 	v.destroy(prevSnapshot, "View.invalidateContent")