internal/lsp/cache: tolerate analysis panics better

Panics in type error analyzers shouldn't block diagnostics.

Fixes golang/go#45075.

Change-Id: I897f0949551ab65276371f7ec8140ccb689e5a7b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/302533
Trust: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
(cherry picked from commit 9b614f5d7b6512434a7f3d9fbf83c23124fe7bed)
Reviewed-on: https://go-review.googlesource.com/c/tools/+/302689
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
diff --git a/gopls/go.mod b/gopls/go.mod
index 5fb54e3..abe531e 100644
--- a/gopls/go.mod
+++ b/gopls/go.mod
@@ -14,3 +14,5 @@
 	mvdan.cc/gofumpt v0.1.0
 	mvdan.cc/xurls/v2 v2.2.0
 )
+
+replace golang.org/x/tools => ../
diff --git a/gopls/internal/regtest/diagnostics/diagnostics_test.go b/gopls/internal/regtest/diagnostics/diagnostics_test.go
index 75ba7de..1d7cb09 100644
--- a/gopls/internal/regtest/diagnostics/diagnostics_test.go
+++ b/gopls/internal/regtest/diagnostics/diagnostics_test.go
@@ -1862,3 +1862,30 @@
 		)
 	})
 }
+
+// Tests golang/go#45075, a panic in fillreturns breaks diagnostics.
+func TestFillReturnsPanic(t *testing.T) {
+	// At tip, the panic no longer reproduces.
+	testenv.SkipAfterGo1Point(t, 16)
+	const files = `
+-- go.mod --
+module mod.com
+
+go 1.16
+-- main.go --
+package main
+
+
+func foo() int {
+	return x, nil
+}
+
+`
+	Run(t, files, func(t *testing.T, env *Env) {
+		env.OpenFile("main.go")
+		env.Await(
+			env.DiagnosticAtRegexpWithMessage("main.go", `return x`, "wrong number of return values"),
+			LogMatching(protocol.Error, `.*analysis fillreturns.*panicked.*`, 2),
+		)
+	})
+}
diff --git a/internal/lsp/cache/analysis.go b/internal/lsp/cache/analysis.go
index 92af4f1..19675af 100644
--- a/internal/lsp/cache/analysis.go
+++ b/internal/lsp/cache/analysis.go
@@ -212,7 +212,6 @@
 	}
 	defer func() {
 		if r := recover(); r != nil {
-			event.Log(ctx, fmt.Sprintf("analysis panicked: %s", r), tag.Package.Of(pkg.ID()))
 			data.err = errors.Errorf("analysis %s for package %s panicked: %v", analyzer.Name, pkg.PkgPath(), r)
 		}
 	}()
@@ -408,7 +407,8 @@
 		var err error
 		errorAnalyzerDiag, err = s.Analyze(ctx, pkg.ID(), analyzers)
 		if err != nil {
-			return nil, err
+			// Keep going: analysis failures should not block diagnostics.
+			event.Error(ctx, "type error analysis failed", err, tag.Package.Of(pkg.ID()))
 		}
 	}
 	diags := map[span.URI][]*source.Diagnostic{}