mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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 <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>
This commit is contained in:
parent
1099436f1b
commit
0c14000f87
55 changed files with 171 additions and 189 deletions
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue