scala / scala/scala-parser-combinators
Scala 3 union types don't always play nicely with choice
Nobody has claimed this yet.
- Dominant language
- Scala
- Stars
- 679
- Forks
- 131
- Avg merge
- 8h 25m
- Merged PRs (30d)
- 3
Description
- Scala:
3.X - scala-parser-combinators:
2.1.1
Consider the following motivating example:
import scala.util.parsing.combinator.Parsers
enum Token {
case A()
case B()
case C()
}
object Parser extends Parsers {
override type Elem = Token
def tokenA: Parser[Token.A] = ???
def tokenB: Parser[Token.B] = ???
def tokenC: Parser[Token.C] = ???
def tokenABC: Parser[Token.A | Token.B | Token.C] =
tokenA | tokenB | tokenC // error
}
Unfortunately the definition tokenABC doesn't compile:
Found: Parser[Token]
Required: Parser[Token.A | Token.B | Token.C]
tokenA | tokenB | tokenC
A workaround is to ascribe tokenA to the desired union type:
def tokenABC: Parser[Token.A | Token.B | Token.C] =
(tokenA: Parser[Token.A | Token.B | Token.C]) | tokenB | tokenC
However this looks unnatural and arguably not very intuitive.
If we look at the source, this is how the choice operator is defined:
def | [U >: T](q: => Parser[U]): Parser[U]
And it is now evident why the code in the above example fails to compile. The obvious change would be to update the signature to:
def | [U](q: => Parser[U]): Parser[T | U]
Which would definitely break cross compatibility and therefore wouldn't be a viable solution.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the choice operator in Parsers, whose signature is shown in the issue, and reproduce the Scala 3 union-type example with scala-parser-combinators 2.1.1. Investigate a compatible way to support the expected result type without breaking cross compatibility; done means the example compiles and existing choice behavior remains compatible.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- scala
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100