github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/cmd/vet/testdata/copylock_func.go (about) 1 // Copyright 2013 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // This file contains tests for the copylock checker's 6 // function declaration analysis. 7 8 package testdata 9 10 import "sync" 11 12 func OkFunc(*sync.Mutex) {} 13 func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes lock by value: sync.Mutex" 14 func BadFunc2(sync.Map) {} // ERROR "BadFunc2 passes lock by value: sync.Map contains sync.Mutex" 15 func OkRet() *sync.Mutex {} 16 func BadRet() sync.Mutex {} // Don't warn about results 17 18 var ( 19 OkClosure = func(*sync.Mutex) {} 20 BadClosure = func(sync.Mutex) {} // ERROR "func passes lock by value: sync.Mutex" 21 BadClosure2 = func(sync.Map) {} // ERROR "func passes lock by value: sync.Map contains sync.Mutex" 22 ) 23 24 type EmbeddedRWMutex struct { 25 sync.RWMutex 26 } 27 28 func (*EmbeddedRWMutex) OkMeth() {} 29 func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes lock by value: testdata.EmbeddedRWMutex" 30 func OkFunc(e *EmbeddedRWMutex) {} 31 func BadFunc(EmbeddedRWMutex) {} // ERROR "BadFunc passes lock by value: testdata.EmbeddedRWMutex" 32 func OkRet() *EmbeddedRWMutex {} 33 func BadRet() EmbeddedRWMutex {} // Don't warn about results 34 35 type FieldMutex struct { 36 s sync.Mutex 37 } 38 39 func (*FieldMutex) OkMeth() {} 40 func (FieldMutex) BadMeth() {} // ERROR "BadMeth passes lock by value: testdata.FieldMutex contains sync.Mutex" 41 func OkFunc(*FieldMutex) {} 42 func BadFunc(FieldMutex, int) {} // ERROR "BadFunc passes lock by value: testdata.FieldMutex contains sync.Mutex" 43 44 type L0 struct { 45 L1 46 } 47 48 type L1 struct { 49 l L2 50 } 51 52 type L2 struct { 53 sync.Mutex 54 } 55 56 func (*L0) Ok() {} 57 func (L0) Bad() {} // ERROR "Bad passes lock by value: testdata.L0 contains testdata.L1 contains testdata.L2" 58 59 type EmbeddedMutexPointer struct { 60 s *sync.Mutex // safe to copy this pointer 61 } 62 63 func (*EmbeddedMutexPointer) Ok() {} 64 func (EmbeddedMutexPointer) AlsoOk() {} 65 func StillOk(EmbeddedMutexPointer) {} 66 func LookinGood() EmbeddedMutexPointer {} 67 68 type EmbeddedLocker struct { 69 sync.Locker // safe to copy interface values 70 } 71 72 func (*EmbeddedLocker) Ok() {} 73 func (EmbeddedLocker) AlsoOk() {} 74 75 type CustomLock struct{} 76 77 func (*CustomLock) Lock() {} 78 func (*CustomLock) Unlock() {} 79 80 func Ok(*CustomLock) {} 81 func Bad(CustomLock) {} // ERROR "Bad passes lock by value: testdata.CustomLock" 82 83 // Passing lock values into interface function arguments 84 func FuncCallInterfaceArg(f func(a int, b interface{})) { 85 var m sync.Mutex 86 var t struct{ lock sync.Mutex } 87 88 f(1, "foo") 89 f(2, &t) 90 f(3, &sync.Mutex{}) 91 f(4, m) // ERROR "call of f copies lock value: sync.Mutex" 92 f(5, t) // ERROR "call of f copies lock value: struct.lock sync.Mutex. contains sync.Mutex" 93 var fntab []func(t) 94 fntab[0](t) // ERROR "call of fntab.0. copies lock value: struct.lock sync.Mutex. contains sync.Mutex" 95 } 96 97 // Returning lock via interface value 98 func ReturnViaInterface(x int) (int, interface{}) { 99 var m sync.Mutex 100 var t struct{ lock sync.Mutex } 101 102 switch x % 4 { 103 case 0: 104 return 0, "qwe" 105 case 1: 106 return 1, &sync.Mutex{} 107 case 2: 108 return 2, m // ERROR "return copies lock value: sync.Mutex" 109 default: 110 return 3, t // ERROR "return copies lock value: struct.lock sync.Mutex. contains sync.Mutex" 111 } 112 } 113 114 // Some cases that we don't warn about. 115 116 func AcceptedCases() { 117 x := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227) 118 x = BadRet() // function call on RHS is OK (#16227) 119 x = *OKRet() // indirection of function call on RHS is OK (#16227) 120 } 121 122 // TODO: Unfortunate cases 123 124 // Non-ideal error message: 125 // Since we're looking for Lock methods, sync.Once's underlying 126 // sync.Mutex gets called out, but without any reference to the sync.Once. 127 type LocalOnce sync.Once 128 129 func (LocalOnce) Bad() {} // ERROR "Bad passes lock by value: testdata.LocalOnce contains sync.Mutex" 130 131 // False negative: 132 // LocalMutex doesn't have a Lock method. 133 // Nevertheless, it is probably a bad idea to pass it by value. 134 type LocalMutex sync.Mutex 135 136 func (LocalMutex) Bad() {} // WANTED: An error here :(