]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: remove under(Type) in favor of Type.Underlying()
authorMark Freeman <mark@golang.org>
Thu, 16 Oct 2025 15:08:13 +0000 (11:08 -0400)
committerGopher Robot <gobot@golang.org>
Thu, 16 Oct 2025 22:30:18 +0000 (15:30 -0700)
As of CL 695977, under(Type) simply delegates to Type.Underlying().
This is just a cleanup.

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

55 files changed:
src/cmd/compile/internal/types2/assignments.go
src/cmd/compile/internal/types2/builtins.go
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/const.go
src/cmd/compile/internal/types2/conversions.go
src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/gcsizes.go
src/cmd/compile/internal/types2/index.go
src/cmd/compile/internal/types2/infer.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/object.go
src/cmd/compile/internal/types2/operand.go
src/cmd/compile/internal/types2/predicates.go
src/cmd/compile/internal/types2/range.go
src/cmd/compile/internal/types2/sizes.go
src/cmd/compile/internal/types2/struct.go
src/cmd/compile/internal/types2/typeparam.go
src/cmd/compile/internal/types2/typeset.go
src/cmd/compile/internal/types2/typeset_test.go
src/cmd/compile/internal/types2/typestring.go
src/cmd/compile/internal/types2/typeterm.go
src/cmd/compile/internal/types2/typexpr.go
src/cmd/compile/internal/types2/under.go
src/cmd/compile/internal/types2/unify.go
src/cmd/compile/internal/types2/union.go
src/go/types/assignments.go
src/go/types/builtins.go
src/go/types/call.go
src/go/types/const.go
src/go/types/conversions.go
src/go/types/decl.go
src/go/types/expr.go
src/go/types/gcsizes.go
src/go/types/index.go
src/go/types/infer.go
src/go/types/instantiate.go
src/go/types/lookup.go
src/go/types/methodset.go
src/go/types/object.go
src/go/types/operand.go
src/go/types/predicates.go
src/go/types/range.go
src/go/types/sizes.go
src/go/types/struct.go
src/go/types/typeparam.go
src/go/types/typeset.go
src/go/types/typeset_test.go
src/go/types/typestring.go
src/go/types/typeterm.go
src/go/types/typexpr.go
src/go/types/under.go
src/go/types/unify.go
src/go/types/union.go

index 8af5f4037a5e3ef1c366173148f0bc9704341dc9..87f5c8beeafcafaeffeec812a727ea1887337a41 100644 (file)
@@ -91,7 +91,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
        // x.typ is typed
 
        // A generic (non-instantiated) function value cannot be assigned to a variable.
