aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2021-07-07 21:38:49 -0700
committerRobert Griesemer <gri@golang.org>2021-07-09 17:36:57 +0000
commit69d945fc6e80475c163f96ba86fe716e77bb0104 (patch)
treef299a8ca8176a672a539979c846d2951e0c1d1ad /src
parent04acb8a7b9fc0212687cc25aa2598d12f6aceb74 (diff)
downloadgo-69d945fc6e80475c163f96ba86fe716e77bb0104.tar.gz
go-69d945fc6e80475c163f96ba86fe716e77bb0104.zip
[dev.typeparams] cmd/compile/internal/types2: use scope numbers to identify local types
Rather than using a local types' position information, use the type name's scope numbers to uniquely identify the type from others with the same name. We use scope numbers rather than indices (with number-1 == index) to preserve the invariant that the zero value for a scope is a ready to use empty scope. Using scope numbers turned out to be fairly simple after all and provides a reasonably stable identification which will make debugging simpler. A scope number series may be a bit longer than a unique ID for each type name but local types should be reasonably rare. Also did a minor cleanup in universe.go to ensure Named.orig is set up correctly (there's still an open TODO but with a work-around). Change-Id: I73935fa9bd960809fd5c95fe8b8a535c313cfc8f Reviewed-on: https://go-review.googlesource.com/c/go/+/333192 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/types2/instance.go2
-rw-r--r--src/cmd/compile/internal/types2/scope.go4
-rw-r--r--src/cmd/compile/internal/types2/sizeof_test.go2
-rw-r--r--src/cmd/compile/internal/types2/subst.go2
-rw-r--r--src/cmd/compile/internal/types2/typestring.go29
-rw-r--r--src/cmd/compile/internal/types2/universe.go12
6 files changed, 30 insertions, 21 deletions
diff --git a/src/cmd/compile/internal/types2/instance.go b/src/cmd/compile/internal/types2/instance.go
index 9d6097e874..b133fd1e65 100644
--- a/src/cmd/compile/internal/types2/instance.go
+++ b/src/cmd/compile/internal/types2/instance.go
@@ -16,7 +16,7 @@ type instance struct {
base *Named // parameterized type to be instantiated
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
+ value Type // base[targs...] after instantiation or Typ[Invalid]; nil if not yet set
}
// expand returns the instantiated (= expanded) type of t.
diff --git a/src/cmd/compile/internal/types2/scope.go b/src/cmd/compile/internal/types2/scope.go
index 2f1814a631..095875d94b 100644
--- a/src/cmd/compile/internal/types2/scope.go
+++ b/src/cmd/compile/internal/types2/scope.go
@@ -23,6 +23,7 @@ import (
type Scope struct {
parent *Scope
children []*Scope
+ number int // parent.children[number-1] is this scope; 0 if there is no parent
elems map[string]Object // lazily allocated
pos, end syntax.Pos // scope extent; may be invalid
comment string // for debugging only
@@ -32,10 +33,11 @@ type Scope struct {
// NewScope returns a new, empty scope contained in the given parent
// scope, if any. The comment is for debugging only.
func NewScope(parent *Scope, pos, end syntax.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!
if parent != nil && parent != Universe {
parent.children = append(parent.children, s)
+ s.number = len(parent.children)
}
return s
}
diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go
index 0b1f7dacad..a51d0c43d5 100644
--- a/src/cmd/compile/internal/types2/sizeof_test.go
+++ b/src/cmd/compile/internal/types2/sizeof_test.go
@@ -47,7 +47,7 @@ func TestSizeof(t *testing.T) {
{Nil{}, 56, 88},
// Misc
- {Scope{}, 56, 96},
+ {Scope{}, 60, 104},
{Package{}, 40, 80},
{TypeSet{}, 20, 40},
}
diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go
index 7b4796fa2e..59efe8a045 100644
--- a/src/cmd/compile/internal/types2/subst.go
+++ b/src/cmd/compile/internal/types2/subst.go
@@ -422,8 +422,6 @@ func (subst *subster) typ(typ Type) Type {
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 {
assert(instanceHashing == 0)
instanceHashing++
diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go
index f63a23c98c..44099133a0 100644
--- a/src/cmd/compile/internal/types2/typestring.go
+++ b/src/cmd/compile/internal/types2/typestring.go
@@ -363,22 +363,27 @@ func writeTypeName(buf *bytes.Buffer, obj *TypeName, qf Qualifier) {
buf.WriteString(obj.name)
if instanceHashing != 0 {
- // For local defined types, use the (original!) TypeName's position
- // to disambiguate. This is overkill, and could probably instead
- // 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.
+ // For local defined types, use the (original!) TypeName's scope
+ // numbers to disambiguate.
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 {
typ = typ.orig
}
- if orig := typ.obj; orig.pkg != nil && orig.parent != orig.pkg.scope {
- fmt.Fprintf(buf, "@%q", orig.pos)
- }
+ writeScopeNumbers(buf, typ.obj.parent)
+ }
+}
+
+// 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)
}
}
diff --git a/src/cmd/compile/internal/types2/universe.go b/src/cmd/compile/internal/types2/universe.go
index c9b53bac92..d328b13a8e 100644
--- a/src/cmd/compile/internal/types2/universe.go
+++ b/src/cmd/compile/internal/types2/universe.go
@@ -86,21 +86,25 @@ func defPredeclaredTypes() {
// type error interface{ Error() string }
{
+ obj := NewTypeName(nopos, nil, "error", nil)
+ obj.setColor(black)
res := NewVar(nopos, nil, "", Typ[String])
sig := NewSignature(nil, nil, NewTuple(res), false)
err := NewFunc(nopos, nil, "Error", sig)
- typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)}
+ typ := NewNamed(obj, NewInterfaceType([]*Func{err}, nil), nil)
sig.recv = NewVar(nopos, nil, "", typ)
- def(NewTypeName(nopos, nil, "error", typ))
+ def(obj)
}
// type comparable interface{ ==() }
{
+ obj := NewTypeName(nopos, nil, "comparable", nil)
+ obj.setColor(black)
sig := NewSignature(nil, nil, nil, false)
eql := NewFunc(nopos, nil, "==", sig)
- typ := &Named{underlying: NewInterfaceType([]*Func{eql}, nil)}
+ typ := NewNamed(obj, NewInterfaceType([]*Func{eql}, nil), nil)
sig.recv = NewVar(nopos, nil, "", typ)
- def(NewTypeName(nopos, nil, "comparable", typ))
+ def(obj)
}
}