DocC symbol disambiguation for multiple compiler versions, illustrated with 'sending' parameters

Hello,

Unless I'm mistaken, Xcode 15.4 and Swift 5.10 do not support the sending parameters introduced in Swift 6 by SE-0430.

As a consequence, a library that wants to support both compiler versions must perform conditional compilation:

public struct MyType {
#if compiler(<6.0)
    public func f(_ closure: @escaping @Sendable () -> Void) async { }
#else
    public func f(_ closure: sending @escaping () -> Void) async { }
#endif
}

So far, so good. For years now, we've been used to duplicating a lot of code in order to support several compiler versions - can't say it's cool, but it's doable.

Now, this creates an unexpected difficulty with DocC, as soon as there exists an overload that requires disambiguation.

For example, the documentation below builds correctly on Xcode 16. On Xcode 15.4, it emits a warning, and the function is not displayed at the correct place in the generated doc, with an incorrect "See also" section, etc:

'8fvhj' isn't a disambiguation for 'f(_:)' at '/MyLibrary/MyType'

/// ## Topics
///
/// ### Public
///
/// - ``f(_:)-8fvhj``
/// - ``f(_:)-8cqoh``
public struct MyType {
#if compiler(<6.0)
    public func f(_ closure: @escaping @Sendable () -> Void) async { }
#else
    public func f(_ closure: sending @escaping () -> Void) async { }
#endif
    
    public func f(_ x: Int) { }
}

Is there any technique for building correct documentation with both compiler versions?

the best you can do today is to #if #else the entire MyType declaration, including its attached doccomment.

this problem is not unique to multiple compiler versions, it also affects documentation for symbols that differ across platforms, and even cross-platform API that references types that have different ABI on different platforms.

if i were the designer of DocC, i would have gone with a disambiguation syntax based around uttering one of the identifier tokens in the relevant declarations, so instead of using an FNV-1 hash, you could write something like

/// - ``f(_:) (Void)``
/// - ``f(_:) (Int)``

or perhaps

/// - ``f(_:) <async>``
/// - ``f(_:) (Int)``

where () would select a sufficiently unambiguous type identifier (Int, Void) and <> would select a sufficiently unambigious keyword or attribute token (@escaping, @Sendable, sending, async). perhaps someday this could see the light of day as a Unidoc extension, or even become part of DocC itself.

OK, thank you very much! :face_exhaling: