DocC omits @Sendable. Bug or intentional?

I recently posted an issue in swiftlang/swift about a missing @Sendable annotation in the documentation for AsyncStream(unfolding:onCancel:):

Social media replies from @beccadax and @ktoso (also quoted in the issue) pointed me to the possibility that this could be a more general issue and that @Sendable attributes are generally omitted in DocC-rendered documentation.

So I created a simple test package to verify this:

And indeed, DocC doesn't seem to render any @Sendable attributes, despite them being in the source code (tested with swift-docc-plugin v1.4.5, Swift 6.2, macOS 15.6.1). For example, this is the declaration in the source code:

struct StructWithSendable {
    public func doSomething(_ body: @Sendable () -> Void) {}
}

And DocC renders it like this:

func doSomething(_ body: () -> Void)

Questions:

  • Is this intended behavior?
  • If it is intended, what's the reason?
5 Likes
  • Is this intended behavior?

No. Don't think its the intended behavior IMO.

You can first confirm that @Sendable is emitted into the symbol graph file. If not, we need some change into the Swift compiler (File a GH issue to swiftlang/swift). cc @QuietMisdreavus

If @Sendable is emitted into symbol graph, then it's probably DocC not consuming it somehow. (File a issue on swift-docc or swift-docc-symbolkit)

1 Like

I'm sure you were just dying to see a bit of a raw symbol graph in the forums, so - taking from Ole's example, this is the function signature that's generated by a symbol graph for the doSomething method, which is - if it existed, I thought I might find the Sendable detail about the parameter.

"functionSignature": {
  "parameters": [
    {
      "name": "body",
      "declarationFragments": [
        {
          "kind": "identifier",
          "spelling": "body"
        },
        {
          "kind": "text",
          "spelling": ": () -> "
        },
        {
          "kind": "typeIdentifier",
          "spelling": "Void",
          "preciseIdentifier": "s:s4Voida"
        }
      ]
    }
  ],
  "returns": [
    {
      "kind": "text",
      "spelling": "()"
    }
  ]
},

(I used the command swift package dump-symbol-graph to get the detail, and took a snippet of the resulting file)

I made another quick variation that included @escaping in a similar method, and it also doesn't show in the parameters list, but it does get listed with the list of declarationFragments. For the Ole's original example, that output today is:

"declarationFragments": [
        {
          "kind": "keyword",
          "spelling": "func"
        },
        {
          "kind": "text",
          "spelling": " "
        },
        {
          "kind": "identifier",
          "spelling": "doSomething"
        },
        {
          "kind": "text",
          "spelling": "("
        },
        {
          "kind": "externalParam",
          "spelling": "_"
        },
        {
          "kind": "text",
          "spelling": " "
        },
        {
          "kind": "internalParam",
          "spelling": "body"
        },
        {
          "kind": "text",
          "spelling": ": () -> "
        },
        {
          "kind": "typeIdentifier",
          "spelling": "Void",
          "preciseIdentifier": "s:s4Voida"
        },
        {
          "kind": "text",
          "spelling": ")"
        }
],

So I think the fundamental issue is that Sendable isn't included in that list as an attribute.

Instead of the following entry from the above list:

        {
          "kind": "text",
          "spelling": ": () -> "
        },

I'd think to see something like:

       {
          "kind": "text",
          "spelling": ": "
        },
        {
          "kind": "attribute",
          "spelling": "@Sendable "
        },
        {
          "kind": "text",
          "spelling": "() -> "
        },

Which I think would reflect the @Sendable attribute into the resulting documentation content.

/cc @QuietMisdreavus, who's far more familiar with symbol graphs than I.

In short, it looks like the SymbolGraph returned from the compiler isn't providing the detail needed to expose it in DocC at the moment.

5 Likes

Also the public declaration was lost in Ole's example. I think documentation should reflect access level.

Thank you so much for doing the analysis, Joseph! I didn't even know swift package dump-symbol-graph existed.

1 Like

The default display for symbols when publishing docs for a library is the public access level, so for the common case, that's assumed rather than repeated in every entry. When you're generating a documentation archive for your own content, you can control what visibility level is included, and that information (the access level for the symbol) is included in the symbol graph.

2 Likes