internal/typeparams: fix crash in interface hover with empty type set

The logic of typeparams.Free.Has was not handling ErrEmptyTypeSet from
InterfaceTermSet, leading to a crash.

Also fix a hover marker in hover/generics.txt that was apparently
missing a '@'.

Fixes golang/go#68213

Change-Id: I0e264b5c5f5ecc0d09a0b8ab381eb7d7c492c18f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/595555
Auto-Submit: Robert Findley <rfindley@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
Rob Findley 2024-06-27 16:50:45 +00:00 коммит произвёл Gopher Robot
Родитель c0ae6bbd24
Коммит 72edac2ff3
2 изменённых файлов: 69 добавлений и 38 удалений

Просмотреть файл

@ -3,8 +3,11 @@ This file contains tests for hovering over generic Go code.
Requires go1.20+ for the new go/doc/comment package, and a change in Go 1.20 Requires go1.20+ for the new go/doc/comment package, and a change in Go 1.20
that affected the formatting of constraint interfaces. that affected the formatting of constraint interfaces.
Its size expectations assume a 64-bit machine.
-- flags -- -- flags --
-min_go=go1.20 -min_go=go1.20
-skip_goarch=386,arm
-- go.mod -- -- go.mod --
// A go.mod is require for correct pkgsite links. // A go.mod is require for correct pkgsite links.
@ -13,10 +16,28 @@ module mod.com
go 1.18 go 1.18
-- issue68213.go --
package generics
// Hovering over an interface with empty type set must not panic.
type empty interface { //@hover("empty", "empty", empty)
int
string
}
-- @empty --
```go
type empty interface { // size=16 (0x10)
int
string
}
```
Hovering over an interface with empty type set must not panic.
-- generics.go -- -- generics.go --
package generics package generics
type value[T any] struct { //hover("lue", "value", value),hover("T", "T", valueT) type value[T any] struct { //@hover("lue", "value", value),hover("T", "T", valueT)
val T //@hover("T", "T", valuevalT) val T //@hover("T", "T", valuevalT)
Q int64 //@hover("Q", "Q", valueQ) Q int64 //@hover("Q", "Q", valueQ)
} }
@ -30,6 +51,52 @@ func F[P interface{ ~int | string }]() { //@hover("P", "P", Ptparam)
var _ P //@hover("P","P",Pvar) var _ P //@hover("P","P",Pvar)
} }
-- @value --
```go
type value[T any] struct {
val T //@hover("T", "T", valuevalT)
Q int64 //@hover("Q", "Q", valueQ)
}
```
-- @valueT --
```go
type parameter T any
```
-- @valuevalT --
```go
type parameter T any
```
-- @valueQ --
```go
field Q int64 // size=8
```
@hover("Q", "Q", valueQ)
-- @ValueT --
```go
type parameter T any
```
-- @ValuevalT --
```go
type parameter T any
```
-- @ValueQ --
```go
field Q int64 // size=8
```
@hover("Q", "Q", ValueQ)
[`(generics.Value).Q` on pkg.go.dev](https://pkg.go.dev/mod.com#Value.Q)
-- @Ptparam --
```go
type parameter P interface{~int | string}
```
-- @Pvar --
```go
type parameter P interface{~int | string}
```
-- inferred.go -- -- inferred.go --
package generics package generics
@ -44,42 +111,7 @@ func _() {
_ = app([]int{}, 0) //@hover("app", "app", appint) _ = app([]int{}, 0) //@hover("app", "app", appint)
} }
-- @ValueQ --
```go
field Q int64 // size=8
```
@hover("Q", "Q", ValueQ)
[`(generics.Value).Q` on pkg.go.dev](https://pkg.go.dev/mod.com#Value.Q)
-- @ValueT --
```go
type parameter T any
```
-- @ValuevalT --
```go
type parameter T any
```
-- @appint -- -- @appint --
```go ```go
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
``` ```
-- @valueQ --
```go
field Q int64 // size=8
```
@hover("Q", "Q", valueQ)
-- @valuevalT --
```go
type parameter T any
```
-- @Ptparam --
```go
type parameter P interface{~int | string}
```
-- @Pvar --
```go
type parameter P interface{~int | string}
```

Просмотреть файл

@ -21,7 +21,6 @@ type Free struct {
// Has reports whether the specified type has a free type parameter. // Has reports whether the specified type has a free type parameter.
func (w *Free) Has(typ types.Type) (res bool) { func (w *Free) Has(typ types.Type) (res bool) {
// detect cycles // detect cycles
if x, ok := w.seen[typ]; ok { if x, ok := w.seen[typ]; ok {
return x return x
@ -83,7 +82,7 @@ func (w *Free) Has(typ types.Type) (res bool) {
} }
terms, err := InterfaceTermSet(t) terms, err := InterfaceTermSet(t)
if err != nil { if err != nil {
panic(err) return false // ill typed
} }
for _, term := range terms { for _, term := range terms {
if w.Has(term.Type()) { if w.Has(term.Type()) {