github.com/euank/go@v0.0.0-20160829210321-495514729181/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 "function call copies lock value: sync.Mutex"
    90  	f(5, t) // ERROR "function call copies lock value: struct{lock sync.Mutex} contains sync.Mutex"
    91  }
    92  
    93  // Returning lock via interface value
    94  func ReturnViaInterface(x int) (int, interface{}) {
    95  	var m sync.Mutex
    96  	var t struct{ lock sync.Mutex }
    97  
    98  	switch x % 4 {
    99  	case 0:
   100  		return 0, "qwe"
   101  	case 1:
   102  		return 1, &sync.Mutex{}
   103  	case 2:
   104  		return 2, m // ERROR "return copies lock value: sync.Mutex"
   105  	default:
   106  		return 3, t // ERROR "return copies lock value: struct{lock sync.Mutex} contains sync.Mutex"
   107  	}
   108  }
   109  
   110  // Some cases that we don't warn about.
   111  
   112  func AcceptedCases() {
   113  	x := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227)
   114  	x = BadRet()           // function call on RHS is OK (#16227)
   115  	x = *OKRet()           // indirection of function call on RHS is OK (#16227)
   116  }
   117  
   118  // TODO: Unfortunate cases
   119  
   120  // Non-ideal error message:
   121  // Since we're looking for Lock methods, sync.Once's underlying
   122  // sync.Mutex gets called out, but without any reference to the sync.Once.
   123  type LocalOnce sync.Once
   124  
   125  func (LocalOnce) Bad() {} // ERROR "Bad passes lock by value: testdata.LocalOnce contains sync.Mutex"
   126  
   127  // False negative:
   128  // LocalMutex doesn't have a Lock method.
   129  // Nevertheless, it is probably a bad idea to pass it by value.
   130  type LocalMutex sync.Mutex
   131  
   132  func (LocalMutex) Bad() {} // WANTED: An error here :(