Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Symbol Graphs Contain Invalid Default Implementation Relationships #61285

Open
theMomax opened this issue Sep 25, 2022 · 1 comment
Open

Symbol Graphs Contain Invalid Default Implementation Relationships #61285

theMomax opened this issue Sep 25, 2022 · 1 comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. SymbolGraphGen The swiftSymbolGraphGen library, responsible for gathering and emitting symbol graphs.

Comments

@theMomax
Copy link
Contributor

Describe the bug

Members that are marked as throws and/or async are recorded as default implementation targets for protocol requirements without the respective keyword(s).

This is caused by the name-based comparison here:

  /// Claim a protocol `P`'s members as default implementation targets
  /// for `VD`.
  auto HandleProtocol = [=](const ProtocolDecl *P) {
    for (const auto *Member : P->getMembers()) {
      if (const auto *MemberVD = dyn_cast<ValueDecl>(Member)) {
        if (MemberVD->getName().compare(VD->getName()) == 0) { // <-- does not consider `throws` or `async` keywords
          recordEdge(Symbol(this, VD, nullptr),
                     Symbol(this, MemberVD, nullptr),
                     RelationshipKind::DefaultImplementationOf());

Steps To Reproduce

  1. Build documentation for the following code:
public protocol E {
  func foo()
}

public extension E {
  func foo() throws { }
}
  1. Inspect the symbol graph file, which should contain a relationship similar to this one:
{
    "kind": "defaultImplementationOf",
    "source": "s:9MyLibrary1EPAAE3fooyyKF",
    "target": "s:9MyLibrary1EP3fooyyF"
}
  1. The default implementation is also reflected in the documentation archive:

image

Expected behavior
The detection of default implementation should follow the rules applied by the Swift compiler, i.e. a member can only implement a protocol requirement if it requires a subset of the call modifiers (try, await) required by the protocol requirement.

E.g. in the example above, the implementation cannot implement the requirement because the former throws, whereas the latter doesn't:

public protocol E {
  func foo()
}

public extension E {
  func foo() throws { }
}

struct D: E { } // Error: Type 'D' does not conform to protocol 'E'

Environment (please fill out the following information)

  • macOS 12.6 (21G115)
  • Xcode Version 13.3 (13E113), but also applies to swift/main
@theMomax theMomax added the bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. label Sep 25, 2022
@LucianoPAlmeida LucianoPAlmeida added the SymbolGraphGen The swiftSymbolGraphGen library, responsible for gathering and emitting symbol graphs. label Sep 28, 2022
@slavapestov
Copy link
Contributor

slavapestov commented Dec 8, 2023

The bug is a consequence of the fact that SymbolGraph::recordDefaultImplementationRelationships() seems to implement it's own thing here: https://github.com/apple/swift/blob/9ee5d6b34291ebfc89f57068ed89842285dc9688/lib/SymbolGraphGen/SymbolGraph.cpp#L410

TypeChecker::inferDefaultWitnesses() already computes this information, and records it in eg ProtocolDecl::getDefaultWitness().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. SymbolGraphGen The swiftSymbolGraphGen library, responsible for gathering and emitting symbol graphs.
Projects
None yet
Development

No branches or pull requests

3 participants