github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/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 {} // ERROR "BadRet returns lock by value: sync.Mutex"
    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    {} // ERROR "BadRet returns lock by value: testdata.EmbeddedRWMutex"
    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  // TODO: Unfortunate cases
   111  
   112  // Non-ideal error message:
   113  // Since we're looking for Lock methods, sync.Once's underlying
   114  // sync.Mutex gets called out, but without any reference to the sync.Once.
   115  type LocalOnce sync.Once
   116  
   117  func (LocalOnce) Bad() {} // ERROR "Bad passes lock by value: testdata.LocalOnce contains sync.Mutex"
   118  
   119  // False negative:
   120  // LocalMutex doesn't have a Lock method.
   121  // Nevertheless, it is probably a bad idea to pass it by value.
   122  type LocalMutex sync.Mutex
   123  
   124  func (LocalMutex) Bad() {} // WANTED: An error here :(