-
Notifications
You must be signed in to change notification settings - Fork 244
atproto: some constructors return uncopyable values #1313
Description
As originally observed here #1306, atproto/identity.NewCacheDirectory returns CacheDirectory. The issue is CacheDirectory contains several sync.Map fields which are marked nocopy. In practice all uses of this return value immediately take its address, because *CacheDirectory implements identity.Directory. go vet and other linters will spot any attempt to copy a CacheDirectory by value, ie cdir := identity.NewCacheDirectory(..); somestruct.dir = cdir, but we shouldn't lean on linters to catch this. I think we should correct the return type to be a reference.
@bnewbold suggested that there may be other occurrences which we should address in one commit because changing the return type is a breaking change, albeit a valuable one. An assay of atproto/ highights:
-
identity.NewCacheDirectory -
apidir.NewAPIDirectorywhich requires the caller to refence the return value to fit theAPIDirectoryinterface. -
identify.NewMockDirectory, as above, also contains a lock and map fields, which represents a correctness issue if the lock is copied. -
syntax.NewTIDClockreturnsTIDClock.TIDClockcontains async.Mutexwhich protects thelastUnixMicrofield. Copying a TIDClock copies the lock, which is a party foul, but it also copies lastUnixMicro. There are some questions about the correctness of the use of this type.
Additionally
atproto/lexicon.NewBaseCatalogandatproto/lexicon.NewResolvingCatalogreturn by value. Inside indigo the result is used immediately, but returing by value means the result does not satisfy thelexicon.Cataloginterface. This may be whyResolvingCatalogreferences itsBasefield asBaseCatalog, not the interface type.identify.ParseIdentityreturns anIdentityby value which is a moderately complex object. Benchmarking might be useful to determine if this is more expensive to copy vs gc the reference later. This may also apply toIdentity.DIDDocument