]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] go/types: move (remaining) type decls into their own files (cleanup)
authorRob Findley <rfindley@google.com>
Fri, 16 Jul 2021 14:59:53 +0000 (10:59 -0400)
committerRobert Findley <rfindley@google.com>
Fri, 16 Jul 2021 23:35:10 +0000 (23:35 +0000)
This is a port of CL 332093 to go/types. A missing comment is added to
named.go, and some TODOs were added to converge on the TypeParam API.

Change-Id: I781a1d0d3fc6c11bb323123e954c106094d998ef
Reviewed-on: https://go-review.googlesource.com/c/go/+/335040
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/types/array.go [new file with mode: 0644]
src/go/types/basic.go [new file with mode: 0644]
src/go/types/chan.go [new file with mode: 0644]
src/go/types/instance.go [new file with mode: 0644]
src/go/types/map.go [new file with mode: 0644]
src/go/types/named.go [new file with mode: 0644]
src/go/types/pointer.go [new file with mode: 0644]
src/go/types/slice.go [new file with mode: 0644]
src/go/types/tuple.go [new file with mode: 0644]
src/go/types/type.go
src/go/types/typeparam.go [new file with mode: 0644]

diff --git a/src/go/types/array.go b/src/go/types/array.go
new file mode 100644 (file)
index 0000000..5b28474
--- /dev/null
@@ -0,0 +1,25 @@
+// 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
+
+// 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 }
+
+func (t *Array) Underlying() Type { return t }
+func (t *Array) String() string   { return TypeString(t, nil) }
diff --git a/src/go/types/basic.go b/src/go/types/basic.go
new file mode 100644 (file)
index 0000000..215923f
--- /dev/null
@@ -0,0 +1,82 @@
+// 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
+
+// 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 }
+
+func (t *Basic) Underlying() Type { return t }
+func (t *Basic) String() string   { return TypeString(t, nil) }
diff --git a/src/go/types/chan.go b/src/go/types/chan.go
new file mode 100644 (file)
index 0000000..1f7b72b
--- /dev/null
@@ -0,0 +1,35 @@
+// 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
+
+// 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 }
+
+func (t *Chan) Underlying() Type { return t }
+func (t *Chan) String() string   { return TypeString(t, nil) }
diff --git a/src/go/types/instance.go b/src/go/types/instance.go
new file mode 100644 (file)
index 0000000..c57a947
--- /dev/null
@@ -0,0 +1,58 @@
+// 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 "go/token"
+
+// 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 }
+
+func (t *instance) Underlying() Type { return t }
+func (t *instance) String() string   { return TypeString(t, nil) }
diff --git a/src/go/types/map.go b/src/go/types/map.go
new file mode 100644 (file)
index 0000000..01e13b2
--- /dev/null
@@ -0,0 +1,24 @@
+// 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
+
+// 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 }
+
+func (t *Map) Underlying() Type { return t }
+func (t *Map) String() string   { return TypeString(t, nil) }
diff --git a/src/go/types/named.go b/src/go/types/named.go
new file mode 100644 (file)
index 0000000..8f2e870
--- /dev/null
@@ -0,0 +1,144 @@
+// 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 "sync"
+
+// TODO(rfindley) Clean up Named struct below; specifically the fromRHS field (can we use underlying?).
+
+// 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       *Named      // original, uninstantiated type
+       fromRHS    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
+
+       resolve func(*Named) ([]*TypeName, Type, []*Func)
+       once    sync.Once
+}
+
+// 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, nil, underlying, nil, methods)
+}
+
+func (t *Named) expand() *Named {
+       if t.resolve == nil {
+               return t
+       }
+
+       t.once.Do(func() {
+               // TODO(mdempsky): Since we're passing t to resolve anyway
+               // (necessary because types2 expects the receiver type for methods
+               // on defined interface types to be the Named rather than the
+               // underlying Interface), maybe it should just handle calling
+               // SetTParams, SetUnderlying, and AddMethod instead?  Those
+               // methods would need to support reentrant calls though.  It would
+               // also make the API more future-proof towards further extensions
+               // (like SetTParams).
+
+               tparams, underlying, methods := t.resolve(t)
+
+               switch underlying.(type) {
+               case nil, *Named:
+                       panic("invalid underlying type")
+               }
+
+               t.tparams = tparams
+               t.underlying = underlying
+               t.methods = methods
+       })
+       return t
+}
+
+// newNamed is like NewNamed but with a *Checker receiver and additional orig argument.
+func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named {
+       typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods}
+       if typ.orig == nil {
+               typ.orig = typ
+       }
+       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 }
+
+// _Orig returns the original generic type an instantiated type is derived from.
+// If t is not an instantiated type, the result is t.
+func (t *Named) _Orig() *Named { return t.orig }
+
+// 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.expand().tparams }
+
+// _SetTParams sets the type parameters of the named type t.
+func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = 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 the named type t.
+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.expand().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.expand().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.expand().underlying = underlying
+}
+
+// AddMethod adds method m unless it is already in the method list.
+func (t *Named) AddMethod(m *Func) {
+       t.expand()
+       if i, _ := lookupMethod(t.methods, m.pkg, m.name); i < 0 {
+               t.methods = append(t.methods, m)
+       }
+}
+
+func (t *Named) Underlying() Type { return t.expand().underlying }
+func (t *Named) String() string   { return TypeString(t, nil) }
diff --git a/src/go/types/pointer.go b/src/go/types/pointer.go
new file mode 100644 (file)
index 0000000..6352ee5
--- /dev/null
@@ -0,0 +1,19 @@
+// 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
+
+// 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 }
+
+func (t *Pointer) Underlying() Type { return t }
+func (t *Pointer) String() string   { return TypeString(t, nil) }
diff --git a/src/go/types/slice.go b/src/go/types/slice.go
new file mode 100644 (file)
index 0000000..debdd81
--- /dev/null
@@ -0,0 +1,19 @@
+// 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
+
+// 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 }
+
+func (t *Slice) Underlying() Type { return t }
+func (t *Slice) String() string   { return TypeString(t, nil) }
diff --git a/src/go/types/tuple.go b/src/go/types/tuple.go
new file mode 100644 (file)
index 0000000..16d28bc
--- /dev/null
@@ -0,0 +1,36 @@
+// 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
+
+// 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] }
+
+func (t *Tuple) Underlying() Type { return t }
+func (t *Tuple) String() string   { return TypeString(t, nil) }
index 2adc2fa3ca97afd66220b56df02d543b609e306f..662dd859f091814db3bb0d561508f04a1c65fdc8 100644 (file)
@@ -4,12 +4,6 @@
 
 package types
 
