gopls/completion: don't take address of interfaces for "%p" values

When completing printf calls, we previously only preferred
pointers and slices. This meant to make an interface object acceptable
for "%p", we would take its address to turn it into a pointer.

Change "%p" to also prefer interface types in addition to chan, map, and
func, which all have pointer semantics. Note that interface types
don't necessarily contain pointers, but they might, so tacking on "&"
automatically is annoying.

Fixes golang/go#65609

Change-Id: Idf2ba9cf27fa4ea8e721396cded5a7743d79807b
Reviewed-on: https://go-review.googlesource.com/c/tools/+/593575
Reviewed-by: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/gopls/internal/golang/completion/completion.go b/gopls/internal/golang/completion/completion.go
index bdd1218..cc235ce 100644
--- a/gopls/internal/golang/completion/completion.go
+++ b/gopls/internal/golang/completion/completion.go
@@ -2128,6 +2128,7 @@
 	kindBool
 	kindBytes
 	kindPtr
+	kindInterface
 	kindFloat
 	kindComplex
 	kindError
@@ -3270,6 +3271,8 @@
 		if _, isArray := t.Elem().Underlying().(*types.Array); isArray {
 			kind |= kindArray
 		}
+	case *types.Interface:
+		kind |= kindInterface
 	case *types.Basic:
 		switch info := t.Info(); {
 		case info&types.IsString > 0:
diff --git a/gopls/internal/golang/completion/printf.go b/gopls/internal/golang/completion/printf.go
index a7413bc..958d77e 100644
--- a/gopls/internal/golang/completion/printf.go
+++ b/gopls/internal/golang/completion/printf.go
@@ -152,7 +152,9 @@
 			// Omit kindStringer and kindError though technically allowed.
 			addVerb(kindString | kindBytes | kindInt | kindFloat | kindComplex)
 		case 'p':
-			addVerb(kindPtr | kindSlice)
+			// Accept kindInterface even though it doesn't necessarily contain a pointer.
+			// This avoids us offering "&foo" when "foo" is an interface type.
+			addVerb(kindPtr | kindSlice | kindMap | kindFunc | kindInterface)
 		case 'w':
 			addVerb(kindError)
 		case '+', '-', '#', ' ', '.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
diff --git a/gopls/internal/golang/completion/printf_test.go b/gopls/internal/golang/completion/printf_test.go
index 19d295b..1a3d971 100644
--- a/gopls/internal/golang/completion/printf_test.go
+++ b/gopls/internal/golang/completion/printf_test.go
@@ -41,7 +41,7 @@
 		{"%s", 1, kindString | kindBytes | kindStringer | kindError},
 		{"%x", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},
 		{"%X", 1, kindString | kindBytes | kindInt | kindFloat | kindComplex},
-		{"%p", 1, kindPtr | kindSlice},
+		{"%p", 1, kindPtr | kindSlice | kindMap | kindFunc | kindInterface},
 		{"%w", 1, kindError},
 
 		{"%1.2f", 1, kindFloat | kindComplex},
diff --git a/gopls/internal/test/marker/testdata/completion/printf.txt b/gopls/internal/test/marker/testdata/completion/printf.txt
index 99b8a1e..270927e 100644
--- a/gopls/internal/test/marker/testdata/completion/printf.txt
+++ b/gopls/internal/test/marker/testdata/completion/printf.txt
@@ -36,4 +36,7 @@
 		a, //@rank(",", printfInt, printfFloat)
 		a, //@rank(",", printfFloat, printfInt)
 	)
+
+  // Don't insert as "&aStringer"
+	fmt.Printf("%p", a) //@snippet(")", printfStringer, "aStringer")
 }