diff options
author | Robert Findley <rfindley@google.com> | 2021-08-16 20:13:25 -0400 |
---|---|---|
committer | Robert Findley <rfindley@google.com> | 2021-08-17 02:50:08 +0000 |
commit | 29ec74fb82328f4c005d556291ea687da7aad4b0 (patch) | |
tree | ef2b1fd4c6f9791f2d9acdb50ad5e6fcd46ebc3d /src/go | |
parent | 91a935ea0f525c04016dd37c45143af942ffd3fc (diff) | |
download | go-29ec74fb82328f4c005d556291ea687da7aad4b0.tar.gz go-29ec74fb82328f4c005d556291ea687da7aad4b0.zip |
go/types: check if the interface is already complete in Complete
Once Interfaces have been completed they must never be written again,
as they may be used concurrently.
Avoid writing Interface.complete unnecessarily in Complete. Also, update
documentation to reflect that Complete must be called before the
Interface may be considered safe for concurrent use.
For #47726
Change-Id: Ic9fd1395ab0dd6d3499f7a698dadf315abcddab8
Reviewed-on: https://go-review.googlesource.com/c/go/+/342749
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/go')
-rw-r--r-- | src/go/types/interface.go | 23 |
1 files changed, 11 insertions, 12 deletions
diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 510c123e97..d27f8cfd4d 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -43,9 +43,12 @@ func NewInterface(methods []*Func, embeddeds []*Named) *Interface { return NewInterfaceType(methods, tnames) } -// NewInterfaceType returns a new interface for the given methods and embedded types. -// NewInterfaceType takes ownership of the provided methods and may modify their types -// by setting missing receivers. +// NewInterfaceType returns a new interface for the given methods and embedded +// types. NewInterfaceType takes ownership of the provided methods and may +// modify their types by setting missing receivers. +// +// To avoid race conditions, the interface's type set should be computed before +// concurrent use of the interface, by explicitly calling Complete. func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { if len(methods) == 0 && len(embeddeds) == 0 { return &emptyInterface @@ -110,16 +113,12 @@ func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() } // form other types. The interface must not contain duplicate methods or a // panic occurs. Complete returns the receiver. // -// Deprecated: Type sets are now computed lazily, on demand; this function -// is only here for backward-compatibility. It does not have to -// be called explicitly anymore. +// Interface types that have been completed are safe for concurrent use. func (t *Interface) Complete() *Interface { - // Some tests are still depending on the state change - // (string representation of an Interface not containing an - // /* incomplete */ marker) caused by the explicit Complete - // call, so we compute the type set eagerly here. - t.complete = true - t.typeSet() + if !t.complete { + t.complete = true + } + t.typeSet() // checks if t.tset is already set return t } |