diff options
author | Robert Findley <rfindley@google.com> | 2021-11-17 10:39:36 -0500 |
---|---|---|
committer | Robert Findley <rfindley@google.com> | 2021-11-17 19:50:58 +0000 |
commit | 88474d47ddeb5714a18923048beaa5dafa7196d5 (patch) | |
tree | caccdceae5f2839ec3e7ccfa22180c5bc2a8260b /src/go/types/predicates.go | |
parent | aa34ea2f4c57ea2648286463ef3f891e49b64fa8 (diff) | |
download | go-88474d47ddeb5714a18923048beaa5dafa7196d5.tar.gz go-88474d47ddeb5714a18923048beaa5dafa7196d5.zip |
go/types: underlying type of a type parameter is its constraint interface
This is a port of CL 359016 from types2 to go/types. Some of the code
around untyped nil differed (because we have to treat untyped nil
differently in go/types for historical reasons).
Updates #47916
Change-Id: Ifc428ed977bf2f4f84cc831f1a3527156940d7b8
Reviewed-on: https://go-review.googlesource.com/c/go/+/364716
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/go/types/predicates.go')
-rw-r--r-- | src/go/types/predicates.go | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 78ad6c4f23..5204eb0c29 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -49,13 +49,10 @@ func allNumericOrString(typ Type) bool { return allBasic(typ, IsNumeric|IsString // for all specific types of the type parameter's type set. // allBasic(t, info) is an optimized version of isBasic(structuralType(t), info). func allBasic(t Type, info BasicInfo) bool { - switch u := under(t).(type) { - case *Basic: - return u.info&info != 0 - case *TypeParam: - return u.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) + if tpar, _ := t.(*TypeParam); tpar != nil { + return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) } - return false + return isBasic(t, info) } // hasName reports whether t has a name. This includes @@ -124,7 +121,7 @@ func comparable(T Type, seen map[Type]bool) bool { // assume invalid types to be comparable // to avoid follow-up errors return t.kind != UntypedNil - case *Pointer, *Interface, *Chan: + case *Pointer, *Chan: return true case *Struct: for _, f := range t.fields { @@ -135,7 +132,13 @@ func comparable(T Type, seen map[Type]bool) bool { return true case *Array: return comparable(t.elem, seen) + case *Interface: + if tparamIsIface && isTypeParam(T) { + return t.IsComparable() + } + return true case *TypeParam: + assert(!tparamIsIface) return t.iface().IsComparable() } return false @@ -146,9 +149,17 @@ func hasNil(t Type) bool { switch u := under(t).(type) { case *Basic: return u.kind == UnsafePointer - case *Slice, *Pointer, *Signature, *Interface, *Map, *Chan: + case *Slice, *Pointer, *Signature, *Map, *Chan: + return true + case *Interface: + if tparamIsIface && isTypeParam(t) { + return u.typeSet().underIs(func(u Type) bool { + return u != nil && hasNil(u) + }) + } return true case *TypeParam: + assert(!tparamIsIface) return u.underIs(func(u Type) bool { return u != nil && hasNil(u) }) |