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