@@ -42,6 +42,7 @@ import (
42
42
"golang.org/x/tools/gopls/internal/util/astutil"
43
43
"golang.org/x/tools/gopls/internal/util/bug"
44
44
"golang.org/x/tools/gopls/internal/util/frob"
45
+ "golang.org/x/tools/gopls/internal/util/maps"
45
46
"golang.org/x/tools/internal/event"
46
47
"golang.org/x/tools/internal/event/tag"
47
48
"golang.org/x/tools/internal/facts"
@@ -178,8 +179,6 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
178
179
179
180
var tagStr string // sorted comma-separated list of PackageIDs
180
181
{
181
- // TODO(adonovan): replace with a generic map[S]any -> string
182
- // function in the tag package, and use maps.Keys + slices.Sort.
183
182
keys := make ([]string , 0 , len (pkgs ))
184
183
for id := range pkgs {
185
184
keys = append (keys , string (id ))
@@ -304,10 +303,10 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
304
303
}
305
304
// Add edge from predecessor.
306
305
if from != nil {
307
- atomic . AddInt32 ( & from .unfinishedSuccs , 1 ) // TODO(adonovan): use generics
306
+ from .unfinishedSuccs . Add ( + 1 ) // incref
308
307
an .preds = append (an .preds , from )
309
308
}
310
- atomic . AddInt32 ( & an .unfinishedPreds , 1 )
309
+ an .unfinishedPreds . Add ( + 1 )
311
310
return an , nil
312
311
}
313
312
@@ -388,7 +387,7 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
388
387
// prevents workers from enqeuing, and thus finishing, and thus allowing the
389
388
// group to make progress: deadlock.
390
389
limiter := make (chan unit , runtime .GOMAXPROCS (0 ))
391
- var completed int64
390
+ var completed atomic. Int64
392
391
393
392
var enqueue func (* analysisNode )
394
393
enqueue = func (an * analysisNode ) {
@@ -400,13 +399,13 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
400
399
if err != nil {
401
400
return err // cancelled, or failed to produce a package
402
401
}
403
- maybeReport (atomic . AddInt64 ( & completed , 1 ))
402
+ maybeReport (completed . Add ( 1 ))
404
403
an .summary = summary
405
404
406
405
// Notify each waiting predecessor,
407
406
// and enqueue it when it becomes a leaf.
408
407
for _ , pred := range an .preds {
409
- if atomic . AddInt32 ( & pred .unfinishedSuccs , - 1 ) == 0 {
408
+ if pred .unfinishedSuccs . Add ( - 1 ) == 0 { // decref
410
409
enqueue (pred )
411
410
}
412
411
}
@@ -428,6 +427,18 @@ func (s *Snapshot) Analyze(ctx context.Context, pkgs map[PackageID]*metadata.Pac
428
427
return nil , err // cancelled, or failed to produce a package
429
428
}
430
429
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
+
431
442
// Report diagnostics only from enabled actions that succeeded.
432
443
// Errors from creating or analyzing packages are ignored.
433
444
// 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
459
470
}
460
471
461
472
// Inv: root.summary is the successful result of run (via runCached).
473
+ // TODO(adonovan): fix: root.summary is sometimes nil! (#66732).
462
474
summary , ok := root .summary .Actions [stableNames [a ]]
463
475
if summary == nil {
464
476
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
476
488
}
477
489
478
490
func (an * analysisNode ) decrefPreds () {
479
- if atomic . AddInt32 ( & an .unfinishedPreds , - 1 ) == 0 {
491
+ if an .unfinishedPreds . Add ( - 1 ) == 0 {
480
492
an .summary .Actions = nil
481
493
}
482
494
}
@@ -511,8 +523,8 @@ type analysisNode struct {
511
523
analyzers []* analysis.Analyzer // set of analyzers to run
512
524
preds []* analysisNode // graph edges:
513
525
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
516
528
allDeps map [PackagePath ]* analysisNode // all dependencies including self
517
529
exportDeps map [PackagePath ]* analysisNode // subset of allDeps ref'd by export data (+self)
518
530
summary * analyzeSummary // serializable result of analyzing this package
@@ -665,6 +677,9 @@ func (an *analysisNode) runCached(ctx context.Context) (*analyzeSummary, error)
665
677
if data , err := filecache .Get (cacheKind , key ); err == nil {
666
678
// cache hit
667
679
analyzeSummaryCodec .Decode (data , & summary )
680
+ if summary == nil { // debugging #66732
681
+ bug .Reportf ("analyzeSummaryCodec.Decode yielded nil *analyzeSummary" )
682
+ }
668
683
} else if err != filecache .ErrNotFound {
669
684
return nil , bug .Errorf ("internal error reading shared cache: %v" , err )
670
685
} else {
@@ -674,8 +689,11 @@ func (an *analysisNode) runCached(ctx context.Context) (*analyzeSummary, error)
674
689
if err != nil {
675
690
return nil , err
676
691
}
692
+ if summary == nil { // debugging #66732 (can't happen)
693
+ bug .Reportf ("analyzeNode.run returned nil *analyzeSummary" )
694
+ }
677
695
678
- atomic . AddInt32 ( & an .unfinishedPreds , + 1 ) // incref
696
+ an .unfinishedPreds . Add ( + 1 ) // incref
679
697
go func () {
680
698
defer an .decrefPreds () //decref
681
699
@@ -743,13 +761,11 @@ func (an *analysisNode) cacheKey() [sha256.Size]byte {
743
761
}
744
762
745
763
// 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 ] })
751
767
for _ , depID := range depIDs {
752
- vdep := an .succs [PackageID ( depID ) ]
768
+ vdep := an .succs [depID ]
753
769
fmt .Fprintf (hasher , "dep: %s\n " , vdep .mp .PkgPath )
754
770
fmt .Fprintf (hasher , "export: %s\n " , vdep .summary .DeepExportHash )
755
771
0 commit comments