-import (
-       "go/token"
-       "sync"
-       "sync/atomic"
-)
-
 // A Type represents a type of Go.
 // All types implement the Type interface.
 type Type interface {
@@ -22,379 +16,31 @@ type Type interface {
        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 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 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 }
-
-// TODO(rfindley) Clean up Named struct below; specifically the fromRHS field (can we use underlying?).
-
-// 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       *Named      // original, uninstantiated type
-       fromRHS    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
+// 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{}
 
-       resolve func(*Named) ([]*TypeName, Type, []*Func)
-       once    sync.Once
-}
+// theTop is the singleton top type.
+var theTop = &top{}
 
-// 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, nil, underlying, nil, methods)
-}
+func (t *top) Underlying() Type { return t }
+func (t *top) String() string   { return TypeString(t, nil) }
 
-func (t *Named) expand() *Named {
-       if t.resolve == nil {
-               return t
+// 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 *Union?
+       if n := asNamed(t); n != nil {
+               return n.under()
        }
-
-       t.once.Do(func() {
-               // TODO(mdempsky): Since we're passing t to resolve anyway
-               // (necessary because types2 expects the receiver type for methods
-               // on defined interface types to be the Named rather than the
-               // underlying Interface), maybe it should just handle calling
-               // SetTParams, SetUnderlying, and AddMethod instead?  Those
-               // methods would need to support reentrant calls though.  It would
-               // also make the API more future-proof towards further extensions
-               // (like SetTParams).
-
-               tparams, underlying, methods := t.resolve(t)
-
-               switch underlying.(type) {
-               case nil, *Named:
-                       panic("invalid underlying type")
-               }
-
-               t.tparams = tparams
-               t.underlying = underlying
-               t.methods = methods
-       })
        return t
 }
 
-func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named {
-       typ := &Named{check: check, obj: obj, orig: orig, fromRHS: underlying, underlying: underlying, tparams: tparams, methods: methods}
-       if typ.orig == nil {
-               typ.orig = typ
-       }
-       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 }
-
-// _Orig returns the original generic type an instantiated type is derived from.
-// If t is not an instantiated type, the result is t.
-func (t *Named) _Orig() *Named { return t.orig }
-
-// 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.expand().tparams }
-
-// _SetTParams sets the type parameters of the named type t.
-func (t *Named) SetTParams(tparams []*TypeName) { t.expand().tparams = 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 the named type t.
-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.expand().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.expand().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.expand().underlying = underlying
-}
-
-// AddMethod adds method m unless it is already in the method list.
-func (t *Named) AddMethod(m *Func) {
-       t.expand()
-       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, for debugging only
-       obj   *TypeName // corresponding type name
-       index int       // type parameter index in source order, starting at 0
-       bound Type      // *Named or *Interface; underlying type is always *Interface
-}
-
-// NewTypeParam returns a new TypeParam.
-func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
-       return (*Checker)(nil).newTypeParam(obj, index, bound)
-}
-
-func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
-       assert(bound != nil)
-
-       // Always increment lastID, even if it is not used.
-       id := nextID()
-       if check != nil {
-               check.nextID++
-               id = check.nextID
-       }
-
-       typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound}
-       if obj.typ == nil {
-               obj.typ = typ
-       }
-       return typ
-}
-
-func (t *TypeParam) Bound() *Interface {
-       // we may not have an interface (error reported elsewhere)
-       iface, _ := under(t.bound).(*Interface)
-       if iface == nil {
-               return &emptyInterface
-       }
-       // 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.
-       computeTypeSet(t.check, 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
@@ -424,102 +70,6 @@ func optype(typ Type) Type {
        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 }
-
-// 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{}
-
-// 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 *Pointer) Underlying() Type   { return t }
-func (t *Tuple) 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.expand().underlying }
-func (t *TypeParam) Underlying() Type { return t }
-func (t *instance) 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 *Pointer) String() string   { return TypeString(t, nil) }
-func (t *Tuple) 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 *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 *Union?
-       if n := asNamed(t); n != nil {
-               return n.under()
-       }
-       return t
-}
-
 // Converters
 //
 // A converter must only be called when a type is
diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go
new file mode 100644 (file)
index 0000000..e134508
--- /dev/null
@@ -0,0 +1,72 @@
+// 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 (
+       "go/token"
+       "sync/atomic"
+)
+
+// 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, for debugging only
+       obj   *TypeName // corresponding type name
+       index int       // type parameter index in source order, starting at 0
+       bound Type      // *Named or *Interface; underlying type is always *Interface
+}
+
+// NewTypeParam returns a new TypeParam.
+func NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
+       return (*Checker)(nil).newTypeParam(obj, index, bound)
+}
+
+// TODO(rfindley): this is factored slightly differently in types2.
+func (check *Checker) newTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
+       assert(bound != nil)
+
+       // Always increment lastID, even if it is not used.
+       id := nextID()
+       if check != nil {
+               check.nextID++
+               id = check.nextID
+       }
+
+       typ := &TypeParam{check: check, id: id, obj: obj, index: index, bound: bound}
+       if obj.typ == nil {
+               obj.typ = typ
+       }
+       return typ
+}
+
+// TODO(rfindley): types2 to has Index and SetID. Should we add them here?
+
+func (t *TypeParam) Bound() *Interface {
+       // we may not have an interface (error reported elsewhere)
+       iface, _ := under(t.bound).(*Interface)
+       if iface == nil {
+               return &emptyInterface
+       }
+       // 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.
+       computeTypeSet(t.check, pos, iface)
+       return iface
+}
+
+func (t *TypeParam) Underlying() Type { return t }
+func (t *TypeParam) String() string   { return TypeString(t, nil) }