Uploaded image for project: 'Swift'
  1. Swift
  2. SR-10907

Default implementation not picked up when conforming to two protocols at once

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Open
    • Priority: Medium
    • Resolution: Unresolved
    • Component/s: Compiler
    • Labels:
      None
    • Environment:

      Xcode 10.2.1

      Swift 5.0.1

      macOS 10.14.5

      Description

      1. Let's declare three protocols HumanHasParent and CanCook:

      protocol Human {
          func breathe()
      }
      
      protocol HasParent {
          associatedtype Parent
      
          var parent: Parent { get }
      }
      
      protocol CanCook {
          func cook()
      }

       

      2. Let's say we want to add a default implementation of the method cook() to every Human who also has a parent (conforming to HasParent protocol), but only if the parent can cook (Parent conforming to CanCook protocol).

      extension Human where Self: CanCook & HasParent, Self.Parent: CanCook {
          func cook() {
              parent.cook()
          }
      }

       

      3. Lastly, let's have two classes that implement these protocols, one of them who implements the method cook() and another that has a parent, that we want to delegate the call to:

      class Father: Human, CanCook {
          func breathe() { }
      
          func cook() { }
      }
      
      
      class Toddler: Human, HasParent, CanCook {
          let parent: Human & CanCook
      
          init(parent: Human & CanCook) {
              self.parent = parent
          }
      
          func breathe() { }
      } 

       

      Expected result would be that when calling cook() on the Toddler class, the parent.cook() would get called.

      Actual result is compile error:

       error: SwiftBug.playground:27:7: error: type 'Toddler' does not conform to protocol 'CanCook'
      class Toddler: Human, HasParent, CanCook {
            ^
      
      SwiftBug.playground:16:10: note: candidate has non-matching type '<Self> () -> ()'
          func cook() {
               ^
      
      SwiftBug.playground:12:10: note: protocol requires function 'cook()' with type '() -> ()'; do you want to add a stub?
          func cook()
               ^
      

       

      Note that if we change the type of parent in Toddler to Father, it works as expected. As well as changing the type of parent in Toddler to CanCook and changing the extension definition so that the conformance states Self.Parent == CanCook instead of Self.Parent: CanCook.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              TadeasKriz Tadeas Kriz
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated: