diff options
Diffstat (limited to 'src/cmd/compile/internal/types2/type.go')
-rw-r--r-- | src/cmd/compile/internal/types2/type.go | 322 |
1 files changed, 114 insertions, 208 deletions
diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 7e51a138b5..52bd99deab 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -1,4 +1,3 @@ -// UNREVIEWED // 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. @@ -18,67 +17,10 @@ type Type interface { // client packages (here for backward-compatibility). Underlying() Type - // 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. - Under() Type - // String returns a string representation of a type. String() string - - // 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 is receiver is not of the - // respective type. - Basic() *Basic - Array() *Array - Slice() *Slice - Struct() *Struct - Pointer() *Pointer - Tuple() *Tuple - Signature() *Signature - Sum() *Sum - Interface() *Interface - Map() *Map - Chan() *Chan - - // If the receiver for Named and TypeParam is of - // the respective type (possibly after unpacking - // an instance type), these methods return that - // type. Otherwise the result is nil. - Named() *Named - TypeParam() *TypeParam } -// aType implements default type behavior -type aType struct{} - -// These methods must be implemented by each type. -func (aType) Underlying() Type { panic("unreachable") } -func (aType) Under() Type { panic("unreachable") } -func (aType) String() string { panic("unreachable") } - -// Each type is implementing its version of these methods -// (Basic must implement Basic, etc.), the other methods -// are inherited. -func (aType) Basic() *Basic { return nil } -func (aType) Array() *Array { return nil } -func (aType) Slice() *Slice { return nil } -func (aType) Struct() *Struct { return nil } -func (aType) Pointer() *Pointer { return nil } -func (aType) Tuple() *Tuple { return nil } -func (aType) Signature() *Signature { return nil } -func (aType) Sum() *Sum { return nil } -func (aType) Interface() *Interface { return nil } -func (aType) Map() *Map { return nil } -func (aType) Chan() *Chan { return nil } - -func (aType) Named() *Named { return nil } -func (aType) TypeParam() *TypeParam { return nil } - // BasicKind describes the kind of basic type. type BasicKind int @@ -142,7 +84,6 @@ type Basic struct { kind BasicKind info BasicInfo name string - aType } // Kind returns the kind of basic type b. @@ -158,7 +99,6 @@ func (b *Basic) Name() string { return b.name } type Array struct { len int64 elem Type - aType } // NewArray returns a new array type for the given element type and length. @@ -175,7 +115,6 @@ func (a *Array) Elem() Type { return a.elem } // A Slice represents a slice type. type Slice struct { elem Type - aType } // NewSlice returns a new slice type for the given element type. @@ -188,7 +127,6 @@ func (s *Slice) Elem() Type { return s.elem } type Struct struct { fields []*Var tags []string // field tags; nil if there are no tags - aType } // NewStruct returns a new struct with the given fields and corresponding field tags. @@ -225,7 +163,6 @@ func (s *Struct) Tag(i int) string { // A Pointer represents a pointer type. type Pointer struct { base Type // element type - aType } // NewPointer returns a new pointer type for the given element (base) type. @@ -239,7 +176,6 @@ func (p *Pointer) Elem() Type { return p.base } // assignments; they are not first class types of Go. type Tuple struct { vars []*Var - aType } // NewTuple returns a new tuple for the given variables. @@ -247,31 +183,11 @@ 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 } -// We cannot rely on the embedded X() *X methods because (*Tuple)(nil) -// is a valid *Tuple value but (*Tuple)(nil).X() would panic without -// these implementations. At the moment we only need X = Basic, Named, -// but add all because missing one leads to very confusing bugs. -// TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer; -// it's too subtle and causes problems. -func (*Tuple) Basic() *Basic { return nil } -func (*Tuple) Array() *Array { return nil } -func (*Tuple) Slice() *Slice { return nil } -func (*Tuple) Struct() *Struct { return nil } -func (*Tuple) Pointer() *Pointer { return nil } - -// func (*Tuple) Tuple() *Tuple // implemented below -func (*Tuple) Signature() *Signature { return nil } -func (*Tuple) Sum() *Sum { return nil } -func (*Tuple) Interface() *Interface { return nil } -func (*Tuple) Map() *Map { return nil } -func (*Tuple) Chan() *Chan { return nil } - -func (*Tuple) Named() *Named { return nil } -func (*Tuple) TypeParam() *TypeParam { return nil } - // Len returns the number variables of tuple t. func (t *Tuple) Len() int { if t != nil { @@ -290,14 +206,13 @@ type Signature struct { // 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 // reveiver type parameters from left to right; or nil + 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) - aType } // NewSignature returns a new function type for the given receiver, parameters, @@ -346,7 +261,6 @@ func (s *Signature) Variadic() bool { return s.variadic } // first class types of Go. type Sum struct { types []Type // types are unique - aType } // NewSum returns a new Sum type consisting of the provided @@ -398,8 +312,6 @@ type Interface struct { 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) - - aType } // unpack unpacks a type into a list of types. @@ -408,7 +320,7 @@ func unpack(typ Type) []Type { if typ == nil { return nil } - if sum := typ.Sum(); sum != nil { + if sum := asSum(typ); sum != nil { return sum.types } return []Type{typ} @@ -530,10 +442,7 @@ func (t *Interface) Empty() bool { return len(t.allMethods) == 0 && t.allTypes == nil } return !t.iterate(func(t *Interface) bool { - if len(t.methods) > 0 || t.types != nil { - return true - } - return false + return len(t.methods) > 0 || t.types != nil }, nil) } @@ -545,10 +454,7 @@ func (t *Interface) HasTypeList() bool { } return t.iterate(func(t *Interface) bool { - if t.types != nil { - return true - } - return false + return t.types != nil }, nil) } @@ -594,7 +500,7 @@ func (t *Interface) iterate(f func(*Interface) bool, seen map[*Interface]bool) b } for _, e := range t.embeddeds { // e should be an interface but be careful (it may be invalid) - if e := e.Interface(); e != nil { + 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] { @@ -622,7 +528,7 @@ func (t *Interface) isSatisfiedBy(typ Type) bool { return true } types := unpack(t.allTypes) - return includes(types, typ) || includes(types, typ.Under()) + return includes(types, typ) || includes(types, under(typ)) } // Complete computes the interface's method set. It must be called by users of @@ -660,8 +566,8 @@ func (t *Interface) Complete() *Interface { allTypes := t.types for _, typ := range t.embeddeds { - utyp := typ.Under() - etyp := utyp.Interface() + utyp := under(typ) + etyp := asInterface(utyp) if etyp == nil { if utyp != Typ[Invalid] { panic(fmt.Sprintf("%s is not an interface", typ)) @@ -695,7 +601,6 @@ func (t *Interface) Complete() *Interface { // A Map represents a map type. type Map struct { key, elem Type - aType } // NewMap returns a new map for the given key and element types. @@ -713,7 +618,6 @@ func (m *Map) Elem() Type { return m.elem } type Chan struct { dir ChanDir elem Type - aType } // A ChanDir value indicates a channel direction. @@ -739,7 +643,7 @@ func (c *Chan) Elem() Type { return c.elem } // A Named represents a named (defined) type. type Named struct { - check *Checker // for Named.Under implementation + check *Checker // for Named.under implementation 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) @@ -747,7 +651,6 @@ type Named struct { 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 - aType } // NewNamed returns a new named type for the given type name, underlying type, and associated methods. @@ -775,21 +678,6 @@ func (check *Checker) NewNamed(obj *TypeName, underlying Type, methods []*Func) // Obj returns the type name for the named type t. func (t *Named) Obj() *TypeName { return t.obj } -// Converter methods -func (t *Named) Basic() *Basic { return t.Under().Basic() } -func (t *Named) Array() *Array { return t.Under().Array() } -func (t *Named) Slice() *Slice { return t.Under().Slice() } -func (t *Named) Struct() *Struct { return t.Under().Struct() } -func (t *Named) Pointer() *Pointer { return t.Under().Pointer() } -func (t *Named) Tuple() *Tuple { return t.Under().Tuple() } -func (t *Named) Signature() *Signature { return t.Under().Signature() } -func (t *Named) Interface() *Interface { return t.Under().Interface() } -func (t *Named) Map() *Map { return t.Under().Map() } -func (t *Named) Chan() *Chan { return t.Under().Chan() } - -// func (t *Named) Named() *Named // declared below -func (t *Named) TypeParam() *TypeParam { return t.Under().TypeParam() } - // TODO(gri) Come up with a better representation and API to distinguish // between parameterized instantiated and non-instantiated types. @@ -834,12 +722,10 @@ type TypeParam struct { obj *TypeName // corresponding type name index int // parameter index bound Type // *Named or *Interface; underlying type is always *Interface - aType } -func (t *TypeParam) Obj() *TypeName { - return t.obj -} +// Obj returns the type name for the type parameter t. +func (t *TypeParam) Obj() *TypeName { return t.obj } // NewTypeParam returns a new TypeParam. func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam { @@ -853,56 +739,41 @@ func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypePa } func (t *TypeParam) Bound() *Interface { - iface := t.bound.Interface() + iface := asInterface(t.bound) // use the type bound position if we have one pos := nopos if n, _ := t.bound.(*Named); n != nil { pos = n.obj.pos } + // TODO(gri) 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 +// 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 := typ.TypeParam(); t != nil { + 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 TypeParam converter methods. This can happen + // 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 => u.Under() != typ, so this is ok - return u.Under() + // u != typ and u is a type parameter => under(u) != typ, so this is ok + return under(u) } return theTop } - return typ + return under(typ) } -// Converter methods -func (t *TypeParam) Basic() *Basic { return optype(t).Basic() } -func (t *TypeParam) Array() *Array { return optype(t).Array() } -func (t *TypeParam) Slice() *Slice { return optype(t).Slice() } -func (t *TypeParam) Struct() *Struct { return optype(t).Struct() } -func (t *TypeParam) Pointer() *Pointer { return optype(t).Pointer() } -func (t *TypeParam) Tuple() *Tuple { return optype(t).Tuple() } -func (t *TypeParam) Signature() *Signature { return optype(t).Signature() } -func (t *TypeParam) Sum() *Sum { return optype(t).Sum() } -func (t *TypeParam) Interface() *Interface { return optype(t).Interface() } -func (t *TypeParam) Map() *Map { return optype(t).Map() } -func (t *TypeParam) Chan() *Chan { return optype(t).Chan() } - -// func (t *TypeParam) Named() *Named // Named does not unpack type parameters -// func (t *TypeParam) TypeParam() *TypeParam // declared below - // 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 @@ -914,25 +785,8 @@ type instance struct { targs []Type // type arguments poslist []syntax.Pos // position of each targ; for error reporting only value Type // base(targs...) after instantiation or Typ[Invalid]; nil if not yet set - aType } -// Converter methods -func (t *instance) Basic() *Basic { return t.Under().Basic() } -func (t *instance) Array() *Array { return t.Under().Array() } -func (t *instance) Slice() *Slice { return t.Under().Slice() } -func (t *instance) Struct() *Struct { return t.Under().Struct() } -func (t *instance) Pointer() *Pointer { return t.Under().Pointer() } -func (t *instance) Tuple() *Tuple { return t.Under().Tuple() } -func (t *instance) Signature() *Signature { return t.Under().Signature() } -func (t *instance) Sum() *Sum { return t.Under().Sum() } -func (t *instance) Interface() *Interface { return t.Under().Interface() } -func (t *instance) Map() *Map { return t.Under().Map() } -func (t *instance) Chan() *Chan { return t.Under().Chan() } - -func (t *instance) Named() *Named { return t.expand().Named() } -func (t *instance) TypeParam() *TypeParam { return t.expand().TypeParam() } - // expand returns the instantiated (= expanded) type of t. // The result is either an instantiated *Named type, or // Typ[Invalid] if there was an error. @@ -972,9 +826,7 @@ func init() { expandf = expand } // 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 { - aType -} +type bottom struct{} // theBottom is the singleton bottom type. var theBottom = &bottom{} @@ -984,29 +836,11 @@ var theBottom = &bottom{} // can be satisfied by any type (ignoring methods), // usually because the type constraint has no type // list. -type top struct { - aType -} +type top struct{} // theTop is the singleton top type. var theTop = &top{} -// Type-specific implementations of type converters. -func (t *Basic) Basic() *Basic { return t } -func (t *Array) Array() *Array { return t } -func (t *Slice) Slice() *Slice { return t } -func (t *Struct) Struct() *Struct { return t } -func (t *Pointer) Pointer() *Pointer { return t } -func (t *Tuple) Tuple() *Tuple { return t } -func (t *Signature) Signature() *Signature { return t } -func (t *Sum) Sum() *Sum { return t } -func (t *Interface) Interface() *Interface { return t } -func (t *Map) Map() *Map { return t } -func (t *Chan) Chan() *Chan { return t } - -func (t *Named) Named() *Named { return t } -func (t *TypeParam) TypeParam() *TypeParam { return t } - // Type-specific implementations of Underlying. func (t *Basic) Underlying() Type { return t } func (t *Array) Underlying() Type { return t } @@ -1025,25 +859,6 @@ 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 Under. -func (t *Basic) Under() Type { return t } -func (t *Array) Under() Type { return t } -func (t *Slice) Under() Type { return t } -func (t *Struct) Under() Type { return t } -func (t *Pointer) Under() Type { return t } -func (t *Tuple) Under() Type { return t } -func (t *Signature) Under() Type { return t } -func (t *Sum) Under() Type { return t } // TODO(gri) is this correct? -func (t *Interface) Under() Type { return t } -func (t *Map) Under() Type { return t } -func (t *Chan) Under() Type { return t } - -// see decl.go for implementation of Named.Under -func (t *TypeParam) Under() Type { return t } -func (t *instance) Under() Type { return t.expand().Under() } -func (t *bottom) Under() Type { return t } -func (t *top) Under() 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) } @@ -1061,3 +876,94 @@ 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 +} + +// asTuple is not needed - not provided + +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 +} + +// Exported for the compiler. + +func AsPointer(t Type) *Pointer { return asPointer(t) } +func AsNamed(t Type) *Named { return asNamed(t) } |