-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Description
Description
Partial block result builder fails to pick correct overload and generates a compiler error Ambiguous use of 'parser(of:)'
Steps to reproduce
Paste the following code into a new project
(This issue is a reduction of trying to compile an example (final 4 lines of the code below) of the swift-parsing package)
//MARK: Parsers
@rethrows public protocol Parser<Input> {
associatedtype Input
}
extension String: Parser {
public typealias Input = Substring
}
extension Int {
static func parser(
of inputType: Substring.Type = Substring.self
) -> FromSubstringToUTF8<IntParser<Substring.UTF8View>> {
FromSubstringToUTF8 { IntParser<Substring.UTF8View>() }
}
static func parser(
of inputType: Substring.UTF8View.Type = Substring.UTF8View.self
) -> IntParser<Substring.UTF8View> {
.init()
}
}
struct FromSubstringToUTF8<P: Parser>: Parser where P.Input == Substring.UTF8View {
typealias Input = Substring
let parser: P
init(@ParserBuilder _ build: () -> P) { self.parser = build() }
}
struct IntParser<Input: Collection>: Parser where Input.SubSequence == Input, Input.Element == UTF8.CodeUnit {
public init() { }
}
//MARK: ParserBuilder
struct Parse<Parsers: Parser>: Parser {
typealias Input = Parsers.Input
let parsers: Parsers
init(@ParserBuilder with build: () -> Parsers) { self.parsers = build() }
}
@resultBuilder
struct ParserBuilder {
public static func buildPartialBlock<P: Parser>(first: P) -> P { first }
public static func buildPartialBlock<P0, P1>(accumulated: P0, next: P1) -> SkipFirst<P0, P1> {
.init(p0: accumulated, p1: next)
}
}
struct SkipFirst<P0: Parser, P1: Parser>: Parser where P0.Input == P1.Input {
typealias Input = P0.Input
let p0: P0
let p1: P1
}
//MARK: main
let first = ParserBuilder.buildPartialBlock(first: ",")
let second = ParserBuilder.buildPartialBlock(accumulated: first, next: Int.parser())
let parser = Parse {
","
Int.parser() // Ambiguous use of 'parser(of:)'
}
Expected behavior
This compiles for toolchain 2023-01-02 but breaks from 2023-01-07.
Expected to compile and choose the correct overload (in this case static func parser(of inputType: Substring.Type = Substring.self)
)
Since the first parser passed to the resultBuilder closure is of type String
therefore the Parser
associated type Input
is of type Substring
. Therefore the compiler should be able to infer that the parser returned by Int.parser()
should have an Input
of Substring
as well.
Calling the individual partialBuildBlock functions does compile
works:
let first = ParserBuilder.buildPartialBlock(first: ",")
let second = ParserBuilder.buildPartialBlock(accumulated: first, next: Int.parser())
fails:
let parser = Parse {
","
Int.parser() // Ambiguous use of 'parser(of:)'
}
Environment
- Swift compiler version info Swift Development Snapshot 2023-01-09
- Xcode version info Xcode 13.4.1 Build version 13F100
- Deployment target: M1 running macOS 12.5