]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/vet: extend copylocks to anonymous functions
authorJosh Bleecher Snyder <josharian@gmail.com>
Sat, 13 Jun 2015 02:49:45 +0000 (19:49 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Sat, 13 Jun 2015 03:07:43 +0000 (03:07 +0000)
Running -copylocks over a large corpus generates 1507 warnings.
Of those, only 3 are from the new anonymous function check,
but they are all bugs.

Fixes #10927.

Change-Id: I2672f6871036bed711beec5f88bc39aa8b3b6a94
Reviewed-on: https://go-review.googlesource.com/11051
Reviewed-by: Rob Pike <r@golang.org>
src/cmd/vet/copylock.go
src/cmd/vet/testdata/copylock_func.go

index 95cecc799c4c3bb4a91b60115ccd510ff4bcb333..6c71061b3e645e77a71bd691faa052ef26142de8 100644 (file)
@@ -18,7 +18,7 @@ func init() {
        register("copylocks",
                "check that locks are not passed by value",
                checkCopyLocks,
-               funcDecl, rangeStmt)
+               funcDecl, rangeStmt, funcLit)
 }
 
 // checkCopyLocks checks whether node might
@@ -28,7 +28,9 @@ func checkCopyLocks(f *File, node ast.Node) {
        case *ast.RangeStmt:
                checkCopyLocksRange(f, node)
        case *ast.FuncDecl:
-               checkCopyLocksFunc(f, node)
+               checkCopyLocksFunc(f, node.Name.Name, node.Recv, node.Type)
+       case *ast.FuncLit:
+               checkCopyLocksFunc(f, "func", nil, node.Type)
        }
 }
 
@@ -36,28 +38,28 @@ func checkCopyLocks(f *File, node ast.Node) {
 // inadvertently copy a lock, by checking whether
 // its receiver, parameters, or return values
 // are locks.
-func checkCopyLocksFunc(f *File, d *ast.FuncDecl) {
-       if d.Recv != nil && len(d.Recv.List) > 0 {
-               expr := d.Recv.List[0].Type
+func checkCopyLocksFunc(f *File, name string, recv *ast.FieldList, typ *ast.FuncType) {
+       if recv != nil && len(recv.List) > 0 {
+               expr := recv.List[0].Type
                if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
-                       f.Badf(expr.Pos(), "%s passes Lock by value: %v", d.Name.Name, path)
+                       f.Badf(expr.Pos(), "%s passes Lock by value: %v", name, path)
                }
        }
 
-       if d.Type.Params != nil {
-               for _, field := range d.Type.Params.List {
+       if typ.Params != nil {
+               for _, field := range typ.Params.List {
                        expr := field.Type
                        if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
-                               f.Badf(expr.Pos(), "%s passes Lock by value: %v", d.Name.Name, path)
+                               f.Badf(expr.Pos(), "%s passes Lock by value: %v", name, path)
                        }
                }
        }
 
-       if d.Type.Results != nil {
-               for _, field := range d.Type.Results.List {
+       if typ.Results != nil {
+               for _, field := range typ.Results.List {
                        expr := field.Type
                        if path := lockPath(f.pkg.typesPkg, f.pkg.types[expr].Type); path != nil {
-                               f.Badf(expr.Pos(), "%s returns Lock by value: %v", d.Name.Name, path)
+                               f.Badf(expr.Pos(), "%s returns Lock by value: %v", name, path)
                        }
                }
        }
index 108c04420954db802edb225505811b6b29eb6375..d83957fe1832f6b6afa9255f005e7e98a5769287 100644 (file)
@@ -14,6 +14,11 @@ func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes Lock by value: sync.Mutex"
 func OkRet() *sync.Mutex {}
 func BadRet() sync.Mutex {} // ERROR "BadRet returns Lock by value: sync.Mutex"
 
+var (
+       OkClosure  = func(*sync.Mutex) {}
+       BadClosure = func(sync.Mutex) {} // ERROR "func passes Lock by value: sync.Mutex"
+)
+
 type EmbeddedRWMutex struct {
        sync.RWMutex
 }