]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: use a global atomic counter for type parameter ids
authorRobert Griesemer <gri@golang.org>
Tue, 13 Apr 2021 23:33:42 +0000 (16:33 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 14 Apr 2021 00:25:33 +0000 (00:25 +0000)
This avoids a dependency on a *Checker when we create type parameters
outside the type checker proper, e.g. in an importer. There may be
better solutions but this does the trick for now.

Change-Id: Icf22c934970cb04c88c2729555ae6a79ef5a2245
Reviewed-on: https://go-review.googlesource.com/c/go/+/309830
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/api_test.go
src/cmd/compile/internal/types2/check.go
src/cmd/compile/internal/types2/type.go
src/cmd/compile/internal/types2/types_test.go

index 9d31fef69b34bf272e6e849143f0e9bde0e9c0be..b3b16131ceb39480d96ac431f825a22709126e5f 100644 (file)
@@ -349,6 +349,7 @@ func TestTypesInfo(t *testing.T) {
        }
 
        for _, test := range tests {
+               ResetId() // avoid renumbering of type parameter ids when adding tests
                info := Info{Types: make(map[syntax.Expr]TypeAndValue)}
                var name string
                if strings.HasPrefix(test.src, brokenPkg) {
index 7703d98fa6694b0dce56c121387e5d496de2e822..66637459e780518d2945578fa5bada7636fb59f3 100644 (file)
@@ -83,7 +83,6 @@ type Checker struct {
        pkg  *Package
        *Info
        version version                     // accepted language version
-       nextId  uint64                      // unique Id for type parameters (first valid Id is 1)
        objMap  map[Object]*declInfo        // maps package-level objects and (non-interface) methods to declaration info
        impMap  map[importKey]*Package      // maps (import path, source directory) to (complete or fake) package
        posMap  map[*Interface][]syntax.Pos // maps interface types to lists of embedded interface positions
@@ -178,7 +177,6 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
                pkg:     pkg,
                Info:    info,
                version: version,
-               nextId:  1,
                objMap:  make(map[Object]*declInfo),
                impMap:  make(map[importKey]*Package),
                posMap:  make(map[*Interface][]syntax.Pos),
index 277ed0602676c6d47811c09d00e42833e421f59c..daa00ddd3ae0317be913e276d35011d22c1419ab 100644 (file)
@@ -7,6 +7,7 @@ package types2
 import (
        "cmd/compile/internal/syntax"
        "fmt"
+       "sync/atomic"
 )
 
 // A Type represents a type of Go.
@@ -718,6 +719,15 @@ func (t *Named) AddMethod(m *Func) {
        }
 }
 
+// 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
@@ -733,8 +743,7 @@ func (t *TypeParam) Obj() *TypeName { return t.obj }
 // NewTypeParam returns a new TypeParam.
 func (check *Checker) NewTypeParam(obj *TypeName, index int, bound Type) *TypeParam {
        assert(bound != nil)
-       typ := &TypeParam{check: check, id: check.nextId, obj: obj, index: index, bound: bound}
-       check.nextId++
+       typ := &TypeParam{check: check, id: nextId(), obj: obj, index: index, bound: bound}
        if obj.typ == nil {
                obj.typ = typ
        }
index 11dca0b53de86421a3a34f5ae505d90dca61d3f2..096402148d38ad481815ad916e00664dfd0419c2 100644 (file)
@@ -4,6 +4,14 @@
 
 package types2
 
+import "sync/atomic"
+
 func init() {
        acceptMethodTypeParams = true
 }
+
+// Upon calling ResetId, nextId starts with 1 again.
+// It may be called concurrently. This is only needed
+// for tests where we may want to have a consistent
+// numbering for each individual test case.
+func ResetId() { atomic.StoreUint32(&lastId, 0) }