aboutsummaryrefslogtreecommitdiff
path: root/src/go/types/predicates.go
diff options
context:
space:
mode:
authorRobert Findley <rfindley@google.com>2021-11-17 10:39:36 -0500
committerRobert Findley <rfindley@google.com>2021-11-17 19:50:58 +0000
commit88474d47ddeb5714a18923048beaa5dafa7196d5 (patch)
treecaccdceae5f2839ec3e7ccfa22180c5bc2a8260b /src/go/types/predicates.go
parentaa34ea2f4c57ea2648286463ef3f891e49b64fa8 (diff)
downloadgo-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.go27
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)
})