-       if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
+       if sig, _ := x.typ.Underlying().(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
                check.errorf(x, WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context)
                x.mode = invalid
                return
@@ -261,7 +261,7 @@ func (check *Checker) assignVar(lhs, rhs syntax.Expr, x *operand, context string
                var target *target
                // avoid calling ExprString if not needed
                if T != nil {
-                       if _, ok := under(T).(*Signature); ok {
+                       if _, ok := T.Underlying().(*Signature); ok {
                                target = newTarget(T, ExprString(lhs))
                        }
                }
index df207a2746d627a746186a7997674151ccf1635d..84acb4ca484164f8ea53ef2986d1c6ee69f6b422 100644 (file)
@@ -144,7 +144,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                // len(x)
                mode := invalid
                var val constant.Value
-               switch t := arrayPtrDeref(under(x.typ)).(type) {
+               switch t := arrayPtrDeref(x.typ.Underlying()).(type) {
                case *Basic:
                        if isString(t) && id == _Len {
                                if x.mode == constant_ {
@@ -203,7 +203,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
                if mode == invalid {
                        // avoid error if underlying type is invalid
-                       if isValid(under(x.typ)) {
+                       if isValid(x.typ.Underlying()) {
                                code := InvalidCap
                                if id == _Len {
                                        code = InvalidLen
@@ -322,7 +322,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                // (applyTypeFunc never calls f with a type parameter)
                f := func(typ Type) Type {
                        assert(!isTypeParam(typ))
-                       if t, _ := under(typ).(*Basic); t != nil {
+                       if t, _ := typ.Underlying().(*Basic); t != nil {
                                switch t.kind {
                                case Float32:
                                        return Typ[Complex64]
@@ -472,7 +472,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
                // (applyTypeFunc never calls f with a type parameter)
                f := func(typ Type) Type {
                        assert(!isTypeParam(typ))
-                       if t, _ := under(typ).(*Basic); t != nil {
+                       if t, _ := typ.Underlying().(*Basic); t != nil {
                                switch t.kind {
                                case Complex64:
                                        return Typ[Float32]
@@ -1020,7 +1020,7 @@ func hasVarSize(t Type, seen map[*Named]bool) (varSized bool) {
                }()
        }
 
-       switch u := under(t).(type) {
+       switch u := t.Underlying().(type) {
        case *Array:
                return hasVarSize(u.elem, seen)
        case *Struct:
@@ -1112,7 +1112,7 @@ func makeSig(res Type, args ...Type) *Signature {
 // otherwise it returns typ.
 func arrayPtrDeref(typ Type) Type {
        if p, ok := Unalias(typ).(*Pointer); ok {
-               if a, _ := under(p.base).(*Array); a != nil {
+               if a, _ := p.base.Underlying().(*Array); a != nil {
                        return a
                }
        }
index b7a2ebb41ec9765d3807ab447a58919e9f9f1241..aca205ad985013a6ad3fd0d7db75a5e06e00da11 100644 (file)
@@ -205,7 +205,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
                case 1:
                        check.expr(nil, x, call.ArgList[0])
                        if x.mode != invalid {
-                               if t, _ := under(T).(*Interface); t != nil && !isTypeParam(T) {
+                               if t, _ := T.Underlying().(*Interface); t != nil && !isTypeParam(T) {
                                        if !t.IsMethodSet() {
                                                check.errorf(call, MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)
                                                break
@@ -812,7 +812,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *TypeName
        obj, index, indirect = lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel, false)
        if obj == nil {
                // Don't report another error if the underlying type was invalid (go.dev/issue/49541).
-               if !isValid(under(x.typ)) {
+               if !isValid(x.typ.Underlying()) {
                        goto Error
                }
 
index 5e5bc74ba34ed6081225e399b242ae106c309aed..b68d72de4d27f4ebfada127f1d3e227b097cd0c8 100644 (file)
@@ -33,7 +33,7 @@ func (check *Checker) overflow(x *operand, opPos syntax.Pos) {
        // x.typ cannot be a type parameter (type
        // parameters cannot be constant types).
        if isTyped(x.typ) {
-               check.representable(x, under(x.typ).(*Basic))
+               check.representable(x, x.typ.Underlying().(*Basic))
                return
        }
 
index 0ad79afe71c409d1cdb1c2144d29786962b9d7d2..d0920d7ef1006d75a8f0110c7b4b4ddd31c2bc95 100644 (file)
@@ -18,7 +18,7 @@ func (check *Checker) conversion(x *operand, T Type) {
        constArg := x.mode == constant_
 
        constConvertibleTo := func(T Type, val *constant.Value) bool {
-               switch t, _ := under(T).(*Basic); {
+               switch t, _ := T.Underlying().(*Basic); {
                case t == nil:
                        // nothing to do
                case representableConst(x.val, check, t, val):
@@ -142,8 +142,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
        origT := T
        V := Unalias(x.typ)
        T = Unalias(T)
-       Vu := under(V)
-       Tu := under(T)
+       Vu := V.Underlying()
+       Tu := T.Underlying()
        Vp, _ := V.(*TypeParam)
        Tp, _ := T.(*TypeParam)
 
@@ -158,7 +158,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
        // and their pointer base types are not type parameters"
        if V, ok := V.(*Pointer); ok {
                if T, ok := T.(*Pointer); ok {
-                       if IdenticalIgnoreTags(under(V.base), under(T.base)) && !isTypeParam(V.base) && !isTypeParam(T.base) {
+                       if IdenticalIgnoreTags(V.base.Underlying(), T.base.Underlying()) && !isTypeParam(V.base) && !isTypeParam(T.base) {
                                return true
                        }
                }
@@ -211,7 +211,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
                                return false
                        }
                case *Pointer:
-                       if a, _ := under(a.Elem()).(*Array); a != nil {
+                       if a, _ := a.Elem().Underlying().(*Array); a != nil {
                                if Identical(s.Elem(), a.Elem()) {
                                        if check == nil || check.allowVersion(go1_17) {
                                                return true
@@ -292,23 +292,23 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
 }
 
 func isUintptr(typ Type) bool {
-       t, _ := under(typ).(*Basic)
+       t, _ := typ.Underlying().(*Basic)
        return t != nil && t.kind == Uintptr
 }
 
 func isUnsafePointer(typ Type) bool {
-       t, _ := under(typ).(*Basic)
+       t, _ := typ.Underlying().(*Basic)
        return t != nil && t.kind == UnsafePointer
 }
 
 func isPointer(typ Type) bool {
-       _, ok := under(typ).(*Pointer)
+       _, ok := typ.Underlying().(*Pointer)
        return ok
 }
 
 func isBytesOrRunes(typ Type) bool {
-       if s, _ := under(typ).(*Slice); s != nil {
-               t, _ := under(s.elem).(*Basic)
+       if s, _ := typ.Underlying().(*Slice); s != nil {
+               t, _ := s.elem.Underlying().(*Basic)
                return t != nil && (t.kind == Byte || t.kind == Rune)
        }
        return false
index 70e79129c91437736c815dc2f2b2216199d344b0..b830cb6f4f3c1c89785e853bdabcfff561cd26f3 100644 (file)
@@ -391,7 +391,7 @@ func (check *Checker) constDecl(obj *Const, typ, init syntax.Expr, inherited boo
                if !isConstType(t) {
                        // don't report an error if the type is an invalid C (defined) type
                        // (go.dev/issue/22090)
-                       if isValid(under(t)) {
+                       if isValid(t.Underlying()) {
                                check.errorf(typ, InvalidConstType, "invalid constant type %s", t)
                        }
                        obj.typ = Typ[Invalid]
index e5f9a1c6f7cb491985b33bbab2846313bdbefd55..d62b0247578d6e5b800a505b4f1974f46d7c95c1 100644 (file)
@@ -361,7 +361,7 @@ func (check *Checker) updateExprType(x syntax.Expr, typ Type, final bool) {
        // If the new type is not final and still untyped, just
        // update the recorded type.
        if !final && isUntyped(typ) {
-               old.typ = under(typ).(*Basic)
+               old.typ = typ.Underlying().(*Basic)
                check.untyped[x] = old
                return
        }
@@ -431,7 +431,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
                return nil, nil, InvalidUntypedConversion
        }
 
-       switch u := under(target).(type) {
+       switch u := target.Underlying().(type) {
        case *Basic:
                if x.mode == constant_ {
                        v, code := check.representation(x, u)
@@ -616,7 +616,7 @@ Error:
 // incomparableCause returns a more specific cause why typ is not comparable.
 // If there is no more specific cause, the result is "".
 func (check *Checker) incomparableCause(typ Type) string {
-       switch under(typ).(type) {
+       switch typ.Underlying().(type) {
        case *Slice, *Signature, *Map:
                return compositeKind(typ) + " can only be compared to nil"
        }
@@ -963,7 +963,7 @@ type target struct {
 // The result is nil if typ is not a signature.
 func newTarget(typ Type, desc string) *target {
        if typ != nil {
-               if sig, _ := under(typ).(*Signature); sig != nil {
+               if sig, _ := typ.Underlying().(*Signature); sig != nil {
                        return &target{sig, desc}
                }
        }
@@ -1112,7 +1112,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
                        check.errorf(x, InvalidAssert, invalidOp+"cannot use type assertion on type parameter value %s", x)
                        goto Error
                }
-               if _, ok := under(x.typ).(*Interface); !ok {
+               if _, ok := x.typ.Underlying().(*Interface); !ok {
                        check.errorf(x, InvalidAssert, invalidOp+"%s is not an interface", x)
                        goto Error
                }
index 15f3e006425ade842f3139fda9c2de6f9023cdca..54e8ea23c173c53791dbd45c121e4ab49a788e67 100644 (file)
@@ -16,7 +16,7 @@ func (s *gcSizes) Alignof(T Type) (result int64) {
 
        // For arrays and structs, alignment is defined in terms
        // of alignment of the elements and fields, respectively.
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Array:
                // spec: "For a variable x of array type: unsafe.Alignof(x)
                // is the same as unsafe.Alignof(x[0]), but at least 1."
@@ -96,7 +96,7 @@ func (s *gcSizes) Offsetsof(fields []*Var) []int64 {
 }
 
 func (s *gcSizes) Sizeof(T Type) int64 {
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Basic:
                assert(isTyped(T))
                k := t.kind
index 7e16a87332dcdf946764dbe9041a01191708445d..ca84184d35afedd6b793a783b2bc9cc19a3540e7 100644 (file)
@@ -35,7 +35,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
                return false
 
        case value:
-               if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
+               if sig, _ := x.typ.Underlying().(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
                        // function instantiation
                        return true
                }
@@ -50,7 +50,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
        // ordinary index expression
        valid := false
        length := int64(-1) // valid if >= 0
-       switch typ := under(x.typ).(type) {
+       switch typ := x.typ.Underlying().(type) {
        case *Basic:
                if isString(typ) {
                        valid = true
@@ -73,7 +73,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
                x.typ = typ.elem
 
        case *Pointer:
-               if typ, _ := under(typ.base).(*Array); typ != nil {
+               if typ, _ := typ.base.Underlying().(*Array); typ != nil {
                        valid = true
                        length = typ.len
                        x.mode = variable
@@ -124,7 +124,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
                                        mode = value
                                }
                        case *Pointer:
-                               if t, _ := under(t.base).(*Array); t != nil {
+                               if t, _ := t.base.Underlying().(*Array); t != nil {
                                        l = t.len
                                        e = t.elem
                                }
@@ -247,7 +247,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) {
                // but don't go from untyped string to string.
                cu = Typ[String]
                if !isTypeParam(x.typ) {
-                       cu = under(x.typ) // untyped string remains untyped
+                       cu = x.typ.Underlying() // untyped string remains untyped
                }
        }
 
@@ -292,7 +292,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) {
                x.typ = &Slice{elem: u.elem}
 
        case *Pointer:
-               if u, _ := under(u.base).(*Array); u != nil {
+               if u, _ := u.base.Underlying().(*Array); u != nil {
                        valid = true
                        length = u.len
                        x.typ = &Slice{elem: u.elem}
index 08d422969059f234f9d76dd125e34cf36f29da11..e7c5959737241396bd2ab9595ee1d36c86781799 100644 (file)
@@ -668,7 +668,7 @@ func coreTerm(tpar *TypeParam) (*term, bool) {
        if n == 1 {
                if debug {
                        u, _ := commonUnder(tpar, nil)
-                       assert(under(single.typ) == u)
+                       assert(single.typ.Underlying() == u)
                }
                return single, true
        }
index 8b24f2fc685b8139cd32ef985ab845991d9b0699..3c4044ed3c9f2ce9b40c6bed0f1e3af9cb16fd16 100644 (file)
@@ -226,12 +226,12 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type,
 // If the provided cause is non-nil, it may be set to an error string
 // explaining why V does not implement (or satisfy, for constraints) T.
 func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool {
-       Vu := under(V)
-       Tu := under(T)
+       Vu := V.Underlying()
+       Tu := T.Underlying()
        if !isValid(Vu) || !isValid(Tu) {
                return true // avoid follow-on errors
        }
-       if p, _ := Vu.(*Pointer); p != nil && !isValid(under(p.base)) {
+       if p, _ := Vu.(*Pointer); p != nil && !isValid(p.base.Underlying()) {
                return true // avoid follow-on errors (see go.dev/issue/49541 for an example)
        }
 
@@ -339,7 +339,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
                        // If V âˆ‰ t.typ but V âˆˆ ~t.typ then remember this type
                        // so we can suggest it as an alternative in the error
                        // message.
-                       if alt == nil && !t.tilde && Identical(t.typ, under(t.typ)) {
+                       if alt == nil && !t.tilde && Identical(t.typ, t.typ.Underlying()) {
                                tt := *t
                                tt.tilde = true
                                if tt.includes(V) {
index 624b510dc83dc3f387417d2d55e0333f2a5a7005..0b9282e1a7cfc2444eb689fc72dde5375e64213f 100644 (file)
@@ -152,7 +152,7 @@ func lookupFieldOrMethodImpl(T Type, addressable bool, pkg *Package, name string
 
        // *typ where typ is an interface (incl. a type parameter) has no methods.
        if isPtr {
-               if _, ok := under(typ).(*Interface); ok {
+               if _, ok := typ.Underlying().(*Interface); ok {
                        return
                }
        }
@@ -202,7 +202,7 @@ func lookupFieldOrMethodImpl(T Type, addressable bool, pkg *Package, name string
                                }
                        }
 
-                       switch t := under(typ).(type) {
+                       switch t := typ.Underlying().(type) {
                        case *Struct:
                                // look for a matching field and collect embedded types
                                for i, f := range t.fields {
@@ -373,7 +373,7 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b
 // The comparator is used to compare signatures.
 // If a method is missing and cause is not nil, *cause describes the error.
 func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y Type) bool, cause *string) (method *Func, wrongType bool) {
-       methods := under(T).(*Interface).typeSet().methods // T must be an interface
+       methods := T.Underlying().(*Interface).typeSet().methods // T must be an interface
        if len(methods) == 0 {
                return nil, false
        }
@@ -393,7 +393,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
        var m *Func // method on T we're trying to implement
        var f *Func // method on V, if found (state is one of ok, wrongName, wrongSig)
 
-       if u, _ := under(V).(*Interface); u != nil {
+       if u, _ := V.Underlying().(*Interface); u != nil {
                tset := u.typeSet()
                for _, m = range methods {
                        _, f = tset.LookupMethod(m.pkg, m.name, false)
@@ -534,7 +534,7 @@ func (check *Checker) hasAllMethods(V, T Type, static bool, equivalent func(x, y
 // hasInvalidEmbeddedFields reports whether T is a struct (or a pointer to a struct) that contains
 // (directly or indirectly) embedded fields with invalid types.
 func hasInvalidEmbeddedFields(T Type, seen map[*Struct]bool) bool {
-       if S, _ := under(derefStructPtr(T)).(*Struct); S != nil && !seen[S] {
+       if S, _ := derefStructPtr(T).Underlying().(*Struct); S != nil && !seen[S] {
                if seen == nil {
                        seen = make(map[*Struct]bool)
                }
@@ -549,14 +549,14 @@ func hasInvalidEmbeddedFields(T Type, seen map[*Struct]bool) bool {
 }
 
 func isInterfacePtr(T Type) bool {
-       p, _ := under(T).(*Pointer)
+       p, _ := T.Underlying().(*Pointer)
        return p != nil && IsInterface(p.base)
 }
 
 // check may be nil.
 func (check *Checker) interfacePtrError(T Type) string {
        assert(isInterfacePtr(T))
-       if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
+       if p, _ := T.Underlying().(*Pointer); isTypeParam(p.base) {
                return check.sprintf("type %s is pointer to type parameter, not type parameter", T)
        }
        return check.sprintf("type %s is pointer to interface, not interface", T)
@@ -629,8 +629,8 @@ func deref(typ Type) (Type, bool) {
 // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a
 // (named or unnamed) struct and returns its base. Otherwise it returns typ.
 func derefStructPtr(typ Type) Type {
-       if p, _ := under(typ).(*Pointer); p != nil {
-               if _, ok := under(p.base).(*Struct); ok {
+       if p, _ := typ.Underlying().(*Pointer); p != nil {
+               if _, ok := p.base.Underlying().(*Struct); ok {
                        return p.base
                }
        }
index 6331259e1767f514b18855b42b8631f7dd084a74..463ed30308d0eeb5b3724ebb34f1b4dc53892d64 100644 (file)
@@ -639,7 +639,7 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
                } else {
                        // TODO(gri) should this be fromRHS for *Named?
                        // (See discussion in #66559.)
-                       typ = under(typ)
+                       typ = typ.Underlying()
                }
        }
 
index 81f46af535152b2dc9460591f1bec25a9ec57541..cd9e9f3575f71a655aa38b98346f27e1f950ec04 100644 (file)
@@ -194,7 +194,7 @@ func operandString(x *operand, qf Qualifier) string {
                                        what := compositeKind(x.typ)
                                        if what == "" {
                                                // x.typ must be basic type
-                                               what = under(x.typ).(*Basic).name
+                                               what = x.typ.Underlying().(*Basic).name
                                        }
                                        desc += what + " "
                                }
@@ -229,7 +229,7 @@ func operandString(x *operand, qf Qualifier) string {
 // ("array", "slice", etc.) or the empty string if typ is not
 // composite but a basic type.
 func compositeKind(typ Type) string {
-       switch under(typ).(type) {
+       switch typ.Underlying().(type) {
        case *Basic:
                return ""
        case *Array:
@@ -319,8 +319,8 @@ func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Cod
                return true, 0
        }
 
-       Vu := under(V)
-       Tu := under(T)
+       Vu := V.Underlying()
+       Tu := T.Underlying()
        Vp, _ := V.(*TypeParam)
        Tp, _ := T.(*TypeParam)
 
index c157672ba58a4d37544312994a5931be1fc155b7..60147c5e21138c9c80d9968dd498e0ff979a6999 100644 (file)
@@ -28,11 +28,11 @@ func isString(t Type) bool         { return isBasic(t, IsString) }
 func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) }
 func isConstType(t Type) bool      { return isBasic(t, IsConstType) }
 
-// isBasic reports whether under(t) is a basic type with the specified info.
+// isBasic reports whether t.Underlying() is a basic type with the specified info.
 // If t is a type parameter the result is false; i.e.,
 // isBasic does not look inside a type parameter.
 func isBasic(t Type, info BasicInfo) bool {
-       u, _ := under(t).(*Basic)
+       u, _ := t.Underlying().(*Basic)
        return u != nil && u.info&info != 0
 }
 
@@ -48,7 +48,7 @@ func allString(t Type) bool          { return allBasic(t, IsString) }
 func allOrdered(t Type) bool         { return allBasic(t, IsOrdered) }
 func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) }
 
-// allBasic reports whether under(t) is a basic type with the specified info.
+// allBasic reports whether t.Underlying() is a basic type with the specified info.
 // If t is a type parameter, the result is true if isBasic(t, info) is true
 // for all specific types of the type parameter's type set.
 func allBasic(t Type, info BasicInfo) bool {
@@ -107,7 +107,7 @@ func isUntypedNumeric(t Type) bool {
 
 // IsInterface reports whether t is an interface type.
 func IsInterface(t Type) bool {
-       _, ok := under(t).(*Interface)
+       _, ok := t.Underlying().(*Interface)
        return ok
 }
 
@@ -163,7 +163,7 @@ func comparableType(T Type, dynamic bool, seen map[Type]bool) *typeError {
        }
        seen[T] = true
 
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Basic:
                // assume invalid types to be comparable to avoid follow-up errors
                if t.kind == UntypedNil {
@@ -206,7 +206,7 @@ func comparableType(T Type, dynamic bool, seen map[Type]bool) *typeError {
 
 // hasNil reports whether type t includes the nil value.
 func hasNil(t Type) bool {
-       switch u := under(t).(type) {
+       switch u := t.Underlying().(type) {
        case *Basic:
                return u.kind == UnsafePointer
        case *Slice, *Pointer, *Signature, *Map, *Chan:
index b654601eafc73ef95410590c2ded7c9d3e01f266..899f5c09911a5e0b3f549ac1c62cc484584e2a03 100644 (file)
@@ -35,7 +35,7 @@ func (check *Checker) rangeStmt(inner stmtContext, rangeStmt *syntax.ForStmt, no
        check.expr(nil, &x, rangeVar)
 
        if isTypes2 && x.mode != invalid && sValue == nil && !check.hasCallOrRecv {
-               if t, ok := arrayPtrDeref(under(x.typ)).(*Array); ok {
+               if t, ok := arrayPtrDeref(x.typ.Underlying()).(*Array); ok {
                        for {
                                // Put constant info on the thing inside parentheses.
                                // That's where (*../noder/writer).expr expects it.
index 7b1c00b40ab9a906de6d10db0489f3ac2a01e61d..534ecfba35ced7439d71d85eb68a5410d83a0eb8 100644 (file)
@@ -54,7 +54,7 @@ func (s *StdSizes) Alignof(T Type) (result int64) {
 
        // For arrays and structs, alignment is defined in terms
        // of alignment of the elements and fields, respectively.
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Array:
                // spec: "For a variable x of array type: unsafe.Alignof(x)
                // is the same as unsafe.Alignof(x[0]), but at least 1."
@@ -162,7 +162,7 @@ var basicSizes = [...]byte{
 }
 
 func (s *StdSizes) Sizeof(T Type) int64 {
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Basic:
                assert(isTyped(T))
                k := t.kind
@@ -307,7 +307,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 {
 func (conf *Config) offsetof(T Type, index []int) int64 {
        var offs int64
        for _, i := range index {
-               s := under(T).(*Struct)
+               s := T.Underlying().(*Struct)
                d := conf.offsetsof(s)[i]
                if d < 0 {
                        return -1
index f5cdc472f77de29b96520f764efb4bef08b4988c..99b75332e8ffec978c25b947e409075aee51eb12 100644 (file)
@@ -141,12 +141,12 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
                        // Because we have a name, typ must be of the form T or *T, where T is the name
                        // of a (named or alias) type, and t (= deref(typ)) must be the type of T.
                        // We must delay this check to the end because we don't want to instantiate
-                       // (via under(t)) a possibly incomplete type.
+                       // (via t.Underlying()) a possibly incomplete type.
                        embeddedTyp := typ // for closure below
                        embeddedPos := pos
                        check.later(func() {
                                t, isPtr := deref(embeddedTyp)
-                               switch u := under(t).(type) {
+                               switch u := t.Underlying().(type) {
                                case *Basic:
                                        if !isValid(t) {
                                                // error was reported before
index c60b5eb41722e4c9f72b8ee08924a16168361c84..2ffa00c32c7ec42849d9548eea678348961b85c6 100644 (file)
@@ -113,7 +113,7 @@ func (t *TypeParam) iface() *Interface {
 
        // determine constraint interface
        var ityp *Interface
-       switch u := under(bound).(type) {
+       switch u := bound.Underlying().(type) {
        case *Basic:
                if !isValid(u) {
                        // error is reported elsewhere
index ce487e74f7232aeea1eaf76e53c27c6684ae0839..fafe6f368ba432577d72e94cb323b02a958d987e 100644 (file)
@@ -114,13 +114,13 @@ func (s *_TypeSet) all(f func(t, u Type) bool) bool {
 
        for _, t := range s.terms {
                assert(t.typ != nil)
-               // Unalias(x) == under(x) for ~x terms
+               // Unalias(x) == x.Underlying() for ~x terms
                u := Unalias(t.typ)
                if !t.tilde {
-                       u = under(u)
+                       u = u.Underlying()
                }
                if debug {
-                       assert(Identical(u, under(u)))
+                       assert(Identical(u, u.Underlying()))
                }
                if !f(t.typ, u) {
                        return false
@@ -264,7 +264,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
                }
                var comparable bool
                var terms termlist
-               switch u := under(typ).(type) {
+               switch u := typ.Underlying().(type) {
                case *Interface:
                        // For now we don't permit type parameters as constraints.
                        assert(!isTypeParam(typ))
@@ -380,7 +380,7 @@ func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos syn
        var allTerms termlist
        for _, t := range utyp.terms {
                var terms termlist
-               u := under(t.typ)
+               u := t.typ.Underlying()
                if ui, _ := u.(*Interface); ui != nil {
                        // For now we don't permit type parameters as constraints.
                        assert(!isTypeParam(t.typ))
index 40ca28e525feb5c9c62f8adf411d933837b83acc..bcff2489306828d47822684dba702e1d336da0f6 100644 (file)
@@ -64,7 +64,7 @@ func TestTypeSetString(t *testing.T) {
                if obj == nil {
                        t.Fatalf("%s: T not found (invalid test case)", body)
                }
-               T, ok := under(obj.Type()).(*Interface)
+               T, ok := obj.Type().Underlying().(*Interface)
                if !ok {
                        t.Fatalf("%s: %v is not an interface (invalid test case)", body, obj)
                }
index 47f53bc12d77b5589377cfc7543147d8f6e0da4e..b1f0d0929bae33e78d9eeab9781575171c0da69c 100644 (file)
@@ -455,7 +455,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
                                } else {
                                        // special case:
                                        // append(s, "foo"...) leads to signature func([]byte, string...)
-                                       if t, _ := under(typ).(*Basic); t == nil || t.kind != String {
+                                       if t, _ := typ.Underlying().(*Basic); t == nil || t.kind != String {
                                                w.error("expected string type")
                                                continue
                                        }
index 97791324e1e75c668a1f5ce5cc0516e337ff6e96..cb11811d458c5ada99ed473840c30fd30bfdb4ca 100644 (file)
@@ -115,7 +115,7 @@ func (x *term) includes(t Type) bool {
 
        u := t
        if x.tilde {
-               u = under(u)
+               u = u.Underlying()
        }
        return Identical(x.typ, u)
 }
@@ -155,11 +155,11 @@ func (x *term) disjoint(y *term) bool {
        }
        ux := x.typ
        if y.tilde {
-               ux = under(ux)
+               ux = ux.Underlying()
        }
        uy := y.typ
        if x.tilde {
-               uy = under(uy)
+               uy = uy.Underlying()
        }
        return !Identical(ux, uy)
 }
index b1533de5048ae169a67fe705456b687eecb32430..8601ce627768e4fa0dfbcc9ede8c13c6f9079851 100644 (file)
@@ -169,11 +169,11 @@ func (check *Checker) validVarType(e syntax.Expr, typ Type) {
                return
        }
 
-       // We don't want to call under() or complete interfaces while we are in
+       // We don't want to call typ.Underlying() or complete interfaces while we are in
        // the middle of type-checking parameter declarations that might belong
        // to interface methods. Delay this check to the end of type-checking.
        check.later(func() {
-               if t, _ := under(typ).(*Interface); t != nil {
+               if t, _ := typ.Underlying().(*Interface); t != nil {
                        pos := syntax.StartPos(e)
                        tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position?
                        if !tset.IsMethodSet() {
@@ -239,7 +239,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *TypeName) (T Type) {
                        check.indent--
                        var under Type
                        if T != nil {
-                               // Calling under() here may lead to endless instantiations.
+                               // Calling T.Underlying() here may lead to endless instantiations.
                                // Test case: type T[P any] *T[P]
                                under = safeUnderlying(T)
                        }
index 8e9871eacd0d90a3e32939cd31b234f4d425b02b..98c62733c7cd990a92a49e51b23c73ed2df04c42 100644 (file)
@@ -6,17 +6,8 @@ package types2
 
 import "iter"
 
-// under returns the true expanded underlying type.
-// If it doesn't exist, the result is Typ[Invalid].
-// under must only be called when a type is known
-// to be fully set up.
-func under(t Type) Type {
-       // TODO(markfreeman): Remove this function, it just delegates.
-       return t.Underlying()
-}
-
 // If typ is a type parameter, underIs returns the result of typ.underIs(f).
-// Otherwise, underIs returns the result of f(under(typ)).
+// Otherwise, underIs returns the result of f(typ.Underlying()).
 func underIs(typ Type, f func(Type) bool) bool {
        return all(typ, func(_, u Type) bool {
                return f(u)
@@ -29,7 +20,7 @@ func all(t Type, f func(t, u Type) bool) bool {
        if p, _ := Unalias(t).(*TypeParam); p != nil {
                return p.typeset(f)
        }
-       return f(t, under(t))
+       return f(t, t.Underlying())
 }
 
 // typeset is an iterator over the (type/underlying type) pairs of the
index 8e112248c635abcbda7762ac3b8849bcc799a667..eecef455ac577c2f76580a6e948a8cd8ef0953e9 100644 (file)
@@ -270,7 +270,7 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
 // it is a non-type parameter interface. Otherwise it returns nil.
 func asInterface(x Type) (i *Interface) {
        if _, ok := Unalias(x).(*TypeParam); !ok {
-               i, _ = under(x).(*Interface)
+               i, _ = x.Underlying().(*Interface)
        }
        return i
 }
@@ -430,7 +430,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
                                                u.set(px, y)
                                        default:
                                                // Neither x nor y are defined types.
-                                               if yc, _ := under(y).(*Chan); yc != nil && yc.dir != SendRecv {
+                                               if yc, _ := y.Underlying().(*Chan); yc != nil && yc.dir != SendRecv {
                                                        // y is a directed channel type: select y.
                                                        u.set(px, y)
                                                }
index 1bf4353f264e34c7a6dc4c95e1f7bb4b48f3790e..ab0bd43cd350ac23c0fea1232ad7257ecbe93c30 100644 (file)
@@ -93,7 +93,7 @@ func parseUnion(check *Checker, uexpr syntax.Expr) Type {
                                continue
                        }
 
-                       u := under(t.typ)
+                       u := t.typ.Underlying()
                        f, _ := u.(*Interface)
                        if t.tilde {
                                if f != nil {
index 3b40a9f84830e66ac4b14427857a393b80ff6170..1524451af766ffb62240b73a228374cc73f73d92 100644 (file)
@@ -94,7 +94,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
        // x.typ is typed
 
        // A generic (non-instantiated) function value cannot be assigned to a variable.
-       if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
+       if sig, _ := x.typ.Underlying().(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
                check.errorf(x, WrongTypeArgCount, "cannot use generic function %s without instantiation in %s", x, context)
                x.mode = invalid
                return
@@ -264,7 +264,7 @@ func (check *Checker) assignVar(lhs, rhs ast.Expr, x *operand, context string) {
                var target *target
                // avoid calling ExprString if not needed
                if T != nil {
-                       if _, ok := under(T).(*Signature); ok {
+                       if _, ok := T.Underlying().(*Signature); ok {
                                target = newTarget(T, ExprString(lhs))
                        }
                }
index 9b03a40cbc34409cdca12efbbd3165951ceb8701..f59c9ddd1203603fcefaa11dc7bab5727e4966a5 100644 (file)
@@ -147,7 +147,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // len(x)
                mode := invalid
                var val constant.Value
-               switch t := arrayPtrDeref(under(x.typ)).(type) {
+               switch t := arrayPtrDeref(x.typ.Underlying()).(type) {
                case *Basic:
                        if isString(t) && id == _Len {
                                if x.mode == constant_ {
@@ -206,7 +206,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
 
                if mode == invalid {
                        // avoid error if underlying type is invalid
-                       if isValid(under(x.typ)) {
+                       if isValid(x.typ.Underlying()) {
                                code := InvalidCap
                                if id == _Len {
                                        code = InvalidLen
@@ -325,7 +325,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // (applyTypeFunc never calls f with a type parameter)
                f := func(typ Type) Type {
                        assert(!isTypeParam(typ))
-                       if t, _ := under(typ).(*Basic); t != nil {
+                       if t, _ := typ.Underlying().(*Basic); t != nil {
                                switch t.kind {
                                case Float32:
                                        return Typ[Complex64]
@@ -475,7 +475,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // (applyTypeFunc never calls f with a type parameter)
                f := func(typ Type) Type {
                        assert(!isTypeParam(typ))
-                       if t, _ := under(typ).(*Basic); t != nil {
+                       if t, _ := typ.Underlying().(*Basic); t != nil {
                                switch t.kind {
                                case Complex64:
                                        return Typ[Float32]
@@ -1023,7 +1023,7 @@ func hasVarSize(t Type, seen map[*Named]bool) (varSized bool) {
                }()
        }
 
-       switch u := under(t).(type) {
+       switch u := t.Underlying().(type) {
        case *Array:
                return hasVarSize(u.elem, seen)
        case *Struct:
@@ -1115,7 +1115,7 @@ func makeSig(res Type, args ...Type) *Signature {
 // otherwise it returns typ.
 func arrayPtrDeref(typ Type) Type {
        if p, ok := Unalias(typ).(*Pointer); ok {
-               if a, _ := under(p.base).(*Array); a != nil {
+               if a, _ := p.base.Underlying().(*Array); a != nil {
                        return a
                }
        }
index 33fe8bb9bfa84f8c3f5eb942463585581182825d..44549b8727cf0bfb80a982808a094b12cb7b2baa 100644 (file)
@@ -211,7 +211,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind {
                                        check.errorf(call.Args[0], BadDotDotDotSyntax, "invalid use of ... in conversion to %s", T)
                                        break
                                }
-                               if t, _ := under(T).(*Interface); t != nil && !isTypeParam(T) {
+                               if t, _ := T.Underlying().(*Interface); t != nil && !isTypeParam(T) {
                                        if !t.IsMethodSet() {
                                                check.errorf(call, MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)
                                                break
@@ -815,7 +815,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *TypeName, w
        obj, index, indirect = lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel, false)
        if obj == nil {
                // Don't report another error if the underlying type was invalid (go.dev/issue/49541).
-               if !isValid(under(x.typ)) {
+               if !isValid(x.typ.Underlying()) {
                        goto Error
                }
 
index c1ed14abe2c12d8cb12e97e55fb488ce9458aed3..dc9efa0130eae3f158ec1383973bf2cd9b2b31e8 100644 (file)
@@ -35,7 +35,7 @@ func (check *Checker) overflow(x *operand, opPos token.Pos) {
        // x.typ cannot be a type parameter (type
        // parameters cannot be constant types).
        if isTyped(x.typ) {
-               check.representable(x, under(x.typ).(*Basic))
+               check.representable(x, x.typ.Underlying().(*Basic))
                return
        }
 
index 6a9f263c57c3771a857c4695f67e5b09500d9802..daef80adf8058b8b3b2fca4721898862b5685685 100644 (file)
@@ -21,7 +21,7 @@ func (check *Checker) conversion(x *operand, T Type) {
        constArg := x.mode == constant_
 
        constConvertibleTo := func(T Type, val *constant.Value) bool {
-               switch t, _ := under(T).(*Basic); {
+               switch t, _ := T.Underlying().(*Basic); {
                case t == nil:
                        // nothing to do
                case representableConst(x.val, check, t, val):
@@ -145,8 +145,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
        origT := T
        V := Unalias(x.typ)
        T = Unalias(T)
-       Vu := under(V)
-       Tu := under(T)
+       Vu := V.Underlying()
+       Tu := T.Underlying()
        Vp, _ := V.(*TypeParam)
        Tp, _ := T.(*TypeParam)
 
@@ -161,7 +161,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
        // and their pointer base types are not type parameters"
        if V, ok := V.(*Pointer); ok {
                if T, ok := T.(*Pointer); ok {
-                       if IdenticalIgnoreTags(under(V.base), under(T.base)) && !isTypeParam(V.base) && !isTypeParam(T.base) {
+                       if IdenticalIgnoreTags(V.base.Underlying(), T.base.Underlying()) && !isTypeParam(V.base) && !isTypeParam(T.base) {
                                return true
                        }
                }
@@ -214,7 +214,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
                                return false
                        }
                case *Pointer:
-                       if a, _ := under(a.Elem()).(*Array); a != nil {
+                       if a, _ := a.Elem().Underlying().(*Array); a != nil {
                                if Identical(s.Elem(), a.Elem()) {
                                        if check == nil || check.allowVersion(go1_17) {
                                                return true
@@ -295,23 +295,23 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
 }
 
 func isUintptr(typ Type) bool {
-       t, _ := under(typ).(*Basic)
+       t, _ := typ.Underlying().(*Basic)
        return t != nil && t.kind == Uintptr
 }
 
 func isUnsafePointer(typ Type) bool {
-       t, _ := under(typ).(*Basic)
+       t, _ := typ.Underlying().(*Basic)
        return t != nil && t.kind == UnsafePointer
 }
 
 func isPointer(typ Type) bool {
-       _, ok := under(typ).(*Pointer)
+       _, ok := typ.Underlying().(*Pointer)
        return ok
 }
 
 func isBytesOrRunes(typ Type) bool {
-       if s, _ := under(typ).(*Slice); s != nil {
-               t, _ := under(s.elem).(*Basic)
+       if s, _ := typ.Underlying().(*Slice); s != nil {
+               t, _ := s.elem.Underlying().(*Basic)
                return t != nil && (t.kind == Byte || t.kind == Rune)
        }
        return false
index 6e61dd9a131429138c597e37d34c4be38529f6a3..15726dc4e2427d06ce7dd48859249a57455d458d 100644 (file)
@@ -466,7 +466,7 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr, inherited bool)
                if !isConstType(t) {
                        // don't report an error if the type is an invalid C (defined) type
                        // (go.dev/issue/22090)
-                       if isValid(under(t)) {
+                       if isValid(t.Underlying()) {
                                check.errorf(typ, InvalidConstType, "invalid constant type %s", t)
                        }
                        obj.typ = Typ[Invalid]
index 97d8c42997863c377ab44c2dabe9076e45b942a6..65995d9bffe690f445b6c718c1b437d8b380c2d0 100644 (file)
@@ -336,7 +336,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) {
        // If the new type is not final and still untyped, just
        // update the recorded type.
        if !final && isUntyped(typ) {
-               old.typ = under(typ).(*Basic)
+               old.typ = typ.Underlying().(*Basic)
                check.untyped[x] = old
                return
        }
@@ -398,7 +398,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
                return nil, nil, InvalidUntypedConversion
        }
 
-       switch u := under(target).(type) {
+       switch u := target.Underlying().(type) {
        case *Basic:
                if x.mode == constant_ {
                        v, code := check.representation(x, u)
@@ -605,7 +605,7 @@ Error:
 // incomparableCause returns a more specific cause why typ is not comparable.
 // If there is no more specific cause, the result is "".
 func (check *Checker) incomparableCause(typ Type) string {
-       switch under(typ).(type) {
+       switch typ.Underlying().(type) {
        case *Slice, *Signature, *Map:
                return compositeKind(typ) + " can only be compared to nil"
        }
@@ -955,7 +955,7 @@ type target struct {
 // The result is nil if typ is not a signature.
 func newTarget(typ Type, desc string) *target {
        if typ != nil {
-               if sig, _ := under(typ).(*Signature); sig != nil {
+               if sig, _ := typ.Underlying().(*Signature); sig != nil {
                        return &target{sig, desc}
                }
        }
@@ -1101,7 +1101,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e ast.Expr, hint Type)
                        check.errorf(x, InvalidAssert, invalidOp+"cannot use type assertion on type parameter value %s", x)
                        goto Error
                }
-               if _, ok := under(x.typ).(*Interface); !ok {
+               if _, ok := x.typ.Underlying().(*Interface); !ok {
                        check.errorf(x, InvalidAssert, invalidOp+"%s is not an interface", x)
                        goto Error
                }
index 227c53e1d280a7dc34c50ebdac33e9927d52c078..adc350a6c2d001f95347851958971d5d17bfc5e7 100644 (file)
@@ -19,7 +19,7 @@ func (s *gcSizes) Alignof(T Type) (result int64) {
 
        // For arrays and structs, alignment is defined in terms
        // of alignment of the elements and fields, respectively.
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Array:
                // spec: "For a variable x of array type: unsafe.Alignof(x)
                // is the same as unsafe.Alignof(x[0]), but at least 1."
@@ -99,7 +99,7 @@ func (s *gcSizes) Offsetsof(fields []*Var) []int64 {
 }
 
 func (s *gcSizes) Sizeof(T Type) int64 {
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Basic:
                assert(isTyped(T))
                k := t.kind
index 1d4f36dcf3c57798fb585384c41fa6b910f17eef..42e472001318cbc5097bad170c6fc2c382932407 100644 (file)
@@ -36,7 +36,7 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) {
                return false
 
        case value:
-               if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
+               if sig, _ := x.typ.Underlying().(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
                        // function instantiation
                        return true
                }
@@ -51,7 +51,7 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) {
        // ordinary index expression
        valid := false
        length := int64(-1) // valid if >= 0
-       switch typ := under(x.typ).(type) {
+       switch typ := x.typ.Underlying().(type) {
        case *Basic:
                if isString(typ) {
                        valid = true
@@ -74,7 +74,7 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) {
                x.typ = typ.elem
 
        case *Pointer:
-               if typ, _ := under(typ.base).(*Array); typ != nil {
+               if typ, _ := typ.base.Underlying().(*Array); typ != nil {
                        valid = true
                        length = typ.len
                        x.mode = variable
@@ -125,7 +125,7 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) {
                                        mode = value
                                }
                        case *Pointer:
-                               if t, _ := under(t.base).(*Array); t != nil {
+                               if t, _ := t.base.Underlying().(*Array); t != nil {
                                        l = t.len
                                        e = t.elem
                                }
@@ -252,7 +252,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) {
                // but don't go from untyped string to string.
                cu = Typ[String]
                if !isTypeParam(x.typ) {
-                       cu = under(x.typ) // untyped string remains untyped
+                       cu = x.typ.Underlying() // untyped string remains untyped
                }
        }
 
@@ -297,7 +297,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) {
                x.typ = &Slice{elem: u.elem}
 
        case *Pointer:
-               if u, _ := under(u.base).(*Array); u != nil {
+               if u, _ := u.base.Underlying().(*Array); u != nil {
                        valid = true
                        length = u.len
                        x.typ = &Slice{elem: u.elem}
index e955880674c1360d8b2addc895e04935016c6f67..a8da7ac674abf9247c88af18b64cdc5d8013236c 100644 (file)
@@ -671,7 +671,7 @@ func coreTerm(tpar *TypeParam) (*term, bool) {
        if n == 1 {
                if debug {
                        u, _ := commonUnder(tpar, nil)
-                       assert(under(single.typ) == u)
+                       assert(single.typ.Underlying() == u)
                }
                return single, true
        }
index 0bccd3dff6b02c94bbcb1d6262dee2e1b38d5e11..6488494cd832274c8e36f419d45bd31c89518d18 100644 (file)
@@ -229,12 +229,12 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeParam, targs []Type,
 // If the provided cause is non-nil, it may be set to an error string
 // explaining why V does not implement (or satisfy, for constraints) T.
 func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool {
-       Vu := under(V)
-       Tu := under(T)
+       Vu := V.Underlying()
+       Tu := T.Underlying()
        if !isValid(Vu) || !isValid(Tu) {
                return true // avoid follow-on errors
        }
-       if p, _ := Vu.(*Pointer); p != nil && !isValid(under(p.base)) {
+       if p, _ := Vu.(*Pointer); p != nil && !isValid(p.base.Underlying()) {
                return true // avoid follow-on errors (see go.dev/issue/49541 for an example)
        }
 
@@ -342,7 +342,7 @@ func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool
                        // If V âˆ‰ t.typ but V âˆˆ ~t.typ then remember this type
                        // so we can suggest it as an alternative in the error
                        // message.
-                       if alt == nil && !t.tilde && Identical(t.typ, under(t.typ)) {
+                       if alt == nil && !t.tilde && Identical(t.typ, t.typ.Underlying()) {
                                tt := *t
                                tt.tilde = true
                                if tt.includes(V) {
index 16d63ae0f118ce6808a32faa8ea7c69c7305adac..c479303a350b8ce0b81e9b92565193be163baa74 100644 (file)
@@ -155,7 +155,7 @@ func lookupFieldOrMethodImpl(T Type, addressable bool, pkg *Package, name string
 
        // *typ where typ is an interface (incl. a type parameter) has no methods.
        if isPtr {
-               if _, ok := under(typ).(*Interface); ok {
+               if _, ok := typ.Underlying().(*Interface); ok {
                        return
                }
        }
@@ -205,7 +205,7 @@ func lookupFieldOrMethodImpl(T Type, addressable bool, pkg *Package, name string
                                }
                        }
 
-                       switch t := under(typ).(type) {
+                       switch t := typ.Underlying().(type) {
                        case *Struct:
                                // look for a matching field and collect embedded types
                                for i, f := range t.fields {
@@ -376,7 +376,7 @@ func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType b
 // The comparator is used to compare signatures.
 // If a method is missing and cause is not nil, *cause describes the error.
 func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y Type) bool, cause *string) (method *Func, wrongType bool) {
-       methods := under(T).(*Interface).typeSet().methods // T must be an interface
+       methods := T.Underlying().(*Interface).typeSet().methods // T must be an interface
        if len(methods) == 0 {
                return nil, false
        }
@@ -396,7 +396,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
        var m *Func // method on T we're trying to implement
        var f *Func // method on V, if found (state is one of ok, wrongName, wrongSig)
 
-       if u, _ := under(V).(*Interface); u != nil {
+       if u, _ := V.Underlying().(*Interface); u != nil {
                tset := u.typeSet()
                for _, m = range methods {
                        _, f = tset.LookupMethod(m.pkg, m.name, false)
@@ -537,7 +537,7 @@ func (check *Checker) hasAllMethods(V, T Type, static bool, equivalent func(x, y
 // hasInvalidEmbeddedFields reports whether T is a struct (or a pointer to a struct) that contains
 // (directly or indirectly) embedded fields with invalid types.
 func hasInvalidEmbeddedFields(T Type, seen map[*Struct]bool) bool {
-       if S, _ := under(derefStructPtr(T)).(*Struct); S != nil && !seen[S] {
+       if S, _ := derefStructPtr(T).Underlying().(*Struct); S != nil && !seen[S] {
                if seen == nil {
                        seen = make(map[*Struct]bool)
                }
@@ -552,14 +552,14 @@ func hasInvalidEmbeddedFields(T Type, seen map[*Struct]bool) bool {
 }
 
 func isInterfacePtr(T Type) bool {
-       p, _ := under(T).(*Pointer)
+       p, _ := T.Underlying().(*Pointer)
        return p != nil && IsInterface(p.base)
 }
 
 // check may be nil.
 func (check *Checker) interfacePtrError(T Type) string {
        assert(isInterfacePtr(T))
-       if p, _ := under(T).(*Pointer); isTypeParam(p.base) {
+       if p, _ := T.Underlying().(*Pointer); isTypeParam(p.base) {
                return check.sprintf("type %s is pointer to type parameter, not type parameter", T)
        }
        return check.sprintf("type %s is pointer to interface, not interface", T)
@@ -632,8 +632,8 @@ func deref(typ Type) (Type, bool) {
 // derefStructPtr dereferences typ if it is a (named or unnamed) pointer to a
 // (named or unnamed) struct and returns its base. Otherwise it returns typ.
 func derefStructPtr(typ Type) Type {
-       if p, _ := under(typ).(*Pointer); p != nil {
-               if _, ok := under(p.base).(*Struct); ok {
+       if p, _ := typ.Underlying().(*Pointer); p != nil {
+               if _, ok := p.base.Underlying().(*Struct); ok {
                        return p.base
                }
        }
index ac8f0bdd288e277e8c69816bda5be78d27b16863..2eac62e6028e0f0f0383715b74b6db2d60c78ee3 100644 (file)
@@ -133,7 +133,7 @@ func NewMethodSet(T Type) *MethodSet {
                                }
                        }
 
-                       switch t := under(typ).(type) {
+                       switch t := typ.Underlying().(type) {
                        case *Struct:
                                for i, f := range t.fields {
                                        if fset == nil {
index 305471222c5ccc1dad60023ff58cfa340d06013b..1bba5d52a8b2b6b4eaaafca2a22b06297005ab63 100644 (file)
@@ -642,7 +642,7 @@ func writeObject(buf *bytes.Buffer, obj Object, qf Qualifier) {
                } else {
                        // TODO(gri) should this be fromRHS for *Named?
                        // (See discussion in #66559.)
-                       typ = under(typ)
+                       typ = typ.Underlying()
                }
        }
 
index d933c173ff60eebc46bf7b045c962c9066d86559..9abeaafae0c4d260b88ea02af7f56b0081d5e760 100644 (file)
@@ -198,7 +198,7 @@ func operandString(x *operand, qf Qualifier) string {
                                        what := compositeKind(x.typ)
                                        if what == "" {
                                                // x.typ must be basic type
-                                               what = under(x.typ).(*Basic).name
+                                               what = x.typ.Underlying().(*Basic).name
                                        }
                                        desc += what + " "
                                }
@@ -233,7 +233,7 @@ func operandString(x *operand, qf Qualifier) string {
 // ("array", "slice", etc.) or the empty string if typ is not
 // composite but a basic type.
 func compositeKind(typ Type) string {
-       switch under(typ).(type) {
+       switch typ.Underlying().(type) {
        case *Basic:
                return ""
        case *Array:
@@ -323,8 +323,8 @@ func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Cod
                return true, 0
        }
 
-       Vu := under(V)
-       Tu := under(T)
+       Vu := V.Underlying()
+       Tu := T.Underlying()
        Vp, _ := V.(*TypeParam)
        Tp, _ := T.(*TypeParam)
 
index 45f28726eecba646e0c1c1236fb4c961c4ecea71..ad929db2667eba0c22ffc4db862ac1ce45a6829f 100644 (file)
@@ -31,11 +31,11 @@ func isString(t Type) bool         { return isBasic(t, IsString) }
 func isIntegerOrFloat(t Type) bool { return isBasic(t, IsInteger|IsFloat) }
 func isConstType(t Type) bool      { return isBasic(t, IsConstType) }
 
-// isBasic reports whether under(t) is a basic type with the specified info.
+// isBasic reports whether t.Underlying() is a basic type with the specified info.
 // If t is a type parameter the result is false; i.e.,
 // isBasic does not look inside a type parameter.
 func isBasic(t Type, info BasicInfo) bool {
-       u, _ := under(t).(*Basic)
+       u, _ := t.Underlying().(*Basic)
        return u != nil && u.info&info != 0
 }
 
@@ -51,7 +51,7 @@ func allString(t Type) bool          { return allBasic(t, IsString) }
 func allOrdered(t Type) bool         { return allBasic(t, IsOrdered) }
 func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) }
 
-// allBasic reports whether under(t) is a basic type with the specified info.
+// allBasic reports whether t.Underlying() is a basic type with the specified info.
 // If t is a type parameter, the result is true if isBasic(t, info) is true
 // for all specific types of the type parameter's type set.
 func allBasic(t Type, info BasicInfo) bool {
@@ -110,7 +110,7 @@ func isUntypedNumeric(t Type) bool {
 
 // IsInterface reports whether t is an interface type.
 func IsInterface(t Type) bool {
-       _, ok := under(t).(*Interface)
+       _, ok := t.Underlying().(*Interface)
        return ok
 }
 
@@ -166,7 +166,7 @@ func comparableType(T Type, dynamic bool, seen map[Type]bool) *typeError {
        }
        seen[T] = true
 
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Basic:
                // assume invalid types to be comparable to avoid follow-up errors
                if t.kind == UntypedNil {
@@ -209,7 +209,7 @@ func comparableType(T Type, dynamic bool, seen map[Type]bool) *typeError {
 
 // hasNil reports whether type t includes the nil value.
 func hasNil(t Type) bool {
-       switch u := under(t).(type) {
+       switch u := t.Underlying().(type) {
        case *Basic:
                return u.kind == UnsafePointer
        case *Slice, *Pointer, *Signature, *Map, *Chan:
index 303d001c72d05be11b14b812753d04e43fb046bf..d38150dea774804da26f9a0b45a9ea43bbe4c84c 100644 (file)
@@ -38,7 +38,7 @@ func (check *Checker) rangeStmt(inner stmtContext, rangeStmt *ast.RangeStmt, noN
        check.expr(nil, &x, rangeVar)
 
        if isTypes2 && x.mode != invalid && sValue == nil && !check.hasCallOrRecv {
-               if t, ok := arrayPtrDeref(under(x.typ)).(*Array); ok {
+               if t, ok := arrayPtrDeref(x.typ.Underlying()).(*Array); ok {
                        for {
                                // Put constant info on the thing inside parentheses.
                                // That's where (*../noder/writer).expr expects it.
index 51ea224f0b2997ce9d2cbc3bcd6f57e4eda9a2f0..e2ff047bc859c3e80092f37f332935e157acf6a8 100644 (file)
@@ -57,7 +57,7 @@ func (s *StdSizes) Alignof(T Type) (result int64) {
 
        // For arrays and structs, alignment is defined in terms
        // of alignment of the elements and fields, respectively.
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Array:
                // spec: "For a variable x of array type: unsafe.Alignof(x)
                // is the same as unsafe.Alignof(x[0]), but at least 1."
@@ -165,7 +165,7 @@ var basicSizes = [...]byte{
 }
 
 func (s *StdSizes) Sizeof(T Type) int64 {
-       switch t := under(T).(type) {
+       switch t := T.Underlying().(type) {
        case *Basic:
                assert(isTyped(T))
                k := t.kind
@@ -310,7 +310,7 @@ func (conf *Config) offsetsof(T *Struct) []int64 {
 func (conf *Config) offsetof(T Type, index []int) int64 {
        var offs int64
        for _, i := range index {
-               s := under(T).(*Struct)
+               s := T.Underlying().(*Struct)
                d := conf.offsetsof(s)[i]
                if d < 0 {
                        return -1
index a6970832c7c0d41d2cfe2e144df39018ea070ecc..0133eb450db6d754f09b6a71c80aacd368a39396 100644 (file)
@@ -137,7 +137,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
                        // Because we have a name, typ must be of the form T or *T, where T is the name
                        // of a (named or alias) type, and t (= deref(typ)) must be the type of T.
                        // We must delay this check to the end because we don't want to instantiate
-                       // (via under(t)) a possibly incomplete type.
+                       // (via t.Underlying()) a possibly incomplete type.
 
                        // for use in the closure below
                        embeddedTyp := typ
@@ -145,7 +145,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
 
                        check.later(func() {
                                t, isPtr := deref(embeddedTyp)
-                               switch u := under(t).(type) {
+                               switch u := t.Underlying().(type) {
                                case *Basic:
                                        if !isValid(t) {
                                                // error was reported before
index 2ffef8f613319a1243663d2f9463c46c02c064ae..eafcb1c145d1f88f783e750ca10f542e11205161 100644 (file)
@@ -116,7 +116,7 @@ func (t *TypeParam) iface() *Interface {
 
        // determine constraint interface
        var ityp *Interface
-       switch u := under(bound).(type) {
+       switch u := bound.Underlying().(type) {
        case *Basic:
                if !isValid(u) {
                        // error is reported elsewhere
index 46ed5ce1802e0bfd9fe58e470d84359244833663..3a61c307561963af40c803d1b7bcc2beb38170d2 100644 (file)
@@ -117,13 +117,13 @@ func (s *_TypeSet) all(f func(t, u Type) bool) bool {
 
        for _, t := range s.terms {
                assert(t.typ != nil)
-               // Unalias(x) == under(x) for ~x terms
+               // Unalias(x) == x.Underlying() for ~x terms
                u := Unalias(t.typ)
                if !t.tilde {
-                       u = under(u)
+                       u = u.Underlying()
                }
                if debug {
-                       assert(Identical(u, under(u)))
+                       assert(Identical(u, u.Underlying()))
                }
                if !f(t.typ, u) {
                        return false
@@ -267,7 +267,7 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
                }
                var comparable bool
                var terms termlist
-               switch u := under(typ).(type) {
+               switch u := typ.Underlying().(type) {
                case *Interface:
                        // For now we don't permit type parameters as constraints.
                        assert(!isTypeParam(typ))
@@ -383,7 +383,7 @@ func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos tok
        var allTerms termlist
        for _, t := range utyp.terms {
                var terms termlist
-               u := under(t.typ)
+               u := t.typ.Underlying()
                if ui, _ := u.(*Interface); ui != nil {
                        // For now we don't permit type parameters as constraints.
                        assert(!isTypeParam(t.typ))
index 51560924839eae230f2c936414202d2c84960cf6..a4feb7469b0637fb05cf9a70c150a3fe14a4b43e 100644 (file)
@@ -65,7 +65,7 @@ func TestTypeSetString(t *testing.T) {
                if obj == nil {
                        t.Fatalf("%s: T not found (invalid test case)", body)
                }
-               T, ok := under(obj.Type()).(*Interface)
+               T, ok := obj.Type().Underlying().(*Interface)
                if !ok {
                        t.Fatalf("%s: %v is not an interface (invalid test case)", body, obj)
                }
index 804e80407ef52aa4bb4e3ef9a3d888cae3ebe594..bd13459832deca80453df0274b15ba1ad674d950 100644 (file)
@@ -458,7 +458,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
                                } else {
                                        // special case:
                                        // append(s, "foo"...) leads to signature func([]byte, string...)
-                                       if t, _ := under(typ).(*Basic); t == nil || t.kind != String {
+                                       if t, _ := typ.Underlying().(*Basic); t == nil || t.kind != String {
                                                w.error("expected string type")
                                                continue
                                        }
index 1cd4e1651f30cd06e29e5684f28c26a7e0a4a737..b9ba8f38f91c837caa49e3dde480450e923bf641 100644 (file)
@@ -118,7 +118,7 @@ func (x *term) includes(t Type) bool {
 
        u := t
        if x.tilde {
-               u = under(u)
+               u = u.Underlying()
        }
        return Identical(x.typ, u)
 }
@@ -158,11 +158,11 @@ func (x *term) disjoint(y *term) bool {
        }
        ux := x.typ
        if y.tilde {
-               ux = under(ux)
+               ux = ux.Underlying()
        }
        uy := y.typ
        if x.tilde {
-               uy = under(uy)
+               uy = uy.Underlying()
        }
        return !Identical(ux, uy)
 }
index 2e45b7570f367784ddd808fae7153fb4dd013530..88ec4b77fca7e9c3fb8ddfbf42af5972dd30295d 100644 (file)
@@ -168,11 +168,11 @@ func (check *Checker) validVarType(e ast.Expr, typ Type) {
                return
        }
 
-       // We don't want to call under() or complete interfaces while we are in
+       // We don't want to call typ.Underlying() or complete interfaces while we are in
        // the middle of type-checking parameter declarations that might belong
        // to interface methods. Delay this check to the end of type-checking.
        check.later(func() {
-               if t, _ := under(typ).(*Interface); t != nil {
+               if t, _ := typ.Underlying().(*Interface); t != nil {
                        tset := computeInterfaceTypeSet(check, e.Pos(), t) // TODO(gri) is this the correct position?
                        if !tset.IsMethodSet() {
                                if tset.comparable {
@@ -237,7 +237,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *TypeName) (T Type) {
                        check.indent--
                        var under Type
                        if T != nil {
-                               // Calling under() here may lead to endless instantiations.
+                               // Calling T.Underlying() here may lead to endless instantiations.
                                // Test case: type T[P any] *T[P]
                                under = safeUnderlying(T)
                        }
index d5e476a79f4739db1e52b934792242dca421af9f..6056b2e4829d3b7ec3c941d62809b56a4df3eb69 100644 (file)
@@ -9,17 +9,8 @@ package types
 
 import "iter"
 
-// under returns the true expanded underlying type.
-// If it doesn't exist, the result is Typ[Invalid].
-// under must only be called when a type is known
-// to be fully set up.
-func under(t Type) Type {
-       // TODO(markfreeman): Remove this function, it just delegates.
-       return t.Underlying()
-}
-
 // If typ is a type parameter, underIs returns the result of typ.underIs(f).
-// Otherwise, underIs returns the result of f(under(typ)).
+// Otherwise, underIs returns the result of f(typ.Underlying()).
 func underIs(typ Type, f func(Type) bool) bool {
        return all(typ, func(_, u Type) bool {
                return f(u)
@@ -32,7 +23,7 @@ func all(t Type, f func(t, u Type) bool) bool {
        if p, _ := Unalias(t).(*TypeParam); p != nil {
                return p.typeset(f)
        }
-       return f(t, under(t))
+       return f(t, t.Underlying())
 }
 
 // typeset is an iterator over the (type/underlying type) pairs of the
index 2e3ba512df70c9f35571e31718305363d4f463f1..ea96de82f0f2974969bc3944a23c4d9a91fc472d 100644 (file)
@@ -273,7 +273,7 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
 // it is a non-type parameter interface. Otherwise it returns nil.
 func asInterface(x Type) (i *Interface) {
        if _, ok := Unalias(x).(*TypeParam); !ok {
-               i, _ = under(x).(*Interface)
+               i, _ = x.Underlying().(*Interface)
        }
        return i
 }
@@ -433,7 +433,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
                                                u.set(px, y)
                                        default:
                                                // Neither x nor y are defined types.
-                                               if yc, _ := under(y).(*Chan); yc != nil && yc.dir != SendRecv {
+                                               if yc, _ := y.Underlying().(*Chan); yc != nil && yc.dir != SendRecv {
                                                        // y is a directed channel type: select y.
                                                        u.set(px, y)
                                                }
index 30365e30bc2a069a4e37f86cd134b495691fa1e6..3f7efdf1f38a9d984125490bc879c5e95811fe1b 100644 (file)
@@ -94,7 +94,7 @@ func parseUnion(check *Checker, uexpr ast.Expr) Type {
                                continue
                        }
 
-                       u := under(t.typ)
+                       u := t.typ.Underlying()
                        f, _ := u.(*Interface)
                        if t.tilde {
                                if f != nil {