From c2eba53e7f80df21d51285879d51ab81bcfbf6bc Mon Sep 17 00:00:00 2001 From: Dan Kortschak Date: Sun, 1 Jul 2018 09:33:55 +0930 Subject: [PATCH] cmd/vet,sync: check lock values more precisely Fixes #26165 Change-Id: I1f3bd193af9b6f8461c736330952b6e50d3e00d9 Reviewed-on: https://go-review.googlesource.com/121876 Reviewed-by: Alan Donovan Run-TryBot: Rob Pike TryBot-Result: Gobot Gobot --- src/cmd/vet/copylock.go | 22 ++++++++++++++++------ src/sync/cond.go | 3 ++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/cmd/vet/copylock.go b/src/cmd/vet/copylock.go index ce14e1af34..ed88ca8960 100644 --- a/src/cmd/vet/copylock.go +++ b/src/cmd/vet/copylock.go @@ -234,13 +234,11 @@ func lockPath(tpkg *types.Package, typ types.Type) typePath { return nil } - // We're looking for cases in which a reference to this type - // can be locked, but a value cannot. This differentiates + // We're looking for cases in which a pointer to this type + // is a sync.Locker, but a value is not. This differentiates // embedded interfaces from embedded values. - if plock := types.NewMethodSet(types.NewPointer(typ)).Lookup(tpkg, "Lock"); plock != nil { - if lock := types.NewMethodSet(typ).Lookup(tpkg, "Lock"); lock == nil { - return []types.Type{typ} - } + if types.Implements(types.NewPointer(typ), lockerType) && !types.Implements(typ, lockerType) { + return []types.Type{typ} } nfields := styp.NumFields() @@ -254,3 +252,15 @@ func lockPath(tpkg *types.Package, typ types.Type) typePath { return nil } + +var lockerType *types.Interface + +// Construct a sync.Locker interface type. +func init() { + nullary := types.NewSignature(nil, nil, nil, false) // func() + methods := []*types.Func{ + types.NewFunc(token.NoPos, nil, "Lock", nullary), + types.NewFunc(token.NoPos, nil, "Unlock", nullary), + } + lockerType = types.NewInterface(methods, nil).Complete() +} diff --git a/src/sync/cond.go b/src/sync/cond.go index 3dcbf1c351..b254c9360a 100644 --- a/src/sync/cond.go +++ b/src/sync/cond.go @@ -94,4 +94,5 @@ func (c *copyChecker) check() { type noCopy struct{} // Lock is a no-op used by -copylocks checker from `go vet`. -func (*noCopy) Lock() {} +func (*noCopy) Lock() {} +func (*noCopy) Unlock() {} -- 2.50.0