mirror of
https://github.com/golang/go
synced 2024-09-05 07:54:46 +00:00
[dev.typeparams] go/types: use scope numbers to identify local types
This is a port of CL 333192 to go/types. Change-Id: I12fd6b682d40c4d30b9ac0e87c463843cf5030d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/335114 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
ccf95f17dd
commit
c7c13ae432
|
@ -16,7 +16,7 @@ type instance struct {
|
||||||
base *Named // parameterized type to be instantiated
|
base *Named // parameterized type to be instantiated
|
||||||
targs []Type // type arguments
|
targs []Type // type arguments
|
||||||
poslist []token.Pos // position of each targ; for error reporting only
|
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
|
value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set
|
||||||
}
|
}
|
||||||
|
|
||||||
// expand returns the instantiated (= expanded) type of t.
|
// expand returns the instantiated (= expanded) type of t.
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
type Scope struct {
|
type Scope struct {
|
||||||
parent *Scope
|
parent *Scope
|
||||||
children []*Scope
|
children []*Scope
|
||||||
|
number int // parent.children[number-1] is this scope; 0 if there is no parent
|
||||||
elems map[string]Object // lazily allocated
|
elems map[string]Object // lazily allocated
|
||||||
pos, end token.Pos // scope extent; may be invalid
|
pos, end token.Pos // scope extent; may be invalid
|
||||||
comment string // for debugging only
|
comment string // for debugging only
|
||||||
|
@ -32,10 +33,11 @@ type Scope struct {
|
||||||
// NewScope returns a new, empty scope contained in the given parent
|
// NewScope returns a new, empty scope contained in the given parent
|
||||||
// scope, if any. The comment is for debugging only.
|
// scope, if any. The comment is for debugging only.
|
||||||
func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope {
|
func NewScope(parent *Scope, pos, end token.Pos, comment string) *Scope {
|
||||||
s := &Scope{parent, nil, nil, pos, end, comment, false}
|
s := &Scope{parent, nil, 0, nil, pos, end, comment, false}
|
||||||
// don't add children to Universe scope!
|
// don't add children to Universe scope!
|
||||||
if parent != nil && parent != Universe {
|
if parent != nil && parent != Universe {
|
||||||
parent.children = append(parent.children, s)
|
parent.children = append(parent.children, s)
|
||||||
|
s.number = len(parent.children)
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func TestSizeof(t *testing.T) {
|
||||||
{Nil{}, 40, 72},
|
{Nil{}, 40, 72},
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
{Scope{}, 40, 80},
|
{Scope{}, 44, 88},
|
||||||
{Package{}, 40, 80},
|
{Package{}, 40, 80},
|
||||||
{TypeSet{}, 20, 40},
|
{TypeSet{}, 20, 40},
|
||||||
}
|
}
|
||||||
|
|
|
@ -430,8 +430,6 @@ func (subst *subster) typ(typ Type) Type {
|
||||||
|
|
||||||
var instanceHashing = 0
|
var instanceHashing = 0
|
||||||
|
|
||||||
// TODO(gri) Eventually, this should be more sophisticated.
|
|
||||||
// It won't work correctly for locally declared types.
|
|
||||||
func instantiatedHash(typ *Named, targs []Type) string {
|
func instantiatedHash(typ *Named, targs []Type) string {
|
||||||
assert(instanceHashing == 0)
|
assert(instanceHashing == 0)
|
||||||
instanceHashing++
|
instanceHashing++
|
||||||
|
|
|
@ -358,22 +358,27 @@ func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) {
|
||||||
buf.WriteString(obj.name)
|
buf.WriteString(obj.name)
|
||||||
|
|
||||||
if instanceHashing != 0 {
|
if instanceHashing != 0 {
|
||||||
// For local defined types, use the (original!) TypeName's position
|
// For local defined types, use the (original!) TypeName's scope
|
||||||
// to disambiguate. This is overkill, and could probably instead
|
// numbers to disambiguate.
|
||||||
// just be the pointer value (if we assume a non-moving GC) or
|
|
||||||
// a unique ID (like cmd/compile uses). But this works for now,
|
|
||||||
// and is convenient for debugging.
|
|
||||||
|
|
||||||
// TODO(mdempsky): I still don't fully understand why typ.orig.orig
|
|
||||||
// can differ from typ.orig, or whether looping more than twice is
|
|
||||||
// ever necessary.
|
|
||||||
typ := obj.typ.(*Named)
|
typ := obj.typ.(*Named)
|
||||||
|
// TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes
|
||||||
|
// and whether the loop can iterate more than twice.
|
||||||
|
// (It seems somehow connected to instance types.)
|
||||||
for typ.orig != typ {
|
for typ.orig != typ {
|
||||||
typ = typ.orig
|
typ = typ.orig
|
||||||
}
|
}
|
||||||
if orig := typ.obj; orig.pkg != nil && orig.parent != orig.pkg.scope {
|
writeScopeNumbers(buf, typ.obj.parent)
|
||||||
fmt.Fprintf(buf, "@%q", orig.pos)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeScopeNumbers writes the number sequence for this scope to buf
|
||||||
|
// in the form ".i.j.k" where i, j, k, etc. stand for scope numbers.
|
||||||
|
// If a scope is nil or has no parent (such as a package scope), nothing
|
||||||
|
// is written.
|
||||||
|
func writeScopeNumbers(buf *bytes.Buffer, s *Scope) {
|
||||||
|
if s != nil && s.number > 0 {
|
||||||
|
writeScopeNumbers(buf, s.parent)
|
||||||
|
fmt.Fprintf(buf, ".%d", s.number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,21 +87,25 @@ func defPredeclaredTypes() {
|
||||||
|
|
||||||
// type error interface{ Error() string }
|
// type error interface{ Error() string }
|
||||||
{
|
{
|
||||||
|
obj := NewTypeName(token.NoPos, nil, "error", nil)
|
||||||
|
obj.setColor(black)
|
||||||
res := NewVar(token.NoPos, nil, "", Typ[String])
|
res := NewVar(token.NoPos, nil, "", Typ[String])
|
||||||
sig := NewSignature(nil, nil, NewTuple(res), false)
|
sig := NewSignature(nil, nil, NewTuple(res), false)
|
||||||
err := NewFunc(token.NoPos, nil, "Error", sig)
|
err := NewFunc(token.NoPos, nil, "Error", sig)
|
||||||
typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)}
|
typ := NewNamed(obj, NewInterfaceType([]*Func{err}, nil), nil)
|
||||||
sig.recv = NewVar(token.NoPos, nil, "", typ)
|
sig.recv = NewVar(token.NoPos, nil, "", typ)
|
||||||
def(NewTypeName(token.NoPos, nil, "error", typ))
|
def(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// type comparable interface{ ==() }
|
// type comparable interface{ ==() }
|
||||||
{
|
{
|
||||||
|
obj := NewTypeName(token.NoPos, nil, "comparable", nil)
|
||||||
|
obj.setColor(black)
|
||||||
sig := NewSignature(nil, nil, nil, false)
|
sig := NewSignature(nil, nil, nil, false)
|
||||||
eql := NewFunc(token.NoPos, nil, "==", sig)
|
eql := NewFunc(token.NoPos, nil, "==", sig)
|
||||||
typ := &Named{underlying: NewInterfaceType([]*Func{eql}, nil)}
|
typ := NewNamed(obj, NewInterfaceType([]*Func{eql}, nil), nil)
|
||||||
sig.recv = NewVar(token.NoPos, nil, "", typ)
|
sig.recv = NewVar(token.NoPos, nil, "", typ)
|
||||||
def(NewTypeName(token.NoPos, nil, "comparable", typ))
|
def(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue