]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/vet: check sync.* types' copying
authorAliaksandr Valialkin <valyala@gmail.com>
Thu, 14 Apr 2016 21:33:28 +0000 (00:33 +0300)
committerIan Lance Taylor <iant@golang.org>
Fri, 6 May 2016 16:43:51 +0000 (16:43 +0000)
Embed noLock struct into the following types, so `go vet -copylocks` catches
their copying additionally to types containing sync.Mutex:
  - sync.Cond
  - sync.WaitGroup
  - sync.Pool
  - atomic.Value

Fixes #14582

Change-Id: Icb543ef5ad10524ad239a15eec8a9b334b0e0660
Reviewed-on: https://go-review.googlesource.com/22015
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/cmd/vet/testdata/copylock.go
src/sync/atomic/value.go
src/sync/cond.go
src/sync/mutex.go
src/sync/pool.go
src/sync/rwmutex.go
src/sync/waitgroup.go

index cf56802cdbb249a05d01b9457015c12e62b687bb..d49f46862758716e77669755a43f798b94926a18 100644 (file)
@@ -1,6 +1,9 @@
 package testdata
 
-import "sync"
+import (
+       "sync"
+       "sync/atomic"
+)
 
 func OkFunc() {
        var x *sync.Mutex
@@ -66,3 +69,72 @@ func BadFunc() {
        new := func(interface{}) {}
        new(t) // ERROR "function call copies lock value: testdata.Tlock contains sync.Once contains sync.Mutex"
 }
+
+// SyncTypesCheck checks copying of sync.* types except sync.Mutex
+func SyncTypesCheck() {
+       // sync.RWMutex copying
+       var rwmuX sync.RWMutex
+       var rwmuXX = sync.RWMutex{}
+       rwmuX1 := new(sync.RWMutex)
+       rwmuY := rwmuX     // ERROR "assignment copies lock value to rwmuY: sync.RWMutex"
+       rwmuY = rwmuX      // ERROR "assignment copies lock value to rwmuY: sync.RWMutex"
+       var rwmuYY = rwmuX // ERROR "variable declaration copies lock value to rwmuYY: sync.RWMutex"
+       rwmuP := &rwmuX
+       rwmuZ := &sync.RWMutex{}
+
+       // sync.Cond copying
+       var condX sync.Cond
+       var condXX = sync.Cond{}
+       condX1 := new(sync.Cond)
+       condY := condX     // ERROR "assignment copies lock value to condY: sync.Cond contains sync.noCopy"
+       condY = condX      // ERROR "assignment copies lock value to condY: sync.Cond contains sync.noCopy"
+       var condYY = condX // ERROR "variable declaration copies lock value to condYY: sync.Cond contains sync.noCopy"
+       condP := &condX
+       condZ := &sync.Cond{
+               L: &sync.Mutex{},
+       }
+       condZ = sync.NewCond(&sync.Mutex{})
+
+       // sync.WaitGroup copying
+       var wgX sync.WaitGroup
+       var wgXX = sync.WaitGroup{}
+       wgX1 := new(sync.WaitGroup)
+       wgY := wgX     // ERROR "assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy"
+       wgY = wgX      // ERROR "assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy"
+       var wgYY = wgX // ERROR "variable declaration copies lock value to wgYY: sync.WaitGroup contains sync.noCopy"
+       wgP := &wgX
+       wgZ := &sync.WaitGroup{}
+
+       // sync.Pool copying
+       var poolX sync.Pool
+       var poolXX = sync.Pool{}
+       poolX1 := new(sync.Pool)
+       poolY := poolX     // ERROR "assignment copies lock value to poolY: sync.Pool contains sync.noCopy"
+       poolY = poolX      // ERROR "assignment copies lock value to poolY: sync.Pool contains sync.noCopy"
+       var poolYY = poolX // ERROR "variable declaration copies lock value to poolYY: sync.Pool contains sync.noCopy"
+       poolP := &poolX
+       poolZ := &sync.Pool{}
+
+       // sync.Once copying
+       var onceX sync.Once
+       var onceXX = sync.Once{}
+       onceX1 := new(sync.Once)
+       onceY := onceX     // ERROR "assignment copies lock value to onceY: sync.Once contains sync.Mutex"
+       onceY = onceX      // ERROR "assignment copies lock value to onceY: sync.Once contains sync.Mutex"
+       var onceYY = onceX // ERROR "variable declaration copies lock value to onceYY: sync.Once contains sync.Mutex"
+       onceP := &onceX
+       onceZ := &sync.Once{}
+}
+
+// AtomicTypesCheck checks copying of sync/atomic types
+func AtomicTypesCheck() {
+       // atomic.Value copying
+       var vX atomic.Value
+       var vXX = atomic.Value{}
+       vX1 := new(atomic.Value)
+       vY := vX     // ERROR "assignment copies lock value to vY: sync/atomic.Value contains sync/atomic.noCopy"
+       vY = vX      // ERROR "assignment copies lock value to vY: sync/atomic.Value contains sync/atomic.noCopy"
+       var vYY = vX // ERROR "variable declaration copies lock value to vYY: sync/atomic.Value contains sync/atomic.noCopy"
+       vP := &vX
+       vZ := &atomic.Value{}
+}
index ab3aa11285478f214bad966f018dee3ab8c2bc1a..30abf726344e96f3955df6101fbdc468ab44a3d9 100644 (file)
@@ -12,7 +12,11 @@ import (
 // Values can be created as part of other data structures.
 // The zero value for a Value returns nil from Load.
 // Once Store has been called, a Value must not be copied.
+//
+// A Value must not be copied after first use.
 type Value struct {
+       noCopy noCopy
+
        v interface{}
 }
 
@@ -83,3 +87,13 @@ func (v *Value) Store(x interface{}) {
 // Disable/enable preemption, implemented in runtime.
 func runtime_procPin()
 func runtime_procUnpin()
+
+// noCopy may be embedded into structs which must not be copied
+// after the first use.
+//
+// See https://github.com/golang/go/issues/8005#issuecomment-190753527
+// for details.
+type noCopy struct{}
+
+// Lock is a no-op used by -copylocks checker from `go vet`.
+func (*noCopy) Lock() {}
index f711c39da2d856c580dbb4494c3f031dc2440382..c070d9d84ef9e5ba39ecca820e747028d55c77ad 100644 (file)
@@ -20,6 +20,8 @@ import (
 // A Cond can be created as part of other structures.
 // A Cond must not be copied after first use.
 type Cond struct {
+       noCopy noCopy
+
        // L is held while observing or changing the condition
        L Locker
 
@@ -84,3 +86,13 @@ func (c *copyChecker) check() {
                panic("sync.Cond is copied")
        }
 }
+
+// noCopy may be embedded into structs which must not be copied
+// after the first use.
+//
+// See https://github.com/golang/go/issues/8005#issuecomment-190753527
+// for details.
+type noCopy struct{}
+
+// Lock is a no-op used by -copylocks checker from `go vet`.
+func (*noCopy) Lock() {}
index 78b115cf5a197279717838c4a24138b815cb1669..90892793f0a99cfa112e3f7f386cc24876aef695 100644 (file)
@@ -19,6 +19,8 @@ import (
 // A Mutex is a mutual exclusion lock.
 // Mutexes can be created as part of other structures;
 // the zero value for a Mutex is an unlocked mutex.
+//
+// A Mutex must not be copied after first use.
 type Mutex struct {
        state int32
        sema  uint32
index 2acf505f3c96b90da8c60ddded56540bc4638239..bf29d88c5cb6ccfb926d8735c934c482c54d3e2c 100644 (file)
@@ -40,7 +40,10 @@ import (
 // that scenario. It is more efficient to have such objects implement their own
 // free list.
 //
+// A Pool must not be copied after first use.
 type Pool struct {
+       noCopy noCopy
+
        local     unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
        localSize uintptr        // size of the local array
 
index 9fc6e3bd2c5151ec27cac36295962123e96a0716..455d412330034ed89b9feafea451e60b4bc86858 100644 (file)
@@ -16,6 +16,8 @@ import (
 // RWMutexes can be created as part of other
 // structures; the zero value for a RWMutex is
 // an unlocked mutex.
+//
+// An RWMutex must not be copied after first use.
 type RWMutex struct {
        w           Mutex  // held if there are pending writers
        writerSem   uint32 // semaphore for writers to wait for completing readers
index 029e6077cde7144b321cd1c8d90fe339cd26a4fc..b386e1fec2b61ab68c0e0cafc5a9012e6ec7e7fe 100644 (file)
@@ -15,7 +15,11 @@ import (
 // goroutines to wait for. Then each of the goroutines
 // runs and calls Done when finished. At the same time,
 // Wait can be used to block until all goroutines have finished.
+//
+// A WaitGroup must not be copied after first use.
 type WaitGroup struct {
+       noCopy noCopy
+
        // 64-bit value: high 32 bits are counter, low 32 bits are waiter count.
        // 64-bit atomic operations require 64-bit alignment, but 32-bit
        // compilers do not ensure it. So we allocate 12 bytes and then use