Skip to content

Commit

Permalink
internal/typeparams: fix crash in interface hover with empty type set
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
findleyr authored and gopherbot committed Jun 27, 2024
1 parent c0ae6bb commit 72edac2
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 31 deletions.
90 changes: 61 additions & 29 deletions gopls/internal/test/marker/testdata/hover/generics.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
that affected the formatting of constraint interfaces.

Its size expectations assume a 64-bit machine.

-- flags --
-min_go=go1.20
-skip_goarch=386,arm

-- go.mod --
// A go.mod is require for correct pkgsite links.
Expand All @@ -13,10 +16,28 @@ module mod.com

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 --
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)
Q int64 //@hover("Q", "Q", valueQ)
}
Expand All @@ -30,51 +51,44 @@ func F[P interface{ ~int | string }]() { //@hover("P", "P", Ptparam)
var _ P //@hover("P","P",Pvar)
}

-- inferred.go --
package generics

func app[S interface{ ~[]E }, E interface{}](s S, e E) S {
return append(s, e)
}

func _() {
_ = app[[]int] //@hover("app", "app", appint)
_ = app[[]int, int] //@hover("app", "app", appint)
_ = app[[]int]([]int{}, 0) //@hover("app", "app", appint), diag("[[]int]", re"unnecessary")
_ = app([]int{}, 0) //@hover("app", "app", appint)
}

-- @ValueQ --
-- @value --
```go
field Q int64 // size=8
type value[T any] struct {
val T //@hover("T", "T", valuevalT)
Q int64 //@hover("Q", "Q", valueQ)
}
```

@hover("Q", "Q", ValueQ)


[`(generics.Value).Q` on pkg.go.dev](https://pkg.go.dev/mod.com#Value.Q)
-- @ValueT --
-- @valueT --
```go
type parameter T any
```
-- @ValuevalT --
-- @valuevalT --
```go
type parameter T any
```
-- @appint --
```go
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 --
-- @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}
Expand All @@ -83,3 +97,21 @@ type parameter P interface{~int | string}
```go
type parameter P interface{~int | string}
```
-- inferred.go --
package generics

func app[S interface{ ~[]E }, E interface{}](s S, e E) S {
return append(s, e)
}

func _() {
_ = app[[]int] //@hover("app", "app", appint)
_ = app[[]int, int] //@hover("app", "app", appint)
_ = app[[]int]([]int{}, 0) //@hover("app", "app", appint), diag("[[]int]", re"unnecessary")
_ = app([]int{}, 0) //@hover("app", "app", appint)
}

-- @appint --
```go
func app(s []int, e int) []int // func[S interface{~[]E}, E interface{}](s S, e E) S
```
3 changes: 1 addition & 2 deletions internal/typeparams/free.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ type Free struct {

// Has reports whether the specified type has a free type parameter.
func (w *Free) Has(typ types.Type) (res bool) {

// detect cycles
if x, ok := w.seen[typ]; ok {
return x
Expand Down Expand Up @@ -83,7 +82,7 @@ func (w *Free) Has(typ types.Type) (res bool) {
}
terms, err := InterfaceTermSet(t)
if err != nil {
panic(err)
return false // ill typed
}
for _, term := range terms {
if w.Has(term.Type()) {
Expand Down

0 comments on commit 72edac2

Please sign in to comment.