// Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package types2 // A Type represents a type of Go. // All types implement the Type interface. type Type interface { // Underlying returns the underlying type of a type // w/o following forwarding chains. Only used by // client packages (here for backward-compatibility). Underlying() Type // String returns a string representation of a type. String() string } // top represents the top of the type lattice. // It is the underlying type of a type parameter that // can be satisfied by any type (ignoring methods), // because its type constraint contains no restrictions // besides methods. type top struct{} // theTop is the singleton top type. var theTop = &top{} func (t *top) Underlying() Type { return t } func (t *top) String() string { return TypeString(t, nil) } // 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 { if n := asNamed(t); n != nil { return n.under() } return t } // optype returns a type's operational type. Except for // type parameters, the operational type is the same // as the underlying type (as returned by under). For // Type parameters, the operational type is the structural // type, if any; otherwise it's the top type. // The result is never the incoming type parameter. func optype(typ Type) Type { if t := asTypeParam(typ); t != nil { // TODO(gri) review accuracy of this comment // If the optype is typ, return the top type as we have // no information. It also prevents infinite recursion // via the asTypeParam converter function. This can happen // for a type parameter list of the form: // (type T interface { type T }). // See also issue #39680. if u := t.structuralType(); u != nil { assert(u != typ) // "naked" type parameters cannot be embedded return u } return theTop } return under(typ) } // Converters // // A converter must only be called when a type is // known to be fully set up. A converter returns // a type's operational type (see comment for optype) // or nil if the type argument is not of the // respective type. func asBasic(t Type) *Basic { op, _ := optype(t).(*Basic) return op } func asArray(t Type) *Array { op, _ := optype(t).(*Array) return op } func asSlice(t Type) *Slice { op, _ := optype(t).(*Slice) return op } func asStruct(t Type) *Struct { op, _ := optype(t).(*Struct) return op } func asPointer(t Type) *Pointer { op, _ := optype(t).(*Pointer) return op } func asSignature(t Type) *Signature { op, _ := optype(t).(*Signature) return op } // If the argument to asInterface, asNamed, or asTypeParam is of the respective type // (possibly after expanding an instance type), these methods return that type. // Otherwise the result is nil. // asInterface does not need to look at optype (type sets don't contain interfaces) func asInterface(t Type) *Interface { u, _ := under(t).(*Interface) return u } func asNamed(t Type) *Named { e, _ := t.(*Named) if e != nil { e.expand(nil) } return e } func asTypeParam(t Type) *TypeParam { u, _ := under(t).(*TypeParam) return u } // Exported for the compiler. func AsPointer(t Type) *Pointer { return asPointer(t) } func AsNamed(t Type) *Named { return asNamed(t) } func AsSignature(t Type) *Signature { return asSignature(t) } func AsInterface(t Type) *Interface { return asInterface(t) } func AsTypeParam(t Type) *TypeParam { return asTypeParam(t) }