Skip to content

Commit c35c44f

Browse files
adonovangopherbot
authored andcommitted
gopls/internal/lsp/cache: add assertions
This change documents and asserts a few invariants that should be maintained by the code. The crash in golang/go#60551 shows that they are not, but I still can't see the mistake in my proof. Updates golang/go#60551 Change-Id: I833f7575f1d7372837ab5d7ba5988c94650ce07f Reviewed-on: https://go-review.googlesource.com/c/tools/+/500055 Auto-Submit: Alan Donovan <[email protected]> Run-TryBot: Alan Donovan <[email protected]> gopls-CI: kokoro <[email protected]> Reviewed-by: Robert Findley <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 0b4461b commit c35c44f

File tree

1 file changed

+24
-18
lines changed

1 file changed

+24
-18
lines changed

gopls/internal/lsp/cache/analysis.go

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"sort"
2424
"strings"
2525
"sync"
26-
"time"
2726

2827
"golang.org/x/sync/errgroup"
2928
"golang.org/x/tools/go/analysis"
@@ -32,6 +31,7 @@ import (
3231
"golang.org/x/tools/gopls/internal/lsp/protocol"
3332
"golang.org/x/tools/gopls/internal/lsp/source"
3433
"golang.org/x/tools/internal/event"
34+
"golang.org/x/tools/internal/event/tag"
3535
"golang.org/x/tools/internal/facts"
3636
"golang.org/x/tools/internal/gcimporter"
3737
"golang.org/x/tools/internal/memoize"
@@ -164,8 +164,6 @@ import (
164164
// Destroy()
165165
// - share cache.{goVersionRx,parseGoImpl}
166166

167-
var born = time.Now()
168-
169167
// Analyze applies a set of analyzers to the package denoted by id,
170168
// and returns their diagnostics for that package.
171169
//
@@ -174,9 +172,8 @@ var born = time.Now()
174172
// Precondition: all analyzers within the process have distinct names.
175173
// (The names are relied on by the serialization logic.)
176174
func (s *snapshot) Analyze(ctx context.Context, id PackageID, analyzers []*source.Analyzer) ([]*source.Diagnostic, error) {
177-
if false { // debugging
178-
log.Println("Analyze@", time.Since(born)) // called after the 7s IWL in k8s
179-
}
175+
ctx, done := event.Start(ctx, "snapshot.Analyze", tag.Package.Of(string(id)))
176+
defer done()
180177

181178
// Filter and sort enabled root analyzers.
182179
// A disabled analyzer may still be run if required by another.
@@ -199,19 +196,13 @@ func (s *snapshot) Analyze(ctx context.Context, id PackageID, analyzers []*sourc
199196
}
200197
}
201198

202-
if false { // debugging
203-
// TODO(adonovan): use proper tracing.
204-
t0 := time.Now()
205-
defer func() {
206-
log.Printf("%v for analyze(%s, %s)", time.Since(t0), id, enabled)
207-
}()
208-
}
209-
210199
// Run the analysis.
211200
res, err := s.analyze(ctx, id, enabled)
212201
if err != nil {
213202
return nil, err
214203
}
204+
// Inv: res is the successful result of analyzeImpl(analyzers, id),
205+
// which augments the successful result of actuallyAnalyze.
215206

216207
// Report diagnostics only from enabled actions that succeeded.
217208
// Errors from creating or analyzing packages are ignored.
@@ -225,7 +216,11 @@ func (s *snapshot) Analyze(ctx context.Context, id PackageID, analyzers []*sourc
225216
// results, we should propagate the per-action errors.
226217
var results []*source.Diagnostic
227218
for _, a := range enabled {
228-
summary := res.Actions[a.Name]
219+
summary, ok := res.Actions[a.Name]
220+
if summary == nil {
221+
panic(fmt.Sprintf("analyzeSummary.Actions[%q] = (nil, %t); got %v (#60551)",
222+
a.Name, ok, res.Actions))
223+
}
229224
if summary.Err != "" {
230225
continue // action failed
231226
}
@@ -309,7 +304,7 @@ type actionSummary struct {
309304

310305
// analyze is a memoization of analyzeImpl.
311306
func (s *snapshot) analyze(ctx context.Context, id PackageID, analyzers []*analysis.Analyzer) (*analyzeSummary, error) {
312-
// Use the sorted list of names of analyzers in the key.
307+
// Use the caller-sorted list of names of analyzers in the key.
313308
//
314309
// TODO(adonovan): opt: account for analysis results at a
315310
// finer grain to avoid duplicate work when a
@@ -568,6 +563,9 @@ func analysisCacheKey(analyzers []*analysis.Analyzer, m *source.Metadata, compil
568563

569564
// actuallyAnalyze implements the cache-miss case.
570565
// This function does not access the snapshot.
566+
//
567+
// Postcondition: on success, the analyzeSummary.Actions
568+
// key set is {a.Name for a in analyzers}.
571569
func actuallyAnalyze(ctx context.Context, analyzers []*analysis.Analyzer, m *source.Metadata, vdeps map[PackageID]*analyzeSummary, compiledGoFiles []source.FileHandle) (*analyzeSummary, error) {
572570
// Create a local FileSet for processing this package only.
573571
fset := token.NewFileSet()
@@ -637,6 +635,7 @@ func actuallyAnalyze(ctx context.Context, analyzers []*analysis.Analyzer, m *sou
637635

638636
// Execute the graph in parallel.
639637
execActions(roots)
638+
// Inv: each root's summary is set (whether success or error).
640639

641640
// Don't return (or cache) the result in case of cancellation.
642641
if err := ctx.Err(); err != nil {
@@ -645,8 +644,11 @@ func actuallyAnalyze(ctx context.Context, analyzers []*analysis.Analyzer, m *sou
645644

646645
// Return summaries only for the requested actions.
647646
summaries := make(map[string]*actionSummary)
648-
for _, act := range roots {
649-
summaries[act.a.Name] = act.summary
647+
for _, root := range roots {
648+
if root.summary == nil {
649+
panic("root has nil action.summary (#60551)")
650+
}
651+
summaries[root.a.Name] = root.summary
650652
}
651653

652654
return &analyzeSummary{
@@ -897,6 +899,7 @@ func (act *action) String() string {
897899
}
898900

899901
// execActions executes a set of action graph nodes in parallel.
902+
// Postcondition: each action.summary is set, even in case of error.
900903
func execActions(actions []*action) {
901904
var wg sync.WaitGroup
902905
for _, act := range actions {
@@ -917,6 +920,9 @@ func execActions(actions []*action) {
917920
}
918921
}
919922
})
923+
if act.summary == nil {
924+
panic("nil action.summary (#60551)")
925+
}
920926
}()
921927
}
922928
wg.Wait()

0 commit comments

Comments
 (0)