Skip to content

atproto: some constructors return uncopyable values #1313

@davecheney

Description

@davecheney

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.NewAPIDirectory which requires the caller to refence the return value to fit the APIDirectory interface.

  • identify.NewMockDirectory, as above, also contains a lock and map fields, which represents a correctness issue if the lock is copied.

  • syntax.NewTIDClock returns TIDClock. TIDClock contains a sync.Mutex which protects the lastUnixMicro field. 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.NewBaseCatalog and atproto/lexicon.NewResolvingCatalog return by value. Inside indigo the result is used immediately, but returing by value means the result does not satisfy the lexicon.Catalog interface. This may be why ResolvingCatalog references its Base field as BaseCatalog, not the interface type.
  • identify.ParseIdentity returns an Identity by 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 to Identity.DIDDocument

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions