Skip to content

Commit f6298eb

Browse files
committed
gopls/internal/cache: add debug assertions to refine golang/go#66732
Also, use go1.19 generic helpers for atomics. Updates golang/go#66732 Change-Id: I7aa447144353ff2ac5906ca746e2f98b115aa732 Reviewed-on: https://go-review.googlesource.com/c/tools/+/577435 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Alan Donovan <[email protected]>
1 parent f41d27e commit f6298eb

File tree

1 file changed

+33
-17
lines changed

1 file changed

+33
-17
lines changed

gopls/internal/cache/analysis.go

+33-17
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import (
4242
"golang.org/x/tools/gopls/internal/util/astutil"
4343
"golang.org/x/tools/gopls/internal/util/bug"
4444
"golang.org/x/tools/gopls/internal/util/frob"
45+
"golang.org/x/tools/gopls/internal/util/maps"
4546
"golang.org/x/tools/internal/event"
4647
"golang.org/x/tools/internal/event/tag"
4748
"golang.org/x/tools/internal/facts"
@@ -178,8 +179,6 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
178179

179180
var tagStr string // sorted comma-separated list of PackageIDs
180181
{
181-
// TODO(adonovan): replace with a generic map[S]any -> string
182-
// function in the tag package, and use maps.Keys + slices.Sort.
183182
keys := make([]string, 0, len(pkgs))
184183
for id := range pkgs {
185184
keys = append(keys, string(id))
@@ -304,10 +303,10 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
304303
}
305304
// Add edge from predecessor.
306305
if from != nil {
307-
atomic.AddInt32(&from.unfinishedSuccs, 1) // TODO(adonovan): use generics
306+
from.unfinishedSuccs.Add(+1) // incref
308307
an.preds = append(an.preds, from)
309308
}
310-
atomic.AddInt32(&an.unfinishedPreds, 1)
309+
an.unfinishedPreds.Add(+1)
311310
return an, nil
312311
}
313312

@@ -388,7 +387,7 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
388387
// prevents workers from enqeuing, and thus finishing, and thus allowing the
389388
// group to make progress: deadlock.
390389
limiter := make(chan unit, runtime.GOMAXPROCS(0))
391-
var completed int64
390+
var completed atomic.Int64
392391

393392
var enqueue func(*analysisNode)
394393
enqueue = func(an *analysisNode) {
@@ -400,13 +399,13 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
400399
if err != nil {
401400
return err // cancelled, or failed to produce a package
402401
}
403-
maybeReport(atomic.AddInt64(&completed, 1))
402+
maybeReport(completed.Add(1))
404403
an.summary = summary
405404

406405
// Notify each waiting predecessor,
407406
// and enqueue it when it becomes a leaf.
408407
for _, pred := range an.preds {
409-
if atomic.AddInt32(&pred.unfinishedSuccs, -1) == 0 {
408+
if pred.unfinishedSuccs.Add(-1) == 0 { // decref
410409
enqueue(pred)
411410
}
412411
}
@@ -428,6 +427,18 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
428427
return nil, err // cancelled, or failed to produce a package
429428
}
430429

430+
// Inv: all root nodes now have a summary (#66732).
431+
//
432+
// We know this is falsified empirically. This means either
433+
// the summary was "successfully" set to nil (above), or there
434+
// is a problem with the graph such the enqueuing leaves does
435+
// not lead to completion of roots (or an error).
436+
for _, root := range roots {
437+
if root.summary == nil {
438+
bug.Report("root analysisNode has nil summary")
439+
}
440+
}
441+
431442
// Report diagnostics only from enabled actions that succeeded.
432443
// Errors from creating or analyzing packages are ignored.
433444
// Diagnostics are reported in the order of the analyzers argument.
@@ -459,6 +470,7 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
459470
}
460471

461472
// Inv: root.summary is the successful result of run (via runCached).
473+
// TODO(adonovan): fix: root.summary is sometimes nil! (#66732).
462474
summary, ok := root.summary.Actions[stableNames[a]]
463475
if summary == nil {
464476
panic(fmt.Sprintf("analyzeSummary.Actions[%q] = (nil, %t); got %v (#60551)",
@@ -476,7 +488,7 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
476488
}
477489

478490
func (an *analysisNode) decrefPreds() {
479-
if atomic.AddInt32(&an.unfinishedPreds, -1) == 0 {
491+
if an.unfinishedPreds.Add(-1) == 0 {
480492
an.summary.Actions = nil
481493
}
482494
}
@@ -511,8 +523,8 @@ type analysisNode struct {
511523
analyzers []*analysis.Analyzer // set of analyzers to run
512524
preds []*analysisNode // graph edges:
513525
succs map[PackageID]*analysisNode // (preds -> self -> succs)
514-
unfinishedSuccs int32
515-
unfinishedPreds int32 // effectively a summary.Actions refcount
526+
unfinishedSuccs atomic.Int32
527+
unfinishedPreds atomic.Int32 // effectively a summary.Actions refcount
516528
allDeps map[PackagePath]*analysisNode // all dependencies including self
517529
exportDeps map[PackagePath]*analysisNode // subset of allDeps ref'd by export data (+self)
518530
summary *analyzeSummary // serializable result of analyzing this package
@@ -665,6 +677,9 @@ func (an *analysisNode) runCached(ctx context.Context) (*analyzeSummary, error)
665677
if data, err := filecache.Get(cacheKind, key); err == nil {
666678
// cache hit
667679
analyzeSummaryCodec.Decode(data, &summary)
680+
if summary == nil { // debugging #66732
681+
bug.Reportf("analyzeSummaryCodec.Decode yielded nil *analyzeSummary")
682+
}
668683
} else if err != filecache.ErrNotFound {
669684
return nil, bug.Errorf("internal error reading shared cache: %v", err)
670685
} else {
@@ -674,8 +689,11 @@ func (an *analysisNode) runCached(ctx context.Context) (*analyzeSummary, error)
674689
if err != nil {
675690
return nil, err
676691
}
692+
if summary == nil { // debugging #66732 (can't happen)
693+
bug.Reportf("analyzeNode.run returned nil *analyzeSummary")
694+
}
677695

678-
atomic.AddInt32(&an.unfinishedPreds, +1) // incref
696+
an.unfinishedPreds.Add(+1) // incref
679697
go func() {
680698
defer an.decrefPreds() //decref
681699

@@ -743,13 +761,11 @@ func (an *analysisNode) cacheKey() [sha256.Size]byte {
743761
}
744762

745763
// vdeps, in PackageID order
746-
depIDs := make([]string, 0, len(an.succs))
747-
for depID := range an.succs {
748-
depIDs = append(depIDs, string(depID))
749-
}
750-
sort.Strings(depIDs) // TODO(adonovan): avoid conversions by using slices.Sort[PackageID]
764+
depIDs := maps.Keys(an.succs)
765+
// TODO(adonovan): use go1.2x slices.Sort(depIDs).
766+
sort.Slice(depIDs, func(i, j int) bool { return depIDs[i] < depIDs[j] })
751767
for _, depID := range depIDs {
752-
vdep := an.succs[PackageID(depID)]
768+
vdep := an.succs[depID]
753769
fmt.Fprintf(hasher, "dep: %s\n", vdep.mp.PkgPath)
754770
fmt.Fprintf(hasher, "export: %s\n", vdep.summary.DeepExportHash)
755771

0 commit comments

Comments
 (0)