Skip to content

Commit

Permalink
go/types/typeutil: audit for types.Alias safety
Browse files Browse the repository at this point in the history
Updates golang/go#65294

Change-Id: I921517b9c722d03aaa7c3dc3e0c45364b3a1d53d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/559915
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Tim King <taking@google.com>
  • Loading branch information
adonovan committed Feb 6, 2024
1 parent a297bfd commit 0d87589
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
7 changes: 7 additions & 0 deletions go/types/typeutil/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"go/types"
"reflect"

"golang.org/x/tools/internal/aliases"
"golang.org/x/tools/internal/typeparams"
)

Expand Down Expand Up @@ -259,6 +260,9 @@ func (h Hasher) hashFor(t types.Type) uint32 {
case *types.Basic:
return uint32(t.Kind())

case *aliases.Alias:
return h.Hash(t.Underlying())

case *types.Array:
return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem())

Expand Down Expand Up @@ -457,6 +461,9 @@ func (h Hasher) shallowHash(t types.Type) uint32 {
// elements (mostly Slice, Pointer, Basic, Named),
// so there's no need to optimize anything else.
switch t := t.(type) {
case *aliases.Alias:
return h.shallowHash(t.Underlying())

case *types.Signature:
var hash uint32 = 604171
if t.Variadic() {
Expand Down
29 changes: 29 additions & 0 deletions go/types/typeutil/map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,15 @@ var Issue56048 = Issue56048_I.m
type Issue56048_Ib interface{ m() chan []*interface { Issue56048_Ib } }
var Issue56048b = Issue56048_Ib.m
// Non-generic alias
type NonAlias int
type Alias1 = NonAlias
type Alias2 = NonAlias
// Generic alias (requires go1.23)
// type SetOfInt = map[int]bool
// type Set[T comparable] = map[K]bool
// type SetOfInt2 = Set[int]
`

fset := token.NewFileSet()
Expand Down Expand Up @@ -307,6 +316,16 @@ var Issue56048b = Issue56048_Ib.m
Quux = scope.Lookup("Quux").Type()
Issue56048 = scope.Lookup("Issue56048").Type()
Issue56048b = scope.Lookup("Issue56048b").Type()

// In go1.23 these will be *types.Alias; for now they are all int.
NonAlias = scope.Lookup("NonAlias").Type()
Alias1 = scope.Lookup("Alias1").Type()
Alias2 = scope.Lookup("Alias2").Type()

// Requires go1.23.
// SetOfInt = scope.Lookup("SetOfInt").Type()
// Set = scope.Lookup("Set").Type().(*types.Alias)
// SetOfInt2 = scope.Lookup("SetOfInt2").Type()
)

tmap := new(typeutil.Map)
Expand Down Expand Up @@ -379,6 +398,16 @@ var Issue56048b = Issue56048_Ib.m

{Issue56048, "Issue56048", true}, // (not actually about generics)
{Issue56048b, "Issue56048b", true}, // (not actually about generics)

// All three types are identical.
{NonAlias, "NonAlias", true},
{Alias1, "Alias1", false},
{Alias2, "Alias2", false},

// Generic aliases: requires go1.23.
// {SetOfInt, "SetOfInt", true},
// {Set, "Set", false},
// {SetOfInt2, "SetOfInt2", false},
}

for _, step := range steps {
Expand Down
6 changes: 4 additions & 2 deletions go/types/typeutil/methodsetcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ package typeutil
import (
"go/types"
"sync"

"golang.org/x/tools/internal/aliases"
)

// A MethodSetCache records the method set of each type T for which
Expand All @@ -32,12 +34,12 @@ func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {
cache.mu.Lock()
defer cache.mu.Unlock()

switch T := T.(type) {
switch T := aliases.Unalias(T).(type) {
case *types.Named:
return cache.lookupNamed(T).value

case *types.Pointer:
if N, ok := T.Elem().(*types.Named); ok {
if N, ok := aliases.Unalias(T.Elem()).(*types.Named); ok {
return cache.lookupNamed(N).pointer
}
}
Expand Down

0 comments on commit 0d87589

Please sign in to comment.