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