From 0c14000f87fc7f9d720a2937717d22b6c4f90e19 Mon Sep 17 00:00:00 2001 From: Mark Freeman Date: Thu, 16 Oct 2025 11:08:13 -0400 Subject: [PATCH] go/types, types2: remove under(Type) in favor of Type.Underlying() 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 Reviewed-by: Robert Griesemer Auto-Submit: Robert Griesemer LUCI-TryBot-Result: Go LUCI --- .../compile/internal/types2/assignments.go | 4 ++-- src/cmd/compile/internal/types2/builtins.go | 12 +++++------ src/cmd/compile/internal/types2/call.go | 4 ++-- src/cmd/compile/internal/types2/const.go | 2 +- .../compile/internal/types2/conversions.go | 20 +++++++++---------- src/cmd/compile/internal/types2/decl.go | 2 +- src/cmd/compile/internal/types2/expr.go | 10 +++++----- src/cmd/compile/internal/types2/gcsizes.go | 4 ++-- src/cmd/compile/internal/types2/index.go | 12 +++++------ src/cmd/compile/internal/types2/infer.go | 2 +- .../compile/internal/types2/instantiate.go | 8 ++++---- src/cmd/compile/internal/types2/lookup.go | 18 ++++++++--------- src/cmd/compile/internal/types2/object.go | 2 +- src/cmd/compile/internal/types2/operand.go | 8 ++++---- src/cmd/compile/internal/types2/predicates.go | 12 +++++------ src/cmd/compile/internal/types2/range.go | 2 +- src/cmd/compile/internal/types2/sizes.go | 6 +++--- src/cmd/compile/internal/types2/struct.go | 4 ++-- src/cmd/compile/internal/types2/typeparam.go | 2 +- src/cmd/compile/internal/types2/typeset.go | 10 +++++----- .../compile/internal/types2/typeset_test.go | 2 +- src/cmd/compile/internal/types2/typestring.go | 2 +- src/cmd/compile/internal/types2/typeterm.go | 6 +++--- src/cmd/compile/internal/types2/typexpr.go | 6 +++--- src/cmd/compile/internal/types2/under.go | 13 ++---------- src/cmd/compile/internal/types2/unify.go | 4 ++-- src/cmd/compile/internal/types2/union.go | 2 +- src/go/types/assignments.go | 4 ++-- src/go/types/builtins.go | 12 +++++------ src/go/types/call.go | 4 ++-- src/go/types/const.go | 2 +- src/go/types/conversions.go | 20 +++++++++---------- src/go/types/decl.go | 2 +- src/go/types/expr.go | 10 +++++----- src/go/types/gcsizes.go | 4 ++-- src/go/types/index.go | 12 +++++------ src/go/types/infer.go | 2 +- src/go/types/instantiate.go | 8 ++++---- src/go/types/lookup.go | 18 ++++++++--------- src/go/types/methodset.go | 2 +- src/go/types/object.go | 2 +- src/go/types/operand.go | 8 ++++---- src/go/types/predicates.go | 12 +++++------ src/go/types/range.go | 2 +- src/go/types/sizes.go | 6 +++--- src/go/types/struct.go | 4 ++-- src/go/types/typeparam.go | 2 +- src/go/types/typeset.go | 10 +++++----- src/go/types/typeset_test.go | 2 +- src/go/types/typestring.go | 2 +- src/go/types/typeterm.go | 6 +++--- src/go/types/typexpr.go | 6 +++--- src/go/types/under.go | 13 ++---------- src/go/types/unify.go | 4 ++-- src/go/types/union.go | 2 +- 55 files changed, 171 insertions(+), 189 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index 8af5f4037a..87f5c8beea 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -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)) } } diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index df207a2746..84acb4ca48 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -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 } } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index b7a2ebb41e..aca205ad98 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -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 } diff --git a/src/cmd/compile/internal/types2/const.go b/src/cmd/compile/internal/types2/const.go index 5e5bc74ba3..b68d72de4d 100644 --- a/src/cmd/compile/internal/types2/const.go +++ b/src/cmd/compile/internal/types2/const.go @@ -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 } diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 0ad79afe71..d0920d7ef1 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -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 diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 70e79129c9..b830cb6f4f 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -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] diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index e5f9a1c6f7..d62b024757 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -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 } diff --git a/src/cmd/compile/internal/types2/gcsizes.go b/src/cmd/compile/internal/types2/gcsizes.go index 15f3e00642..54e8ea23c1 100644 --- a/src/cmd/compile/internal/types2/gcsizes.go +++ b/src/cmd/compile/internal/types2/gcsizes.go @@ -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 diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 7e16a87332..ca84184d35 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -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} diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 08d4229690..e7c5959737 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -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 } diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index 8b24f2fc68..3c4044ed3c 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -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) { diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 624b510dc8..0b9282e1a7 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -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 } } diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index 6331259e17..463ed30308 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -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() } } diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 81f46af535..cd9e9f3575 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -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) diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index c157672ba5..60147c5e21 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -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: diff --git a/src/cmd/compile/internal/types2/range.go b/src/cmd/compile/internal/types2/range.go index b654601eaf..899f5c0991 100644 --- a/src/cmd/compile/internal/types2/range.go +++ b/src/cmd/compile/internal/types2/range.go @@ -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. diff --git a/src/cmd/compile/internal/types2/sizes.go b/src/cmd/compile/internal/types2/sizes.go index 7b1c00b40a..534ecfba35 100644 --- a/src/cmd/compile/internal/types2/sizes.go +++ b/src/cmd/compile/internal/types2/sizes.go @@ -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 diff --git a/src/cmd/compile/internal/types2/struct.go b/src/cmd/compile/internal/types2/struct.go index f5cdc472f7..99b75332e8 100644 --- a/src/cmd/compile/internal/types2/struct.go +++ b/src/cmd/compile/internal/types2/struct.go @@ -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 diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index c60b5eb417..2ffa00c32c 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -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 diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index ce487e74f7..fafe6f368b 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -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)) diff --git a/src/cmd/compile/internal/types2/typeset_test.go b/src/cmd/compile/internal/types2/typeset_test.go index 40ca28e525..bcff248930 100644 --- a/src/cmd/compile/internal/types2/typeset_test.go +++ b/src/cmd/compile/internal/types2/typeset_test.go @@ -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) } diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go index 47f53bc12d..b1f0d0929b 100644 --- a/src/cmd/compile/internal/types2/typestring.go +++ b/src/cmd/compile/internal/types2/typestring.go @@ -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 } diff --git a/src/cmd/compile/internal/types2/typeterm.go b/src/cmd/compile/internal/types2/typeterm.go index 97791324e1..cb11811d45 100644 --- a/src/cmd/compile/internal/types2/typeterm.go +++ b/src/cmd/compile/internal/types2/typeterm.go @@ -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) } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index b1533de504..8601ce6277 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -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) } diff --git a/src/cmd/compile/internal/types2/under.go b/src/cmd/compile/internal/types2/under.go index 8e9871eacd..98c62733c7 100644 --- a/src/cmd/compile/internal/types2/under.go +++ b/src/cmd/compile/internal/types2/under.go @@ -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 diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 8e112248c6..eecef455ac 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -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) } diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 1bf4353f26..ab0bd43cd3 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -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 { diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 3b40a9f848..1524451af7 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -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)) } } diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 9b03a40cbc..f59c9ddd12 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -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 } } diff --git a/src/go/types/call.go b/src/go/types/call.go index 33fe8bb9bf..44549b8727 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -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 } diff --git a/src/go/types/const.go b/src/go/types/const.go index c1ed14abe2..dc9efa0130 100644 --- a/src/go/types/const.go +++ b/src/go/types/const.go @@ -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 } diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 6a9f263c57..daef80adf8 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -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 diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 6e61dd9a13..15726dc4e2 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -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] diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 97d8c42997..65995d9bff 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -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 } diff --git a/src/go/types/gcsizes.go b/src/go/types/gcsizes.go index 227c53e1d2..adc350a6c2 100644 --- a/src/go/types/gcsizes.go +++ b/src/go/types/gcsizes.go @@ -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 diff --git a/src/go/types/index.go b/src/go/types/index.go index 1d4f36dcf3..42e4720013 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -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} diff --git a/src/go/types/infer.go b/src/go/types/infer.go index e955880674..a8da7ac674 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -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 } diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 0bccd3dff6..6488494cd8 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -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) { diff --git a/src/go/types/lookup.go b/src/go/types/lookup.go index 16d63ae0f1..c479303a35 100644 --- a/src/go/types/lookup.go +++ b/src/go/types/lookup.go @@ -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 } } diff --git a/src/go/types/methodset.go b/src/go/types/methodset.go index ac8f0bdd28..2eac62e602 100644 --- a/src/go/types/methodset.go +++ b/src/go/types/methodset.go @@ -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 { diff --git a/src/go/types/object.go b/src/go/types/object.go index 305471222c..1bba5d52a8 100644 --- a/src/go/types/object.go +++ b/src/go/types/object.go @@ -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() } } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index d933c173ff..9abeaafae0 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -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) diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 45f28726ee..ad929db266 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -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: diff --git a/src/go/types/range.go b/src/go/types/range.go index 303d001c72..d38150dea7 100644 --- a/src/go/types/range.go +++ b/src/go/types/range.go @@ -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. diff --git a/src/go/types/sizes.go b/src/go/types/sizes.go index 51ea224f0b..e2ff047bc8 100644 --- a/src/go/types/sizes.go +++ b/src/go/types/sizes.go @@ -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 diff --git a/src/go/types/struct.go b/src/go/types/struct.go index a6970832c7..0133eb450d 100644 --- a/src/go/types/struct.go +++ b/src/go/types/struct.go @@ -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 diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 2ffef8f613..eafcb1c145 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -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 diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 46ed5ce180..3a61c30756 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -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)) diff --git a/src/go/types/typeset_test.go b/src/go/types/typeset_test.go index 5156092483..a4feb7469b 100644 --- a/src/go/types/typeset_test.go +++ b/src/go/types/typeset_test.go @@ -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) } diff --git a/src/go/types/typestring.go b/src/go/types/typestring.go index 804e80407e..bd13459832 100644 --- a/src/go/types/typestring.go +++ b/src/go/types/typestring.go @@ -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 } diff --git a/src/go/types/typeterm.go b/src/go/types/typeterm.go index 1cd4e1651f..b9ba8f38f9 100644 --- a/src/go/types/typeterm.go +++ b/src/go/types/typeterm.go @@ -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) } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 2e45b7570f..88ec4b77fc 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -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) } diff --git a/src/go/types/under.go b/src/go/types/under.go index d5e476a79f..6056b2e482 100644 --- a/src/go/types/under.go +++ b/src/go/types/under.go @@ -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 diff --git a/src/go/types/unify.go b/src/go/types/unify.go index 2e3ba512df..ea96de82f0 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -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) } diff --git a/src/go/types/union.go b/src/go/types/union.go index 30365e30bc..3f7efdf1f3 100644 --- a/src/go/types/union.go +++ b/src/go/types/union.go @@ -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 { -- 2.52.0