encoding of generic constraints loses information for complex bounds #149

Open
opened 2025-10-14 15:49:29 -06:00 by navan · 0 comments
Owner

Originally created by @tayloraswift on 6/13/2024

currently, Unidoc’s generics ABI is very weak; given a constraint like T.U == Array<Int>, Unidoc will only be able to identify it as T.U == Array. one implication of this is if there are two extensions with distinct constraints T.U == Array<Int>, T.U == Array<UInt>, Unidoc will be unable to distinguish them, as the type parameters to Array are lost.

there are two upstream bugs in lib/SymbolGraphGen:

  1. T.U is encoded without specifying the depth of the generic parameters, although this only affects Swift 5.10 code and earlier, as generic parameter shadowing was banned in Swift 6. (https://github.com/apple/swift/issues/64444)

  2. the ID of Array<T> points to the generic type, not the concrete type with type substitutions. this was likely an intentional choice in lib/SymbolGraphGen, because we could not possibly generate documentation for Array<Int>, Array<UInt>, etc., so the generic type is a better choice of link target. however, it is unsafe to use as an identity. (https://github.com/apple/swift/issues/74406)

we can partly mitigate the problem by adding the formatted string Array<Int> to the identity of a generic constraint clause, although this is still incorrect - it cannot distinguish between types that shadow names in other modules.

fixing this is ABI-breaking for Swiftinit, as it changes the sort order of extension groups in very rare scenarios. we’ll probably need to do a second ABI break if we get an upstream fix in lib/SymbolGraphGen.

*Originally created by @tayloraswift on 6/13/2024* currently, Unidoc’s generics ABI is very weak; given a constraint like `T.U == Array<Int>`, Unidoc will only be able to identify it as `T.U == Array`. one implication of this is if there are two extensions with distinct constraints `T.U == Array<Int>`, `T.U == Array<UInt>`, Unidoc will be unable to distinguish them, as the type parameters to `Array` are lost. there are two upstream bugs in lib/SymbolGraphGen: 1. `T.U` is encoded without specifying the *depth* of the generic parameters, although this only affects Swift 5.10 code and earlier, as generic parameter shadowing was banned in Swift 6. (https://github.com/apple/swift/issues/64444) 2. the ID of `Array<T>` points to the generic type, not the concrete type with type substitutions. this was likely an intentional choice in lib/SymbolGraphGen, because we could not possibly generate documentation for `Array<Int>`, `Array<UInt>`, etc., so the generic type is a better choice of link target. however, it is unsafe to use as an identity. (https://github.com/apple/swift/issues/74406) we can *partly* mitigate the problem by adding the formatted string `Array<Int>` to the identity of a generic constraint clause, although this is still incorrect - it cannot distinguish between types that shadow names in other modules. fixing this is ABI-breaking for Swiftinit, as it changes the sort order of extension groups in very rare scenarios. we’ll probably need to do a second ABI break if we get an upstream fix in lib/SymbolGraphGen.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github/swift-unidoc#149
No description provided.