aboutsummaryrefslogtreecommitdiff
path: root/src/go
diff options
context:
space:
mode:
authorRobert Findley <rfindley@google.com>2021-08-16 20:13:25 -0400
committerRobert Findley <rfindley@google.com>2021-08-17 02:50:08 +0000
commit29ec74fb82328f4c005d556291ea687da7aad4b0 (patch)
treeef2b1fd4c6f9791f2d9acdb50ad5e6fcd46ebc3d /src/go
parent91a935ea0f525c04016dd37c45143af942ffd3fc (diff)
downloadgo-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.go23
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
}