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

Conditional conformance over array of heterogenous values that share a protocol conformance fails

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Medium
    • Resolution: Won't Do
    • Component/s: Compiler
    • Labels:
      None
    • Environment:

      macOS 10.13.3 (17D102)

      Xcode Version 9.3 (9E145)

      Description

      The following code that makes an Array to conform to Protocol only if all its elements conform to that same protocol fails to compile when trying to assign such array to variable declared as the protocol's type. The following is an example that reproduces the error

       

      public protocol QueryStringConvertible {
          
          var asQueryString: String { get }
          
      }
      
      extension Array: QueryStringConvertible where Element: QueryStringConvertible {
          
          public var asQueryString: String {
              return self.reduce("") { $0.isEmpty ? $1.asQueryString : "\($0)&\($1.asQueryString)"  }
          }
          
      }
      
      extension Dictionary: QueryStringConvertible where Key == String, Value: CustomStringConvertible {
          
          public var asQueryString: String {
              return self.reduce("") { ($0.isEmpty ? "" : "\($0)&") + "\($1.key)=\($1.value)" }
          }
          
      }
      
      struct Person: QueryStringConvertible {
          
          let firstName: String
          let lastName: String
          
          public var asQueryString: String {
              return "firstName=\(firstName)&lastName=\(lastName)"
          }
          
      }
      
      func bar<Q: QueryStringConvertible>(query: Q) -> String{
          return "QUERY: " + query.asQueryString
      }
      
      func baz(query: QueryStringConvertible) -> String {
          return "QUERY: " + query.asQueryString
      }
      
      let dictionary = [ "param1" : "value1", "param2" : "value2" ]
      dictionary.asQueryString
      let person = Person(firstName: "John", lastName: "Doe")
      person.asQueryString
      bar(query: dictionary)
      bar(query: person)
      bar(query: [dictionary])
      bar(query: [person])
      
      // THIS does not compile -> '<Q where Q : QueryStringConvertible> (query: Q) -> String' requires that 'Any' conform to 'QueryStringConvertible'
      bar(query: [dictionary, person])
      
      baz(query: dictionary)
      baz(query: person)
      baz(query: [dictionary])
      baz(query: [person])
      
      //  This does not compile -> Contextual type 'QueryStringConvertible' cannot be used with array literal
      baz(query: [dictionary, person])
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              Unassigned Unassigned
              Reporter:
              guidomb Guido Marucci Blas
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: