]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: implement underIs, coreType, coreString via typeset iterator
authorRobert Griesemer <gri@golang.org>
Thu, 19 Sep 2024 22:20:30 +0000 (15:20 -0700)
committerGopher Robot <gobot@golang.org>
Tue, 24 Sep 2024 23:20:47 +0000 (23:20 +0000)
Remove remaining underIs methods and call underIs function instead.

Change-Id: Ic98430d3a56b85f6f4b35c4508c4c67dafbfa3f2
Reviewed-on: https://go-review.googlesource.com/c/go/+/614240
Reviewed-by: Tim King <taking@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Robert Griesemer <gri@google.com>

16 files changed:
src/cmd/compile/internal/types2/builtins.go
src/cmd/compile/internal/types2/conversions.go
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/index.go
src/cmd/compile/internal/types2/predicates.go
src/cmd/compile/internal/types2/typeparam.go
src/cmd/compile/internal/types2/typeset.go
src/cmd/compile/internal/types2/under.go
src/go/types/builtins.go
src/go/types/conversions.go
src/go/types/expr.go
src/go/types/index.go
src/go/types/predicates.go
src/go/types/typeparam.go
src/go/types/typeset.go
src/go/types/under.go

index 59d2e76ec24f2b9f2d9b72c09c4827df3b89d4e8..c30bc8dc4d114089d933d52c1e70bf39dc062e4d 100644 (file)
@@ -184,8 +184,8 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                        if !isTypeParam(x.typ) {
                                break
                        }
-                       if t.typeSet().underIs(func(t Type) bool {
-                               switch t := arrayPtrDeref(t).(type) {
+                       if underIs(x.typ, func(u Type) bool {
+                               switch t := arrayPtrDeref(u).(type) {
                                case *Basic:
                                        if isString(t) && id == _Len {
                                                return true
index 43208c3d9b9aae390241f3c7fdf8ea8f9f38a103..1dd3e55c2a2903e09ec8fa0a5072ff152fb5183f 100644 (file)
@@ -56,7 +56,7 @@ func (check *Checker) conversion(x *operand, T Type) {
                // If T's type set is empty, or if it doesn't
                // have specific types, constant x cannot be
                // converted.
-               ok = Unalias(T).(*TypeParam).underIs(func(u Type) bool {
+               ok = underIs(T, func(u Type) bool {
                        // u is nil if there are no specific type terms
                        if u == nil {
                                cause = check.sprintf("%s does not contain specific types", T)
index df2f2e4608b751053996ab7ae7b3d6da8e90e8a6..76d7891b733aeb9294797cd2c064aabfcac37505 100644 (file)
@@ -434,7 +434,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
                }
        case *Interface:
                if isTypeParam(target) {
-                       if !u.typeSet().underIs(func(u Type) bool {
+                       if !underIs(target, func(u Type) bool {
                                if u == nil {
                                        return false
                                }
index 4db2213086444e4cd974f4a3e12f9ae2fa83a684..51684340f722b986b881b9f64f167f82c4d4c33e 100644 (file)
@@ -108,7 +108,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
                var key, elem Type // key != nil: we must have all maps
                mode := variable   // non-maps result mode
                // TODO(gri) factor out closure and use it for non-typeparam cases as well
-               if typ.typeSet().underIs(func(u Type) bool {
+               if underIs(x.typ, func(u Type) bool {
                        l := int64(-1) // valid if >= 0
                        var k, e Type  // k is only set for maps
                        switch t := u.(type) {
index d40939e2b5d0c0a247390abdf1a47c29637d0410..ca51706d66c0e5c51e70a84d2b0de32744d363af 100644 (file)
@@ -211,7 +211,7 @@ func hasNil(t Type) bool {
        case *Slice, *Pointer, *Signature, *Map, *Chan:
                return true
        case *Interface:
-               return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool {
+               return !isTypeParam(t) || underIs(t, func(u Type) bool {
                        return u != nil && hasNil(u)
                })
        }
index cedae76c2a1ff4c57aba97f6f48203d6f93b614b..a04f928908fbae907ad5c26bbe0875c54482a400 100644 (file)
@@ -155,13 +155,6 @@ func (t *TypeParam) is(f func(*term) bool) bool {
        return t.iface().typeSet().is(f)
 }
 
-// underIs calls f with the underlying types of the specific type terms
-// of t's constraint and reports whether all calls to f returned true.
-// If there are no specific terms, underIs returns the result of f(nil).
-func (t *TypeParam) underIs(f func(Type) bool) bool {
-       return t.iface().typeSet().underIs(f)
-}
-
 // typeset is an iterator over the (type/underlying type) pairs of the
 // specific type terms of t's constraint.
 // If there are no specific terms, typeset calls yield with (nil, nil).
index 4f53d0d31cf1541321ed83d1730bc621deeb1c76..2ab470274dd99240b0733dae5a0c9a46333a4f1e 100644 (file)
@@ -145,30 +145,6 @@ func (s *_TypeSet) is(f func(*term) bool) bool {
        return true
 }
 
-// underIs calls f with the underlying types of the specific type terms
-// of s and reports whether all calls to f returned true. If there are
-// no specific terms, underIs returns the result of f(nil).
-func (s *_TypeSet) underIs(f func(Type) bool) bool {
-       if !s.hasTerms() {
-               return f(nil)
-       }
-       for _, t := range s.terms {
-               assert(t.typ != nil)
-               // Unalias(x) == under(x) for ~x terms
-               u := Unalias(t.typ)
-               if !t.tilde {
-                       u = under(u)
-               }
-               if debug {
-                       assert(Identical(u, under(u)))
-               }
-               if !f(u) {
-                       return false
-               }
-       }
-       return true
-}
-
 // topTypeSet may be used as type set for the empty interface.
 var topTypeSet = _TypeSet{terms: allTermlist}
 
index b1b6f89b484aed40d42d63761d92551a4b4c66f3..6d7a234ef49cf1d62650bfddff7d2f247f95b754 100644 (file)
@@ -18,11 +18,12 @@ func under(t Type) Type {
 // If typ is a type parameter, underIs returns the result of typ.underIs(f).
 // Otherwise, underIs returns the result of f(under(typ)).
 func underIs(typ Type, f func(Type) bool) bool {
-       typ = Unalias(typ)
-       if tpar, _ := typ.(*TypeParam); tpar != nil {
-               return tpar.underIs(f)
-       }
-       return f(under(typ))
+       var ok bool
+       typeset(typ, func(_, u Type) bool {
+               ok = f(u)
+               return ok
+       })
+       return ok
 }
 
 // typeset is an iterator over the (type/underlying type) pairs of the
@@ -46,45 +47,38 @@ func typeset(t Type, yield func(t, u Type) bool) {
 // identical element types), the single underlying type is the restricted
 // channel type if the restrictions are always the same, or nil otherwise.
 func coreType(t Type) Type {
-       t = Unalias(t)
-       tpar, _ := t.(*TypeParam)
-       if tpar == nil {
-               return under(t)
-       }
-
        var su Type
-       if tpar.underIs(func(u Type) bool {
+       typeset(t, func(_, u Type) bool {
                if u == nil {
                        return false
                }
                if su != nil {
                        u = match(su, u)
                        if u == nil {
+                               su = nil
                                return false
                        }
                }
                // su == nil || match(su, u) != nil
                su = u
                return true
-       }) {
-               return su
-       }
-       return nil
+       })
+       return su
 }
 
 // coreString is like coreType but also considers []byte
 // and strings as identical. In this case, if successful and we saw
 // a string, the result is of type (possibly untyped) string.
 func coreString(t Type) Type {
-       t = Unalias(t)
-       tpar, _ := t.(*TypeParam)
-       if tpar == nil {
-               return under(t) // string or untyped string
+       // This explicit case is needed because otherwise the
+       // result would be string if t is an untyped string.
+       if !isTypeParam(t) {
+               return under(t) // untyped string remains untyped
        }
 
        var su Type
        hasString := false
-       if tpar.underIs(func(u Type) bool {
+       typeset(t, func(_, u Type) bool {
                if u == nil {
                        return false
                }
@@ -95,19 +89,19 @@ func coreString(t Type) Type {
                if su != nil {
                        u = match(su, u)
                        if u == nil {
+                               su = nil
+                               hasString = false
                                return false
                        }
                }
                // su == nil || match(su, u) != nil
                su = u
                return true
-       }) {
-               if hasString {
-                       return Typ[String]
-               }
-               return su
+       })
+       if hasString {
+               return Typ[String]
        }
-       return nil
+       return su
 }
 
 // If x and y are identical, match returns x.
index 2cd6c52b7bf6e2e6f58c4d4f5c7bc956de293600..9f4b09c92d2150a380d736649e12a2c8f3d3dd6b 100644 (file)
@@ -187,8 +187,8 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                        if !isTypeParam(x.typ) {
                                break
                        }
-                       if t.typeSet().underIs(func(t Type) bool {
-                               switch t := arrayPtrDeref(t).(type) {
+                       if underIs(x.typ, func(u Type) bool {
+                               switch t := arrayPtrDeref(u).(type) {
                                case *Basic:
                                        if isString(t) && id == _Len {
                                                return true
index d28c2294a7e3dbdafed4516f9bb45b1be2564e1d..1c1dd14ba4f8e452964dc04df6f1099619a524d5 100644 (file)
@@ -59,7 +59,7 @@ func (check *Checker) conversion(x *operand, T Type) {
                // If T's type set is empty, or if it doesn't
                // have specific types, constant x cannot be
                // converted.
-               ok = Unalias(T).(*TypeParam).underIs(func(u Type) bool {
+               ok = underIs(T, func(u Type) bool {
                        // u is nil if there are no specific type terms
                        if u == nil {
                                cause = check.sprintf("%s does not contain specific types", T)
index 5995e9d87ece329541b9c6883d1e3f4a24ce3451..658de037398237b40b47a63d0bffe3ba2e9dd30d 100644 (file)
@@ -410,7 +410,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
                }
        case *Interface:
                if isTypeParam(target) {
-                       if !u.typeSet().underIs(func(u Type) bool {
+                       if !underIs(target, func(u Type) bool {
                                if u == nil {
                                        return false
                                }
index 7a1666b59ab9b31ffd2840f7f073c648191a4111..1b1a7b0007ab8781eef8485da90775322feb2d73 100644 (file)
@@ -109,7 +109,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst
                var key, elem Type // key != nil: we must have all maps
                mode := variable   // non-maps result mode
                // TODO(gri) factor out closure and use it for non-typeparam cases as well
-               if typ.typeSet().underIs(func(u Type) bool {
+               if underIs(x.typ, func(u Type) bool {
                        l := int64(-1) // valid if >= 0
                        var k, e Type  // k is only set for maps
                        switch t := u.(type) {
index 5261aaf1585cec04c90816e2ad5215f96403cc60..017dc17c6a97961007e0187199a2931749a0f884 100644 (file)
@@ -214,7 +214,7 @@ func hasNil(t Type) bool {
        case *Slice, *Pointer, *Signature, *Map, *Chan:
                return true
        case *Interface:
-               return !isTypeParam(t) || u.typeSet().underIs(func(u Type) bool {
+               return !isTypeParam(t) || underIs(t, func(u Type) bool {
                        return u != nil && hasNil(u)
                })
        }
index 4cff6b7b31c7725616a81e5bf2ff88aa3ecada16..cdcd552739f038d21ced5949ba69044514ee74eb 100644 (file)
@@ -158,13 +158,6 @@ func (t *TypeParam) is(f func(*term) bool) bool {
        return t.iface().typeSet().is(f)
 }
 
-// underIs calls f with the underlying types of the specific type terms
-// of t's constraint and reports whether all calls to f returned true.
-// If there are no specific terms, underIs returns the result of f(nil).
-func (t *TypeParam) underIs(f func(Type) bool) bool {
-       return t.iface().typeSet().underIs(f)
-}
-
 // typeset is an iterator over the (type/underlying type) pairs of the
 // specific type terms of t's constraint.
 // If there are no specific terms, typeset calls yield with (nil, nil).
index 5d28226596c1542a14373c9005d6a5e1c515adf5..e2eb0766b0917494528d19732ea4fe7b703c20af 100644 (file)
@@ -148,30 +148,6 @@ func (s *_TypeSet) is(f func(*term) bool) bool {
        return true
 }
 
-// underIs calls f with the underlying types of the specific type terms
-// of s and reports whether all calls to f returned true. If there are
-// no specific terms, underIs returns the result of f(nil).
-func (s *_TypeSet) underIs(f func(Type) bool) bool {
-       if !s.hasTerms() {
-               return f(nil)
-       }
-       for _, t := range s.terms {
-               assert(t.typ != nil)
-               // Unalias(x) == under(x) for ~x terms
-               u := Unalias(t.typ)
-               if !t.tilde {
-                       u = under(u)
-               }
-               if debug {
-                       assert(Identical(u, under(u)))
-               }
-               if !f(u) {
-                       return false
-               }
-       }
-       return true
-}
-
 // topTypeSet may be used as type set for the empty interface.
 var topTypeSet = _TypeSet{terms: allTermlist}
 
index 16afcb28a9fd4b87eb584164c9eae7e9102dc8d8..b4c2e342a02c933cd602452fd817664df3baa295 100644 (file)
@@ -21,11 +21,12 @@ func under(t Type) Type {
 // If typ is a type parameter, underIs returns the result of typ.underIs(f).
 // Otherwise, underIs returns the result of f(under(typ)).
 func underIs(typ Type, f func(Type) bool) bool {
-       typ = Unalias(typ)
-       if tpar, _ := typ.(*TypeParam); tpar != nil {
-               return tpar.underIs(f)
-       }
-       return f(under(typ))
+       var ok bool
+       typeset(typ, func(_, u Type) bool {
+               ok = f(u)
+               return ok
+       })
+       return ok
 }
 
 // typeset is an iterator over the (type/underlying type) pairs of the
@@ -49,45 +50,38 @@ func typeset(t Type, yield func(t, u Type) bool) {
 // identical element types), the single underlying type is the restricted
 // channel type if the restrictions are always the same, or nil otherwise.
 func coreType(t Type) Type {
-       t = Unalias(t)
-       tpar, _ := t.(*TypeParam)
-       if tpar == nil {
-               return under(t)
-       }
-
        var su Type
-       if tpar.underIs(func(u Type) bool {
+       typeset(t, func(_, u Type) bool {
                if u == nil {
                        return false
                }
                if su != nil {
                        u = match(su, u)
                        if u == nil {
+                               su = nil
                                return false
                        }
                }
                // su == nil || match(su, u) != nil
                su = u
                return true
-       }) {
-               return su
-       }
-       return nil
+       })
+       return su
 }
 
 // coreString is like coreType but also considers []byte
 // and strings as identical. In this case, if successful and we saw
 // a string, the result is of type (possibly untyped) string.
 func coreString(t Type) Type {
-       t = Unalias(t)
-       tpar, _ := t.(*TypeParam)
-       if tpar == nil {
-               return under(t) // string or untyped string
+       // This explicit case is needed because otherwise the
+       // result would be string if t is an untyped string.
+       if !isTypeParam(t) {
+               return under(t) // untyped string remains untyped
        }
 
        var su Type
        hasString := false
-       if tpar.underIs(func(u Type) bool {
+       typeset(t, func(_, u Type) bool {
                if u == nil {
                        return false
                }
@@ -98,19 +92,19 @@ func coreString(t Type) Type {
                if su != nil {
                        u = match(su, u)
                        if u == nil {
+                               su = nil
+                               hasString = false
                                return false
                        }
                }
                // su == nil || match(su, u) != nil
                su = u
                return true
-       }) {
-               if hasString {
-                       return Typ[String]
-               }
-               return su
+       })
+       if hasString {
+               return Typ[String]
        }
-       return nil
+       return su
 }
 
 // If x and y are identical, match returns x.