...
Run Format

Source file src/cmd/vet/testdata/copylock_func.go

Documentation: cmd/vet/testdata

  // Copyright 2013 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // This file contains tests for the copylock checker's
  // function declaration analysis.
  
  package testdata
  
  import "sync"
  
  func OkFunc(*sync.Mutex) {}
  func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes lock by value: sync.Mutex"
  func OkRet() *sync.Mutex {}
  func BadRet() sync.Mutex {} // Don't warn about results
  
  var (
  	OkClosure  = func(*sync.Mutex) {}
  	BadClosure = func(sync.Mutex) {} // ERROR "func passes lock by value: sync.Mutex"
  )
  
  type EmbeddedRWMutex struct {
  	sync.RWMutex
  }
  
  func (*EmbeddedRWMutex) OkMeth() {}
  func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes lock by value: testdata.EmbeddedRWMutex"
  func OkFunc(e *EmbeddedRWMutex)  {}
  func BadFunc(EmbeddedRWMutex)    {} // ERROR "BadFunc passes lock by value: testdata.EmbeddedRWMutex"
  func OkRet() *EmbeddedRWMutex    {}
  func BadRet() EmbeddedRWMutex    {} // Don't warn about results
  
  type FieldMutex struct {
  	s sync.Mutex
  }
  
  func (*FieldMutex) OkMeth()   {}
  func (FieldMutex) BadMeth()   {} // ERROR "BadMeth passes lock by value: testdata.FieldMutex contains sync.Mutex"
  func OkFunc(*FieldMutex)      {}
  func BadFunc(FieldMutex, int) {} // ERROR "BadFunc passes lock by value: testdata.FieldMutex contains sync.Mutex"
  
  type L0 struct {
  	L1
  }
  
  type L1 struct {
  	l L2
  }
  
  type L2 struct {
  	sync.Mutex
  }
  
  func (*L0) Ok() {}
  func (L0) Bad() {} // ERROR "Bad passes lock by value: testdata.L0 contains testdata.L1 contains testdata.L2"
  
  type EmbeddedMutexPointer struct {
  	s *sync.Mutex // safe to copy this pointer
  }
  
  func (*EmbeddedMutexPointer) Ok()      {}
  func (EmbeddedMutexPointer) AlsoOk()   {}
  func StillOk(EmbeddedMutexPointer)     {}
  func LookinGood() EmbeddedMutexPointer {}
  
  type EmbeddedLocker struct {
  	sync.Locker // safe to copy interface values
  }
  
  func (*EmbeddedLocker) Ok()    {}
  func (EmbeddedLocker) AlsoOk() {}
  
  type CustomLock struct{}
  
  func (*CustomLock) Lock()   {}
  func (*CustomLock) Unlock() {}
  
  func Ok(*CustomLock) {}
  func Bad(CustomLock) {} // ERROR "Bad passes lock by value: testdata.CustomLock"
  
  // Passing lock values into interface function arguments
  func FuncCallInterfaceArg(f func(a int, b interface{})) {
  	var m sync.Mutex
  	var t struct{ lock sync.Mutex }
  
  	f(1, "foo")
  	f(2, &t)
  	f(3, &sync.Mutex{})
  	f(4, m) // ERROR "call of f copies lock value: sync.Mutex"
  	f(5, t) // ERROR "call of f copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
  	var fntab []func(t)
  	fntab[0](t) // ERROR "call of fntab.0. copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
  }
  
  // Returning lock via interface value
  func ReturnViaInterface(x int) (int, interface{}) {
  	var m sync.Mutex
  	var t struct{ lock sync.Mutex }
  
  	switch x % 4 {
  	case 0:
  		return 0, "qwe"
  	case 1:
  		return 1, &sync.Mutex{}
  	case 2:
  		return 2, m // ERROR "return copies lock value: sync.Mutex"
  	default:
  		return 3, t // ERROR "return copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
  	}
  }
  
  // Some cases that we don't warn about.
  
  func AcceptedCases() {
  	x := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227)
  	x = BadRet()           // function call on RHS is OK (#16227)
  	x = *OKRet()           // indirection of function call on RHS is OK (#16227)
  }
  
  // TODO: Unfortunate cases
  
  // Non-ideal error message:
  // Since we're looking for Lock methods, sync.Once's underlying
  // sync.Mutex gets called out, but without any reference to the sync.Once.
  type LocalOnce sync.Once
  
  func (LocalOnce) Bad() {} // ERROR "Bad passes lock by value: testdata.LocalOnce contains sync.Mutex"
  
  // False negative:
  // LocalMutex doesn't have a Lock method.
  // Nevertheless, it is probably a bad idea to pass it by value.
  type LocalMutex sync.Mutex
  
  func (LocalMutex) Bad() {} // WANTED: An error here :(
  

View as plain text