Skip to content

Commit 29ec74f

Browse files
committed
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 <[email protected]> Run-TryBot: Robert Findley <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 91a935e commit 29ec74f

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

src/go/types/interface.go

+11-12
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,12 @@ func NewInterface(methods []*Func, embeddeds []*Named) *Interface {
4343
return NewInterfaceType(methods, tnames)
4444
}
4545

46-
// NewInterfaceType returns a new interface for the given methods and embedded types.
47-
// NewInterfaceType takes ownership of the provided methods and may modify their types
48-
// by setting missing receivers.
46+
// NewInterfaceType returns a new interface for the given methods and embedded
47+
// types. NewInterfaceType takes ownership of the provided methods and may
48+
// modify their types by setting missing receivers.
49+
//
50+
// To avoid race conditions, the interface's type set should be computed before
51+
// concurrent use of the interface, by explicitly calling Complete.
4952
func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface {
5053
if len(methods) == 0 && len(embeddeds) == 0 {
5154
return &emptyInterface
@@ -110,16 +113,12 @@ func (t *Interface) IsConstraint() bool { return !t.typeSet().IsMethodSet() }
110113
// form other types. The interface must not contain duplicate methods or a
111114
// panic occurs. Complete returns the receiver.
112115
//
113-
// Deprecated: Type sets are now computed lazily, on demand; this function
114-
// is only here for backward-compatibility. It does not have to
115-
// be called explicitly anymore.
116+
// Interface types that have been completed are safe for concurrent use.
116117
func (t *Interface) Complete() *Interface {
117-
// Some tests are still depending on the state change
118-
// (string representation of an Interface not containing an
119-
// /* incomplete */ marker) caused by the explicit Complete
120-
// call, so we compute the type set eagerly here.
121-
t.complete = true
122-
t.typeSet()
118+
if !t.complete {
119+
t.complete = true
120+
}
121+
t.typeSet() // checks if t.tset is already set
123122
return t
124123
}
125124

0 commit comments

Comments
 (0)