Make it explicit in the code where we call under.
The asNamed and asTypeParam converters need to
stay: asNamed does resolution if necessary, and
asTypeParam may or may not call under() depending
on the next CL.
Reviewed uses of asNamed and .(*Named) for correctness.
Removed unnecessary Named.resolve call in lookup.
Change-Id: I2acf176925e00bd1703a00230a779aa65a8f5a51
Reviewed-on: https://go-review.googlesource.com/c/go/+/362254
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
// x.typ is typed
// A generic (non-instantiated) function value cannot be assigned to a variable.
- if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 {
+ if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
check.errorf(x, "cannot use generic function %s without instantiation in %s", x, context)
}
// (applyTypeFunc never calls f with a type parameter)
f := func(typ Type) Type {
assert(asTypeParam(typ) == nil)
- if t := asBasic(typ); t != nil {
+ if t, _ := under(typ).(*Basic); t != nil {
switch t.kind {
case Float32:
return Typ[Complex64]
// (applyTypeFunc never calls f with a type parameter)
f := func(typ Type) Type {
assert(asTypeParam(typ) == nil)
- if t := asBasic(typ); t != nil {
+ if t, _ := under(typ).(*Basic); t != nil {
switch t.kind {
case Complex64:
return Typ[Float32]
return
}
- typ := asPointer(x.typ)
+ typ, _ := under(x.typ).(*Pointer)
if typ == nil {
check.errorf(x, invalidArg+"%s is not a pointer", x)
return
// otherwise it returns typ.
func arrayPtrDeref(typ Type) Type {
if p, ok := typ.(*Pointer); ok {
- if a := asArray(p.base); a != nil {
+ if a, _ := under(p.base).(*Array); a != nil {
return a
}
}
case 1:
check.expr(x, call.ArgList[0])
if x.mode != invalid {
- if t := asInterface(T); t != nil {
+ if t, _ := under(T).(*Interface); t != nil {
if !t.IsMethodSet() {
check.errorf(call, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", T)
break
var buf bytes.Buffer
h := newTypeHasher(&buf, ctxt)
- if named, _ := typ.(*Named); named != nil && len(targs) > 0 {
+ if named := asNamed(typ); named != nil && len(targs) > 0 {
// Don't use WriteType because we need to use the provided targs
// and not any targs that might already be with the *Named type.
h.typePrefix(named)
constArg := x.mode == constant_
constConvertibleTo := func(T Type, val *constant.Value) bool {
- switch t := asBasic(T); {
+ switch t, _ := under(T).(*Basic); {
case t == nil:
// nothing to do
case representableConst(x.val, check, t, val):
// "V a slice, T is a pointer-to-array type,
// and the slice and array types have identical element types."
- if s := asSlice(V); s != nil {
- if p := asPointer(T); p != nil {
- if a := asArray(p.Elem()); a != nil {
+ if s, _ := under(V).(*Slice); s != nil {
+ if p, _ := under(T).(*Pointer); p != nil {
+ if a, _ := under(p.Elem()).(*Array); a != nil {
if Identical(s.Elem(), a.Elem()) {
if check == nil || check.allowVersion(check.pkg, 1, 17) {
return true
// use the toT convenience converters in the predicates below.
func isUintptr(typ Type) bool {
- t := asBasic(typ)
+ t, _ := under(typ).(*Basic)
return t != nil && t.kind == Uintptr
}
func isUnsafePointer(typ Type) bool {
- // TODO(gri): Is this asBasic(typ) instead of typ.(*Basic) correct?
+ // TODO(gri): Is this under(typ).(*Basic) instead of typ.(*Basic) correct?
// (The former calls under(), while the latter doesn't.)
// The spec does not say so, but gc claims it is. See also
// issue 6326.
- t := asBasic(typ)
+ t, _ := under(typ).(*Basic)
return t != nil && t.kind == UnsafePointer
}
func isPointer(typ Type) bool {
- return asPointer(typ) != nil
+ _, ok := under(typ).(*Pointer)
+ return ok
}
func isBytesOrRunes(typ Type) bool {
- if s := asSlice(typ); s != nil {
- t := asBasic(s.elem)
+ if s, _ := under(typ).(*Slice); s != nil {
+ t, _ := under(s.elem).(*Basic)
return t != nil && (t.kind == Byte || t.kind == Rune)
}
return false
// x.typ cannot be a type parameter (type
// parameters cannot be constant types).
if isTyped(x.typ) {
- check.representable(x, asBasic(x.typ))
+ check.representable(x, under(x.typ).(*Basic))
return
}
// If the new type is not final and still untyped, just
// update the recorded type.
if !final && isUntyped(typ) {
- old.typ = asBasic(typ)
+ old.typ = under(typ).(*Basic)
check.untyped[x] = old
return
}
duplicate := false
// if the key is of interface type, the type is also significant when checking for duplicates
xkey := keyVal(x.val)
- if asInterface(utyp.key) != nil {
+ if IsInterface(utyp.key) {
for _, vtyp := range visited[xkey] {
if Identical(vtyp, x.typ) {
duplicate = true
return false
case value:
- if sig := asSignature(x.typ); sig != nil && sig.TypeParams().Len() > 0 {
+ if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
// function instantiation
return true
}
x.typ = typ.elem
case *Pointer:
- if typ := asArray(typ.base); typ != nil {
+ if typ, _ := under(typ.base).(*Array); typ != nil {
valid = true
length = typ.len
x.mode = variable
mode = value
}
case *Pointer:
- if t := asArray(t.base); t != nil {
+ if t, _ := under(t.base).(*Array); t != nil {
l = t.len
e = t.elem
}
x.typ = &Slice{elem: u.elem}
case *Pointer:
- if u := asArray(u.base); u != nil {
+ if u, _ := under(u.base).(*Array); u != nil {
valid = true
length = u.len
x.typ = &Slice{elem: u.elem}
seen[named] = true
// look for a matching attached method
- named.resolve(nil)
if i, m := lookupMethod(named.methods, pkg, name); m != nil {
// potential match
// caution: method may not have a proper signature yet
return
}
- if ityp := asInterface(V); ityp != nil {
+ if ityp, _ := under(V).(*Interface); ityp != nil {
// TODO(gri) the methods are sorted - could do this more efficiently
for _, m := range T.typeSet().methods {
_, f := ityp.typeSet().LookupMethod(m.pkg, m.name)
// no static check is required if T is an interface
// spec: "If T is an interface type, x.(T) asserts that the
// dynamic type of x implements the interface T."
- if asInterface(T) != nil && !forceStrict {
+ if IsInterface(T) && !forceStrict {
return
}
return check.missingMethod(T, V, false)
// 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 := asPointer(typ); p != nil {
- if asStruct(p.base) != nil {
+ if p, _ := under(typ).(*Pointer); p != nil {
+ if _, ok := under(p.base).(*Struct); ok {
return p.base
}
}
// are not fully set up.
func isTyped(t Type) bool {
// isTyped is called with types that are not fully
- // set up. Must not call asBasic()!
+ // set up. Must not call under()!
b, _ := t.(*Basic)
return b == nil || b.info&IsUntyped == 0
}
// IsInterface reports whether t is an interface type.
func IsInterface(t Type) bool {
- return asInterface(t) != nil
+ _, ok := under(t).(*Interface)
+ return ok
}
// isTypeParam reports whether t is a type parameter.
func (conf *Config) offsetof(typ Type, index []int) int64 {
var o int64
for _, i := range index {
- s := asStruct(typ)
+ s := under(typ).(*Struct)
o += conf.offsetsof(s)[i]
typ = s.fields[i].typ
}
return t
}
-// Convenience converters
-
-func asBasic(t Type) *Basic {
- u, _ := under(t).(*Basic)
- return u
-}
-
-func asArray(t Type) *Array {
- u, _ := under(t).(*Array)
- return u
-}
-
-func asSlice(t Type) *Slice {
- u, _ := under(t).(*Slice)
- return u
-}
-
-func asStruct(t Type) *Struct {
- u, _ := under(t).(*Struct)
- return u
-}
-
-func asPointer(t Type) *Pointer {
- u, _ := under(t).(*Pointer)
- return u
-}
-
-func asSignature(t Type) *Signature {
- u, _ := under(t).(*Signature)
- return u
-}
-
-func asInterface(t Type) *Interface {
- u, _ := under(t).(*Interface)
- return u
-}
-
// If the argument to asNamed, or asTypeParam is of the respective type
-// (possibly after expanding resolving a *Named type), these methods return that type.
+// (possibly after resolving a *Named type), these methods return that type.
// Otherwise the result is nil.
func asNamed(t Type) *Named {
} else {
// special case:
// append(s, "foo"...) leads to signature func([]byte, string...)
- if t := asBasic(typ); t == nil || t.kind != String {
+ if t, _ := under(typ).(*Basic); t == nil || t.kind != String {
w.error("expected string type")
continue
}
// 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 := asInterface(typ); t != nil {
+ if t, _ := under(typ).(*Interface); t != nil {
pos := syntax.StartPos(e)
tset := computeInterfaceTypeSet(check, pos, t) // TODO(gri) is this the correct position?
if !tset.IsMethodSet() {