internal/lsp/source: fix panic in formatZeroValue for invalid type

formatZeroValue is currently only used when formatting return values for
statement completion. Per golang/go#40956, it must be possible to hit
this codepath with an invalid type.

In this case, the empty string seems like a reasonable value. Perhaps we
could do better, but fix the panic for now.

Fixes golang/go#40956

Change-Id: I45b559d41001c857cef34aea2a5ac4a9096fe950
Reviewed-on: https://go-review.googlesource.com/c/tools/+/249818
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go
index a043a17..63bfd4e 100644
--- a/internal/lsp/source/util.go
+++ b/internal/lsp/source/util.go
@@ -582,7 +582,8 @@
 	return nil
 }
 
-// formatZeroValue produces Go code representing the zero value of T.
+// formatZeroValue produces Go code representing the zero value of T. It
+// returns the empty string if T is invalid.
 func formatZeroValue(T types.Type, qf types.Qualifier) string {
 	switch u := T.Underlying().(type) {
 	case *types.Basic:
@@ -594,7 +595,7 @@
 		case u.Info()&types.IsBoolean > 0:
 			return "false"
 		default:
-			panic(fmt.Sprintf("unhandled basic type: %v", u))
+			return ""
 		}
 	case *types.Pointer, *types.Interface, *types.Chan, *types.Map, *types.Slice, *types.Signature:
 		return "nil"
diff --git a/internal/lsp/source/util_test.go b/internal/lsp/source/util_test.go
new file mode 100644
index 0000000..0dfa0b0
--- /dev/null
+++ b/internal/lsp/source/util_test.go
@@ -0,0 +1,28 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package source
+
+import (
+	"go/types"
+	"testing"
+)
+
+func TestFormatZeroValue(t *testing.T) {
+	tests := []struct {
+		typ  types.Type
+		want string
+	}{
+		{types.Typ[types.String], `""`},
+		{types.Typ[types.Byte], "0"},
+		{types.Typ[types.Invalid], ""},
+		{types.Universe.Lookup("error").Type(), "nil"},
+	}
+
+	for _, test := range tests {
+		if got := formatZeroValue(test.typ, nil); got != test.want {
+			t.Errorf("formatZeroValue(%v) = %q, want %q", test.typ, got, test.want)
+		}
+	}
+}