pointfreeco/swift-parsing

Swift 5.8 / Xcode 14.3: Ambiguous use of 'init()' for `Rest()`

Jeehut opened this issue · 5 comments

Jeehut commented

I just upgraded to Xcode 14.3 RC 2 which ships with Swift 5.8 and my project no longer builds, it was building just fine in Xcode 14.2 (Swift 5.7).

The compiler reports Ambiguous use of 'init()' for the line Skip { Rest() } in my code. Here's the full function:

   public static func parseKnownLanguages(_ input: Substring) throws -> [Language] {
      let listOfKnownRegions: Substring = try Parse {
         Skip {
            PrefixThrough("knownRegions")
            Whitespaces()
            "="
            Whitespaces()
            "("
         }
         PrefixUpTo(");")
         Skip { Rest() }  // <-- ERROR: Ambiguous use of 'init()
      }
      .parse(input)

      // ...
   }

Looks like there was a change in Swift 5.8 which causes an ambiguity. Not sure what goes wrong with how simple the initializer of Rest looks (simply @inlinable public init() {}), but something seems to be off. Maybe the usage @_disfavoredOverload is the culprit? I'm on the latest release 0.11.0.

As a workaround, I could explicitly specify the generic, so instead of Rest() if I write Rest<Substring>() it compiles. So I'm good for now, but I think others might run into this issue as well.

Jeehut commented

Ok, here's another parser that fails compiling now (see comment towards end):

       /// Consumes a specific start-tag with a given name, e.g. `<key>` and two attribute, e.g. `<img src="hogwarts.png" title="School">`. Outputs the attributes values.
      struct DoubleAttributes: Parser {
         typealias Values = (firstValue: Substring, secondValue: Substring)

         /// The name of the tag. E.g.  `key` for `</key>`.
         let name: String

         /// The first attribute to be parsed. E.g. `src="hogwarts.png"`.
         let firstAttribute: NamedAttribute

         /// The second attribute to be parsed. E.g. `title="School"`.
         let secondAttribute: NamedAttribute

         func parse(_ input: inout Substring) throws -> Values {
            try Parse {
               "<"
               self.name

               Parse {
                  Whitespaces(minCharacters: 1)
                  firstAttribute
               }

               Parse {
                  Whitespaces(minCharacters: 1)
                  secondAttribute
               }

               Skip {
                  Optionally {
                     PrefixUpTo(">")
                  }
               }

               ">"
            }
            .parse(&input)  // <-- ERROR: Type of expression is ambiguous without more context
         }
      }

UPDATE: Okay, this one might not be related to swift-parsing at all. It seems that automatic mapping of (Substring, Substring) to my custom (firstValue: Substring, secondValue: Substring) no longer worked. But when I store the result of try Parse { ... }.parse(&input) into a variable and then return that on the next line, it works again:

        func parse(_ input: inout Substring) throws -> Values {
            let values = try Parse {
               "<"
               self.name

               Parse {
                  Whitespaces(minCharacters: 1)
                  firstAttribute
               }

               Parse {
                  Whitespaces(minCharacters: 1)
                  secondAttribute
               }

               Skip {
                  Optionally {
                     PrefixUpTo(">")
                  }
               }

               ">"
            }
            .parse(&input)

            return values
         }
Jeehut commented

Alright, there sure are many problems after upgrading to Swift 5.8, here's another one:

      try Parse {
         "%"

         Optionally {
            UInt.parser()  // <-- ERROR: Ambiguous use of 'parser(of:radix:)'
            "$"
         }

         // ...
      }

UPDATE: The workaround was to replace UInt.parser() with UInt.parser(of: Substring.self).

Uki19 commented

I am getting the same error when using Whitespace:

lazy var openingTagParser = Parse {
        "<"
        Not { "/" }
        Prefix(1...) { character in
            character != ">"
        }
        .pipe {
            tagContentParser
            Whitespace(.horizontal)    // <---- Ambiguous use of 'init(_:)'
            Not { "/" }
        }
        ">"
    } 

Other usages as well such as Whitespace(1..., .horizontal) or just Whitespace().

@Jeehut @Uki19 Have you checked the discussion #290? You may need to switch to the swift-5-8 branch and slightly update your code to make it work on Xcode 14.3.

Jeehut commented

@tgrapperon Thank you for pointing me to #290, I didn't check the Discussions tab as I expect issues to appear in the Issues tab. But I switched to the swift-5-8 branch now and things went smoothly, I just had to replace one try Parse { call with try Parse(input: Substring.self) { and all is building, even without the other workarounds I mentioned above.

Closing this as #289 is under way and should fix most issues.