mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00:00
[dev.typeparams] go/types: add Named.SetTParams and Named.Orig methods
This is a port of CL 309832 to go/types, adjusted to not export the new API and to amend TestSizeof. Change-Id: I67efd3ba9b921c8431528eba1cd88ec1f41898bb Reviewed-on: https://go-review.googlesource.com/c/go/+/324755 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>
This commit is contained in:
parent
991dca0112
commit
1395952075
|
@ -333,7 +333,7 @@ func (check *Checker) validType(typ Type, path []Object) typeInfo {
|
||||||
switch t.info {
|
switch t.info {
|
||||||
case unknown:
|
case unknown:
|
||||||
t.info = marked
|
t.info = marked
|
||||||
t.info = check.validType(t.orig, append(path, t.obj)) // only types of current package added to path
|
t.info = check.validType(t.fromRHS, append(path, t.obj)) // only types of current package added to path
|
||||||
case marked:
|
case marked:
|
||||||
// cycle detected
|
// cycle detected
|
||||||
for i, tn := range path {
|
for i, tn := range path {
|
||||||
|
@ -692,9 +692,8 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
|
||||||
} else {
|
} else {
|
||||||
// defined type declaration
|
// defined type declaration
|
||||||
|
|
||||||
named := check.newNamed(obj, nil, nil)
|
named := check.newNamed(obj, nil, nil, nil, nil)
|
||||||
def.setUnderlying(named)
|
def.setUnderlying(named)
|
||||||
obj.typ = named // make sure recursive type declarations terminate
|
|
||||||
|
|
||||||
if tparams := typeparams.Get(tdecl); tparams != nil {
|
if tparams := typeparams.Get(tdecl); tparams != nil {
|
||||||
check.openScope(tdecl, "type parameters")
|
check.openScope(tdecl, "type parameters")
|
||||||
|
@ -703,7 +702,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine underlying type of named
|
// determine underlying type of named
|
||||||
named.orig = check.definedType(tdecl.Type, named)
|
named.fromRHS = check.definedType(tdecl.Type, named)
|
||||||
|
|
||||||
// The underlying type of named may be itself a named type that is
|
// The underlying type of named may be itself a named type that is
|
||||||
// incomplete:
|
// incomplete:
|
||||||
|
@ -718,7 +717,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
|
||||||
// and which has as its underlying type the named type B.
|
// and which has as its underlying type the named type B.
|
||||||
// Determine the (final, unnamed) underlying type by resolving
|
// Determine the (final, unnamed) underlying type by resolving
|
||||||
// any forward chain.
|
// any forward chain.
|
||||||
// TODO(gri) Investigate if we can just use named.origin here
|
// TODO(gri) Investigate if we can just use named.fromRHS here
|
||||||
// and rely on lazy computation of the underlying type.
|
// and rely on lazy computation of the underlying type.
|
||||||
named.underlying = under(named)
|
named.underlying = under(named)
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,8 +138,8 @@ func (s sanitizer) typ(typ Type) Type {
|
||||||
if debug && t.check != nil {
|
if debug && t.check != nil {
|
||||||
panic("internal error: Named.check != nil")
|
panic("internal error: Named.check != nil")
|
||||||
}
|
}
|
||||||
if orig := s.typ(t.orig); orig != t.orig {
|
if orig := s.typ(t.fromRHS); orig != t.fromRHS {
|
||||||
t.orig = orig
|
t.fromRHS = orig
|
||||||
}
|
}
|
||||||
if under := s.typ(t.underlying); under != t.underlying {
|
if under := s.typ(t.underlying); under != t.underlying {
|
||||||
t.underlying = under
|
t.underlying = under
|
||||||
|
|
|
@ -30,7 +30,7 @@ func TestSizeof(t *testing.T) {
|
||||||
{Interface{}, 60, 120},
|
{Interface{}, 60, 120},
|
||||||
{Map{}, 16, 32},
|
{Map{}, 16, 32},
|
||||||
{Chan{}, 12, 24},
|
{Chan{}, 12, 24},
|
||||||
{Named{}, 64, 128},
|
{Named{}, 68, 136},
|
||||||
{_TypeParam{}, 28, 48},
|
{_TypeParam{}, 28, 48},
|
||||||
{instance{}, 44, 88},
|
{instance{}, 44, 88},
|
||||||
{bottom{}, 0, 0},
|
{bottom{}, 0, 0},
|
||||||
|
|
|
@ -396,8 +396,7 @@ func (subst *subster) typ(typ Type) Type {
|
||||||
|
|
||||||
// create a new named type and populate caches to avoid endless recursion
|
// create a new named type and populate caches to avoid endless recursion
|
||||||
tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil)
|
tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil)
|
||||||
named := subst.check.newNamed(tname, t.underlying, t.methods) // method signatures are updated lazily
|
named := subst.check.newNamed(tname, t, t.underlying, t.tparams, t.methods) // method signatures are updated lazily
|
||||||
named.tparams = t.tparams // new type is still parameterized
|
|
||||||
named.targs = newTargs
|
named.targs = newTargs
|
||||||
if subst.check != nil {
|
if subst.check != nil {
|
||||||
subst.check.typMap[h] = named
|
subst.check.typMap[h] = named
|
||||||
|
@ -407,7 +406,7 @@ func (subst *subster) typ(typ Type) Type {
|
||||||
// do the substitution
|
// do the substitution
|
||||||
dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs)
|
dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs)
|
||||||
named.underlying = subst.typOrNil(t.underlying)
|
named.underlying = subst.typOrNil(t.underlying)
|
||||||
named.orig = named.underlying // for cycle detection (Checker.validType)
|
named.fromRHS = named.underlying // for cycle detection (Checker.validType)
|
||||||
|
|
||||||
return named
|
return named
|
||||||
|
|
||||||
|
|
|
@ -642,12 +642,15 @@ func (c *Chan) Dir() ChanDir { return c.dir }
|
||||||
// Elem returns the element type of channel c.
|
// Elem returns the element type of channel c.
|
||||||
func (c *Chan) Elem() Type { return c.elem }
|
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.
|
// A Named represents a named (defined) type.
|
||||||
type Named struct {
|
type Named struct {
|
||||||
check *Checker // for Named.under implementation; nilled once under has been called
|
check *Checker // for Named.under implementation; nilled once under has been called
|
||||||
info typeInfo // for cycle detection
|
info typeInfo // for cycle detection
|
||||||
obj *TypeName // corresponding declared object
|
obj *TypeName // corresponding declared object
|
||||||
orig Type // type (on RHS of declaration) this *Named type is derived of (for cycle reporting)
|
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
|
underlying Type // possibly a *Named during setup; never a *Named once set up completely
|
||||||
tparams []*TypeName // type parameters, or nil
|
tparams []*TypeName // type parameters, or nil
|
||||||
targs []Type // type arguments (after instantiation), or nil
|
targs []Type // type arguments (after instantiation), or nil
|
||||||
|
@ -661,11 +664,14 @@ func NewNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
|
||||||
if _, ok := underlying.(*Named); ok {
|
if _, ok := underlying.(*Named); ok {
|
||||||
panic("types.NewNamed: underlying type must not be *Named")
|
panic("types.NewNamed: underlying type must not be *Named")
|
||||||
}
|
}
|
||||||
return (*Checker)(nil).newNamed(obj, underlying, methods)
|
return (*Checker)(nil).newNamed(obj, nil, underlying, nil, methods)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func) *Named {
|
func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tparams []*TypeName, methods []*Func) *Named {
|
||||||
typ := &Named{check: check, obj: obj, orig: underlying, underlying: underlying, methods: methods}
|
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 {
|
if obj.typ == nil {
|
||||||
obj.typ = typ
|
obj.typ = typ
|
||||||
}
|
}
|
||||||
|
@ -692,6 +698,10 @@ func (check *Checker) newNamed(obj *TypeName, underlying Type, methods []*Func)
|
||||||
// Obj returns the type name for the named type t.
|
// Obj returns the type name for the named type t.
|
||||||
func (t *Named) Obj() *TypeName { return t.obj }
|
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
|
// TODO(gri) Come up with a better representation and API to distinguish
|
||||||
// between parameterized instantiated and non-instantiated types.
|
// between parameterized instantiated and non-instantiated types.
|
||||||
|
|
||||||
|
@ -699,10 +709,13 @@ func (t *Named) Obj() *TypeName { return t.obj }
|
||||||
// The result is non-nil for an (originally) parameterized type even if it is instantiated.
|
// The result is non-nil for an (originally) parameterized type even if it is instantiated.
|
||||||
func (t *Named) _TParams() []*TypeName { return t.tparams }
|
func (t *Named) _TParams() []*TypeName { return t.tparams }
|
||||||
|
|
||||||
|
// _SetTParams sets the type parameters of the named type t.
|
||||||
|
func (t *Named) _SetTParams(tparams []*TypeName) { t.tparams = tparams }
|
||||||
|
|
||||||
// _TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated.
|
// _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 }
|
func (t *Named) _TArgs() []Type { return t.targs }
|
||||||
|
|
||||||
// _SetTArgs sets the type arguments of Named.
|
// SetTArgs sets the type arguments of the named type t.
|
||||||
func (t *Named) _SetTArgs(args []Type) { t.targs = args }
|
func (t *Named) _SetTArgs(args []Type) { t.targs = args }
|
||||||
|
|
||||||
// NumMethods returns the number of explicit methods whose receiver is named type t.
|
// NumMethods returns the number of explicit methods whose receiver is named type t.
|
||||||
|
@ -741,9 +754,9 @@ func nextID() uint64 { return uint64(atomic.AddUint32(&lastID, 1)) }
|
||||||
// A _TypeParam represents a type parameter type.
|
// A _TypeParam represents a type parameter type.
|
||||||
type _TypeParam struct {
|
type _TypeParam struct {
|
||||||
check *Checker // for lazy type bound completion
|
check *Checker // for lazy type bound completion
|
||||||
id uint64 // unique id
|
id uint64 // unique id, for debugging only
|
||||||
obj *TypeName // corresponding type name
|
obj *TypeName // corresponding type name
|
||||||
index int // parameter index
|
index int // type parameter index in source order, starting at 0
|
||||||
bound Type // *Named or *Interface; underlying type is always *Interface
|
bound Type // *Named or *Interface; underlying type is always *Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue