| // 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 types |
| |
| import ( |
| "fmt" |
| "go/token" |
| "sync/atomic" |
| ) |
| |
| // 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 |
| } |
| |
| // BasicKind describes the kind of basic type. |
| type BasicKind int |
| |
| const ( |
| Invalid BasicKind = iota // type is invalid |
| |
| // predeclared types |
| Bool |
| Int |
| Int8 |
| Int16 |
| Int32 |
| Int64 |
| Uint |
| Uint8 |
| Uint16 |
| Uint32 |
| Uint64 |
| Uintptr |
| Float32 |
| Float64 |
| Complex64 |
| Complex128 |
| String |
| UnsafePointer |
| |
| // types for untyped values |
| UntypedBool |
| UntypedInt |
| UntypedRune |
| UntypedFloat |
| UntypedComplex |
| UntypedString |
| UntypedNil |
| |
| // aliases |
| Byte = Uint8 |
| Rune = Int32 |
| ) |
| |
| // BasicInfo is a set of flags describing properties of a basic type. |
| type BasicInfo int |
| |
| // Properties of basic types. |
| const ( |
| IsBoolean BasicInfo = 1 << iota |
| IsInteger |
| IsUnsigned |
| IsFloat |
| IsComplex |
| IsString |
| IsUntyped |
| |
| IsOrdered = IsInteger | IsFloat | IsString |
| IsNumeric = IsInteger | IsFloat | IsComplex |
| IsConstType = IsBoolean | IsNumeric | IsString |
| ) |
| |
| // A Basic represents a basic type. |
| type Basic struct { |
| kind BasicKind |
| info BasicInfo |
| name string |
| } |
| |
| // Kind returns the kind of basic type b. |
| func (b *Basic) Kind() BasicKind { return b.kind } |
| |
| // Info returns information about properties of basic type b. |
| func (b *Basic) Info() BasicInfo { return b.info } |
| |
| // Name returns the name of basic type b. |
| func (b *Basic) Name() string { return b.name } |
| |
| // An Array represents an array type. |
| type Array struct { |
| len int64 |
| elem Type |
| } |
| |
| // NewArray returns a new array type for the given element type and length. |
| // A negative length indicates an unknown length. |
| func NewArray(elem Type, len int64) *Array { return &Array{len: len, elem: elem} } |
| |
| // Len returns the length of array a. |
| // A negative result indicates an unknown length. |
| func (a *Array) Len() int64 { return a.len } |
| |
| // Elem returns element type of array a. |
| func (a *Array) Elem() Type { return a.elem } |
| |
| // A Slice represents a slice type. |
| type Slice struct { |
| elem Type |
| } |
| |
| // NewSlice returns a new slice type for the given element type. |
| func NewSlice(elem Type) *Slice { return &Slice{elem: elem} } |
| |
| // Elem returns the element type of slice s. |
| func (s *Slice) Elem() Type { return s.elem } |
| |
| // A Struct represents a struct type. |
| type Struct struct { |
| fields []*Var |
| tags []string // field tags; nil if there are no tags |
| } |
| |
| // NewStruct returns a new struct with the given fields and corresponding field tags. |
| // If a field with index i has a tag, tags[i] must be that tag, but len(tags) may be |
| // only as long as required to hold the tag with the largest index i. Consequently, |
| // if no field has a tag, tags may be nil. |
| func NewStruct(fields []*Var, tags []string) *Struct { |
| var fset objset |
| for _, f := range fields { |
| if f.name != "_" && fset.insert(f) != nil { |
| panic("multiple fields with the same name") |
| } |
| } |
| if len(tags) > len(fields) { |
| panic("more tags than fields") |
| } |
| return &Struct{fields: fields, tags: tags} |
| } |
| |
| // NumFields returns the number of fields in the struct (including blank and embedded fields). |
| func (s *Struct) NumFields() int { return len(s.fields) } |
| |
| // Field returns the i'th field for 0 <= i < NumFields(). |
| func (s *Struct) Field(i int) *Var { return s.fields[i] } |
| |
| // Tag returns the i'th field tag for 0 <= i < NumFields(). |
| func (s *Struct) Tag(i int) string { |
| if i < len(s.tags) { |
| return s.tags[i] |
| } |
| return "" |
| } |
| |
| // A Pointer represents a pointer type. |
| type Pointer struct { |
| base Type // element type |
| } |
| |
| // NewPointer returns a new pointer type for the given element (base) type. |
| func NewPointer(elem Type) *Pointer { return &Pointer{base: elem} } |
| |
| // Elem returns the element type for the given pointer p. |
| func (p *Pointer) Elem() Type { return p.base } |
| |
| // A Tuple represents an ordered list of variables; a nil *Tuple is a valid (empty) tuple. |
| // Tuples are used as components of signatures and to represent the type of multiple |
| // assignments; they are not first class types of Go. |
| type Tuple struct { |
| vars []*Var |
| } |
| |
| // NewTuple returns a new tuple for the given variables. |
| func NewTuple(x ...*Var) *Tuple { |
| if len(x) > 0 { |
| return &Tuple{vars: x} |
| } |
| // TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; |
| // it's too subtle and causes problems. |
| return nil |
| } |
| |
| // Len returns the number variables of tuple t. |
| func (t *Tuple) Len() int { |
| if t != nil { |
| return len(t.vars) |
| } |
| return 0 |
| } |
| |
| // At returns the i'th variable of tuple t. |
| func (t *Tuple) At(i int) *Var { return t.vars[i] } |
| |
| // A Signature represents a (non-builtin) function or method type. |
| // The receiver is ignored when comparing signatures for identity. |
| type Signature struct { |
| // We need to keep the scope in Signature (rather than passing it around |
| // and store it in the Func Object) because when type-checking a function |
| // literal we call the general type checker which returns a general Type. |
| // We then unpack the *Signature and use the scope for the literal body. |
| rparams []*TypeName // receiver type parameters from left to right, or nil |
| tparams []*TypeName // type parameters from left to right, or nil |
| scope *Scope // function scope, present for package-local signatures |
| recv *Var // nil if not a method |
| params *Tuple // (incoming) parameters from left to right; or nil |
| results *Tuple // (outgoing) results from left to right; or nil |
| variadic bool // true if the last parameter's type is of the form ...T (or string, for append built-in only) |
| } |
| |
| // NewSignature returns a new function type for the given receiver, parameters, |
| // and results, either of which may be nil. If variadic is set, the function |
| // is variadic, it must have at least one parameter, and the last parameter |
| // must be of unnamed slice type. |
| func NewSignature(recv *Var, params, results *Tuple, variadic bool) *Signature { |
| if variadic { |
| n := params.Len() |
| if n == 0 { |
| panic("types.NewSignature: variadic function must have at least one parameter") |
| } |
| if _, ok := params.At(n - 1).typ.(*Slice); !ok { |
| panic("types.NewSignature: variadic parameter must be of unnamed slice type") |
| } |
| } |
| return &Signature{recv: recv, params: params, results: results, variadic: variadic} |
| } |
| |
| // Recv returns the receiver of signature s (if a method), or nil if a |
| // function. It is ignored when comparing signatures for identity. |
| // |
| // For an abstract method, Recv returns the enclosing interface either |
| // as a *Named or an *Interface. Due to embedding, an interface may |
| // contain methods whose receiver type is a different interface. |
| func (s *Signature) Recv() *Var { return s.recv } |
| |
| // _TParams returns the type parameters of signature s, or nil. |
| func (s *Signature) _TParams() []*TypeName { return s.tparams } |
| |
| // _SetTParams sets the type parameters of signature s. |
| func (s *Signature) _SetTParams(tparams []*TypeName) { s.tparams = tparams } |
| |
| // Params returns the parameters of signature s, or nil. |
| func (s *Signature) Params() *Tuple { return s.params } |
| |
| // Results returns the results of signature s, or nil. |
| func (s *Signature) Results() *Tuple { return s.results } |
| |
| // Variadic reports whether the signature s is variadic. |
| func (s *Signature) Variadic() bool { return s.variadic } |
| |
| // A _Sum represents a set of possible types. |
| // Sums are currently used to represent type lists of interfaces |
| // and thus the underlying types of type parameters; they are not |
| // first class types of Go. |
| type _Sum struct { |
| types []Type // types are unique |
| } |
| |
| // _NewSum returns a new Sum type consisting of the provided |
| // types if there are more than one. If there is exactly one |
| // type, it returns that type. If the list of types is empty |
| // the result is nil. |
| func _NewSum(types []Type) Type { |
| if len(types) == 0 { |
| return nil |
| } |
| |
| // What should happen if types contains a sum type? |
| // Do we flatten the types list? For now we check |
| // and panic. This should not be possible for the |
| // current use case of type lists. |
| // TODO(gri) Come up with the rules for sum types. |
| for _, t := range types { |
| if _, ok := t.(*_Sum); ok { |
| panic("sum type contains sum type - unimplemented") |
| } |
| } |
| |
| if len(types) == 1 { |
| return types[0] |
| } |
| return &_Sum{types: types} |
| } |
| |
| // is reports whether all types in t satisfy pred. |
| func (s *_Sum) is(pred func(Type) bool) bool { |
| if s == nil { |
| return false |
| } |
| for _, t := range s.types { |
| if !pred(t) { |
| return false |
| } |
| } |
| return true |
| } |
| |
| // An Interface represents an interface type. |
| type Interface struct { |
| methods []*Func // ordered list of explicitly declared methods |
| types Type // (possibly a Sum) type declared with a type list (TODO(gri) need better field name) |
| embeddeds []Type // ordered list of explicitly embedded types |
| |
| allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset) |
| allTypes Type // intersection of all embedded and locally declared types (TODO(gri) need better field name) |
| |
| obj Object // type declaration defining this interface; or nil (for better error messages) |
| } |
| |
| // unpack unpacks a type into a list of types. |
| // TODO(gri) Try to eliminate the need for this function. |
| func unpackType(typ Type) []Type { |
| if typ == nil { |
| return nil |
| } |
| if sum := asSum(typ); sum != nil { |
| return sum.types |
| } |
| return []Type{typ} |
| } |
| |
| // is reports whether interface t represents types that all satisfy pred. |
| func (t *Interface) is(pred func(Type) bool) bool { |
| if t.allTypes == nil { |
| return false // we must have at least one type! (was bug) |
| } |
| for _, t := range unpackType(t.allTypes) { |
| if !pred(t) { |
| return false |
| } |
| } |
| return true |
| } |
| |
| // emptyInterface represents the empty (completed) interface |
| var emptyInterface = Interface{allMethods: markComplete} |
| |
| // markComplete is used to mark an empty interface as completely |
| // set up by setting the allMethods field to a non-nil empty slice. |
| var markComplete = make([]*Func, 0) |
| |
| // NewInterface returns a new (incomplete) interface for the given methods and embedded types. |
| // Each embedded type must have an underlying type of interface type. |
| // NewInterface takes ownership of the provided methods and may modify their types by setting |
| // missing receivers. To compute the method set of the interface, Complete must be called. |
| // |
| // Deprecated: Use NewInterfaceType instead which allows any (even non-defined) interface types |
| // to be embedded. This is necessary for interfaces that embed alias type names referring to |
| // non-defined (literal) interface types. |
| func NewInterface(methods []*Func, embeddeds []*Named) *Interface { |
| tnames := make([]Type, len(embeddeds)) |
| for i, t := range embeddeds { |
| tnames[i] = t |
| } |
| return NewInterfaceType(methods, tnames) |
| } |
| |
| // NewInterfaceType returns a new (incomplete) interface for the given methods and embedded types. |
| // Each embedded type must have an underlying type of interface type (this property is not |
| // verified for defined types, which may be in the process of being set up and which don't |
| // have a valid underlying type yet). |
| // NewInterfaceType takes ownership of the provided methods and may modify their types by setting |
| // missing receivers. To compute the method set of the interface, Complete must be called. |
| func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { |
| if len(methods) == 0 && len(embeddeds) == 0 { |
| return &emptyInterface |
| } |
| |
| // set method receivers if necessary |
| typ := new(Interface) |
| for _, m := range methods { |
| if sig := m.typ.(*Signature); sig.recv == nil { |
| sig.recv = NewVar(m.pos, m.pkg, "", typ) |
| } |
| } |
| |
| // All embedded types should be interfaces; however, defined types |
| // may not yet be fully resolved. Only verify that non-defined types |
| // are interfaces. This matches the behavior of the code before the |
| // fix for #25301 (issue #25596). |
| for _, t := range embeddeds { |
| if _, ok := t.(*Named); !ok && !IsInterface(t) { |
| panic("embedded type is not an interface") |
| } |
| } |
| |
| // sort for API stability |
| sortMethods(methods) |
| sortTypes(embeddeds) |
| |
| typ.methods = methods |
| typ.embeddeds = embeddeds |
| return typ |
| } |
| |
| // NumExplicitMethods returns the number of explicitly declared methods of interface t. |
| func (t *Interface) NumExplicitMethods() int { return len(t.methods) } |
| |
| // ExplicitMethod returns the i'th explicitly declared method of interface t for 0 <= i < t.NumExplicitMethods(). |
| // The methods are ordered by their unique Id. |
| func (t *Interface) ExplicitMethod(i int) *Func { return t.methods[i] } |
| |
| // NumEmbeddeds returns the number of embedded types in interface t. |
| func (t *Interface) NumEmbeddeds() int { return len(t.embeddeds) } |
| |
| // Embedded returns the i'th embedded defined (*Named) type of interface t for 0 <= i < t.NumEmbeddeds(). |
| // The result is nil if the i'th embedded type is not a defined type. |
| // |
| // Deprecated: Use EmbeddedType which is not restricted to defined (*Named) types. |
| func (t *Interface) Embedded(i int) *Named { tname, _ := t.embeddeds[i].(*Named); return tname } |
| |
| // EmbeddedType returns the i'th embedded type of interface t for 0 <= i < t.NumEmbeddeds(). |
| func (t *Interface) EmbeddedType(i int) Type { return t.embeddeds[i] } |
| |
| // NumMethods returns the total number of methods of interface t. |
| // The interface must have been completed. |
| func (t *Interface) NumMethods() int { t.assertCompleteness(); return len(t.allMethods) } |
| |
| func (t *Interface) assertCompleteness() { |
| if t.allMethods == nil { |
| panic("interface is incomplete") |
| } |
| } |
| |
| // Method returns the i'th method of interface t for 0 <= i < t.NumMethods(). |
| // The methods are ordered by their unique Id. |
| // The interface must have been completed. |
| func (t *Interface) Method(i int) *Func { t.assertCompleteness(); return t.allMethods[i] } |
| |
| // Empty reports whether t is the empty interface. |
| func (t *Interface) Empty() bool { |
| if t.allMethods != nil { |
| // interface is complete - quick test |
| // A non-nil allTypes may still be empty and represents the bottom type. |
| return len(t.allMethods) == 0 && t.allTypes == nil |
| } |
| return !t.iterate(func(t *Interface) bool { |
| return len(t.methods) > 0 || t.types != nil |
| }, nil) |
| } |
| |
| // _HasTypeList reports whether interface t has a type list, possibly from an embedded type. |
| func (t *Interface) _HasTypeList() bool { |
| if t.allMethods != nil { |
| // interface is complete - quick test |
| return t.allTypes != nil |
| } |
| |
| return t.iterate(func(t *Interface) bool { |
| return t.types != nil |
| }, nil) |
| } |
| |
| // _IsComparable reports whether interface t is or embeds the predeclared interface "comparable". |
| func (t *Interface) _IsComparable() bool { |
| if t.allMethods != nil { |
| // interface is complete - quick test |
| _, m := lookupMethod(t.allMethods, nil, "==") |
| return m != nil |
| } |
| |
| return t.iterate(func(t *Interface) bool { |
| _, m := lookupMethod(t.methods, nil, "==") |
| return m != nil |
| }, nil) |
| } |
| |
| // _IsConstraint reports t.HasTypeList() || t.IsComparable(). |
| func (t *Interface) _IsConstraint() bool { |
| if t.allMethods != nil { |
| // interface is complete - quick test |
| if t.allTypes != nil { |
| return true |
| } |
| _, m := lookupMethod(t.allMethods, nil, "==") |
| return m != nil |
| } |
| |
| return t.iterate(func(t *Interface) bool { |
| if t.types != nil { |
| return true |
| } |
| _, m := lookupMethod(t.methods, nil, "==") |
| return m != nil |
| }, nil) |
| } |
| |
| // iterate calls f with t and then with any embedded interface of t, recursively, until f returns true. |
| // iterate reports whether any call to f returned true. |
| func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) bool { |
| if f(t) { |
| return true |
| } |
| for _, e := range t.embeddeds { |
| // e should be an interface but be careful (it may be invalid) |
| if e := asInterface(e); e != nil { |
| // Cyclic interfaces such as "type E interface { E }" are not permitted |
| // but they are still constructed and we need to detect such cycles. |
| if seen[e] { |
| continue |
| } |
| if seen == nil { |
| seen = make(map[*Interface]bool) |
| } |
| seen[e] = true |
| if e.iterate(f, seen) { |
| return true |
| } |
| } |
| } |
| return false |
| } |
| |
| // isSatisfiedBy reports whether interface t's type list is satisfied by the type typ. |
| // If the type list is empty (absent), typ trivially satisfies the interface. |
| // TODO(gri) This is not a great name. Eventually, we should have a more comprehensive |
| // "implements" predicate. |
| func (t *Interface) isSatisfiedBy(typ Type) bool { |
| t.Complete() |
| if t.allTypes == nil { |
| return true |
| } |
| types := unpackType(t.allTypes) |
| return includes(types, typ) || includes(types, under(typ)) |
| } |
| |
| // Complete computes the interface's method set. It must be called by users of |
| // NewInterfaceType and NewInterface after the interface's embedded types are |
| // fully defined and before using the interface type in any way other than to |
| // form other types. The interface must not contain duplicate methods or a |
| // panic occurs. Complete returns the receiver. |
| func (t *Interface) Complete() *Interface { |
| // TODO(gri) consolidate this method with Checker.completeInterface |
| if t.allMethods != nil { |
| return t |
| } |
| |
| t.allMethods = markComplete // avoid infinite recursion |
| |
| var todo []*Func |
| var methods []*Func |
| var seen objset |
| addMethod := func(m *Func, explicit bool) { |
| switch other := seen.insert(m); { |
| case other == nil: |
| methods = append(methods, m) |
| case explicit: |
| panic("duplicate method " + m.name) |
| default: |
| // check method signatures after all locally embedded interfaces are computed |
| todo = append(todo, m, other.(*Func)) |
| } |
| } |
| |
| for _, m := range t.methods { |
| addMethod(m, true) |
| } |
| |
| allTypes := t.types |
| |
| for _, typ := range t.embeddeds { |
| utyp := under(typ) |
| etyp := asInterface(utyp) |
| if etyp == nil { |
| if utyp != Typ[Invalid] { |
| panic(fmt.Sprintf("%s is not an interface", typ)) |
| } |
| continue |
| } |
| etyp.Complete() |
| for _, m := range etyp.allMethods { |
| addMethod(m, false) |
| } |
| allTypes = intersect(allTypes, etyp.allTypes) |
| } |
| |
| for i := 0; i < len(todo); i += 2 { |
| m := todo[i] |
| other := todo[i+1] |
| if !Identical(m.typ, other.typ) { |
| panic("duplicate method " + m.name) |
| } |
| } |
| |
| if methods != nil { |
| sortMethods(methods) |
| t.allMethods = methods |
| } |
| t.allTypes = allTypes |
| |
| return t |
| } |
| |
| // A Map represents a map type. |
| type Map struct { |
| key, elem Type |
| } |
| |
| // NewMap returns a new map for the given key and element types. |
| func NewMap(key, elem Type) *Map { |
| return &Map{key: key, elem: elem} |
| } |
| |
| // Key returns the key type of map m. |
| func (m *Map) Key() Type { return m.key } |
| |
| // Elem returns the element type of map m. |
| func (m *Map) Elem() Type { return m.elem } |
| |
| // A Chan represents a channel type. |
| type Chan struct { |
| dir ChanDir |
| elem Type |
| } |
| |
| // A ChanDir value indicates a channel direction. |
| type ChanDir int |
| |
| // The direction of a channel is indicated by one of these constants. |
| const ( |
| SendRecv ChanDir = iota |
| SendOnly |
| RecvOnly |
| ) |
| |
| // NewChan returns a new channel type for the given direction and element type. |
| func NewChan(dir ChanDir, elem Type) *Chan { |
| return &Chan{dir: dir, elem: elem} |
| } |
| |
| // Dir returns the direction of channel c. |
| func (c *Chan) Dir() ChanDir { return c.dir } |
| |
| // Elem returns the element type of channel c. |
| func (c *Chan) Elem() Type { return c.elem } |
| |
| // A Named represents a named (defined) type. |
| type Named struct { |
| check *Checker // for Named.under implementation; nilled once under has been called |
| info typeInfo // for cycle detection |
| obj *TypeName // corresponding declared object |
| orig Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting) |
| underlying Type // possibly a *Named during setup; never a *Named once set up completely |
| tparams []*TypeName // type parameters, or nil |
| targs []Type // type arguments (after instantiation), or nil |
| methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily |
| } |
| |
| // NewNamed returns a new named type for the given type name, underlying type, and associated methods. |
| // If the given type name obj doesn't have a type yet, its type is set to the returned named type. |
| // The underlying type must not be a *Named. |
| func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named { |
| if _, ok := underlying.(*Named); ok { |
| panic("types.NewNamed: underlying type must not be *Named") |
| } |
| return (*Checker)(nil).newNamed(obj, underlying, methods) |
| } |
| |
| func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) *Named { |
| typ := &Named{check: check, obj: obj, orig: underlying, underlying: underlying, methods: methods} |
| if obj.typ == nil { |
| obj.typ = typ |
| } |
| // Ensure that typ is always expanded, at which point the check field can be |
| // nilled out. |
| // |
| // Note that currently we cannot nil out check inside typ.under(), because |
| // it's possible that typ is expanded multiple times. |
| // |
| // TODO(rFindley): clean this up so that under is the only function mutating |
| // named types. |
| if check != nil { |
| check.later(func() { |
| switch typ.under().(type) { |
| case *Named, *instance: |
| panic("internal error: unexpanded underlying type") |
| } |
| typ.check = nil |
| }) |
| } |
| return typ |
| } |
| |
| // Obj returns the type name for the named type t. |
| func (t *Named) Obj() *TypeName { return t.obj } |
| |
| // TODO(gri) Come up with a better representation and API to distinguish |
| // between parameterized instantiated and non-instantiated types. |
| |
| // _TParams returns the type parameters of the named type t, or nil. |
| // The result is non-nil for an (originally) parameterized type even if it is instantiated. |
| func (t *Named) _TParams() []*TypeName { return t.tparams } |
| |
| // _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated. |
| func (t *Named) _TArgs() []Type { return t.targs } |
| |
| // _SetTArgs sets the type arguments of Named. |
| func (t *Named) _SetTArgs(args []Type) { t.targs = args } |
| |
| // NumMethods returns the number of explicit methods whose receiver is named type t. |
| func (t *Named) NumMethods() int { return len(t.methods) } |
| |
| // Method returns the i'th method of named type t for 0 <= i < t.NumMethods(). |
| func (t *Named) Method(i int) *Func { return t.methods[i] } |
| |
| // SetUnderlying sets the underlying type and marks t as complete. |
| func (t *Named) SetUnderlying(underlying Type) { |
| if underlying == nil { |
| panic("types.Named.SetUnderlying: underlying type must not be nil") |
| } |
| if _, ok := underlying.(*Named); ok { |
| panic("types.Named.SetUnderlying: underlying type must not be *Named") |
| } |
| t.underlying = underlying |
| } |
| |
| // AddMethod adds method m unless it is already in the method list. |
| func (t *Named) AddMethod(m *Func) { |
| if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 { |
| t.methods = append(t.methods, m) |
| } |
| } |
| |
| // Note: This is a uint32 rather than a uint64 because the |
| // respective 64 bit atomic instructions are not available |
| // on all platforms. |
| var lastId uint32 |
| |
| // nextId returns a value increasing monotonically by 1 with |
| // each call, starting with 1. It may be called concurrently. |
| func nextId() uint64 { return uint64(atomic.AddUint32(&lastId, 1)) } |
| |
| // A _TypeParam represents a type parameter type. |
| type _TypeParam struct { |
| check *Checker // for lazy type bound completion |
| id uint64 // unique id |
| obj *TypeName // corresponding type name |
| index int // parameter index |
| bound Type // *Named or *Interface; underlying type is always *Interface |
| } |
| |
| // newTypeParam returns a new TypeParam. |
| func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *_TypeParam { |
| assert(bound != nil) |
| typ := &_TypeParam{check: check, id: nextId(), obj: obj, index: index, bound: bound} |
| if obj.typ == nil { |
| obj.typ = typ |
| } |
| return typ |
| } |
| |
| func (t *_TypeParam) Bound() *Interface { |
| iface := asInterface(t.bound) |
| // use the type bound position if we have one |
| pos := token.NoPos |
| if n, _ := t.bound.(*Named); n != nil { |
| pos = n.obj.pos |
| } |
| // TODO(rFindley) switch this to an unexported method on Checker. |
| t.check.completeInterface(pos, iface) |
| return iface |
| } |
| |
| // 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 determined |
| // by the corresponding type bound's type list. The |
| // result may be the bottom or top type, but it is never |
| // the incoming type parameter. |
| func optype(typ Type) Type { |
| if t := asTypeParam(typ); t != nil { |
| // 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.Bound().allTypes; u != nil && u != typ { |
| // u != typ and u is a type parameter => under(u) != typ, so this is ok |
| return under(u) |
| } |
| return theTop |
| } |
| return under(typ) |
| } |
| |
| // An instance represents an instantiated generic type syntactically |
| // (without expanding the instantiation). Type instances appear only |
| // during type-checking and are replaced by their fully instantiated |
| // (expanded) types before the end of type-checking. |
| type instance struct { |
| check *Checker // for lazy instantiation |
| pos token.Pos // position of type instantiation; for error reporting only |
| base *Named // parameterized type to be instantiated |
| targs []Type // type arguments |
| poslist []token.Pos // position of each targ; for error reporting only |
| value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set |
| } |
| |
| // expand returns the instantiated (= expanded) type of t. |
| // The result is either an instantiated *Named type, or |
| // Typ[Invalid] if there was an error. |
| func (t *instance) expand() Type { |
| v := t.value |
| if v == nil { |
| v = t.check.instantiate(t.pos, t.base, t.targs, t.poslist) |
| if v == nil { |
| v = Typ[Invalid] |
| } |
| t.value = v |
| } |
| // After instantiation we must have an invalid or a *Named type. |
| if debug && v != Typ[Invalid] { |
| _ = v.(*Named) |
| } |
| return v |
| } |
| |
| // expand expands a type instance into its instantiated |
| // type and leaves all other types alone. expand does |
| // not recurse. |
| func expand(typ Type) Type { |
| if t, _ := typ.(*instance); t != nil { |
| return t.expand() |
| } |
| return typ |
| } |
| |
| // expandf is set to expand. |
| // Call expandf when calling expand causes compile-time cycle error. |
| var expandf func(Type) Type |
| |
| func init() { expandf = expand } |
| |
| // bottom represents the bottom of the type lattice. |
| // It is the underlying type of a type parameter that |
| // cannot be satisfied by any type, usually because |
| // the intersection of type constraints left nothing). |
| type bottom struct{} |
| |
| // theBottom is the singleton bottom type. |
| var theBottom = &bottom{} |
| |
| // 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), |
| // usually because the type constraint has no type |
| // list. |
| type top struct{} |
| |
| // theTop is the singleton top type. |
| var theTop = &top{} |
| |
| // Type-specific implementations of Underlying. |
| func (t *Basic) Underlying() Type { return t } |
| func (t *Array) Underlying() Type { return t } |
| func (t *Slice) Underlying() Type { return t } |
| func (t *Struct) Underlying() Type { return t } |
| func (t *Pointer) Underlying() Type { return t } |
| func (t *Tuple) Underlying() Type { return t } |
| func (t *Signature) Underlying() Type { return t } |
| func (t *_Sum) Underlying() Type { return t } |
| func (t *Interface) Underlying() Type { return t } |
| func (t *Map) Underlying() Type { return t } |
| func (t *Chan) Underlying() Type { return t } |
| func (t *Named) Underlying() Type { return t.underlying } |
| func (t *_TypeParam) Underlying() Type { return t } |
| func (t *instance) Underlying() Type { return t } |
| func (t *bottom) Underlying() Type { return t } |
| func (t *top) Underlying() Type { return t } |
| |
| // Type-specific implementations of String. |
| func (t *Basic) String() string { return TypeString(t, nil) } |
| func (t *Array) String() string { return TypeString(t, nil) } |
| func (t *Slice) String() string { return TypeString(t, nil) } |
| func (t *Struct) String() string { return TypeString(t, nil) } |
| func (t *Pointer) String() string { return TypeString(t, nil) } |
| func (t *Tuple) String() string { return TypeString(t, nil) } |
| func (t *Signature) String() string { return TypeString(t, nil) } |
| func (t *_Sum) String() string { return TypeString(t, nil) } |
| func (t *Interface) String() string { return TypeString(t, nil) } |
| func (t *Map) String() string { return TypeString(t, nil) } |
| func (t *Chan) String() string { return TypeString(t, nil) } |
| func (t *Named) String() string { return TypeString(t, nil) } |
| func (t *_TypeParam) String() string { return TypeString(t, nil) } |
| func (t *instance) String() string { return TypeString(t, nil) } |
| func (t *bottom) String() string { return TypeString(t, nil) } |
| 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 { |
| // TODO(gri) is this correct for *Sum? |
| if n := asNamed(t); n != nil { |
| return n.under() |
| } |
| return t |
| } |
| |
| // 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 asTuple(t Type) *Tuple { |
| op, _ := optype(t).(*Tuple) |
| return op |
| } |
| |
| func asSignature(t Type) *Signature { |
| op, _ := optype(t).(*Signature) |
| return op |
| } |
| |
| func asSum(t Type) *_Sum { |
| op, _ := optype(t).(*_Sum) |
| return op |
| } |
| |
| func asInterface(t Type) *Interface { |
| op, _ := optype(t).(*Interface) |
| return op |
| } |
| |
| func asMap(t Type) *Map { |
| op, _ := optype(t).(*Map) |
| return op |
| } |
| |
| func asChan(t Type) *Chan { |
| op, _ := optype(t).(*Chan) |
| return op |
| } |
| |
| // If the argument to asNamed and asTypeParam is of the respective types |
| // (possibly after expanding an instance type), these methods return that type. |
| // Otherwise the result is nil. |
| |
| func asNamed(t Type) *Named { |
| e, _ := expand(t).(*Named) |
| return e |
| } |
| |
| func asTypeParam(t Type) *_TypeParam { |
| u, _ := under(t).(*_TypeParam) |
| return u |
| } |