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 :(