Skip to content

Incorrect match inexhaustive warnings in Scala 2.13.5. #12384

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
counter2015 opened this issue Apr 26, 2021 · 2 comments
Closed

Incorrect match inexhaustive warnings in Scala 2.13.5. #12384

counter2015 opened this issue Apr 26, 2021 · 2 comments

Comments

@counter2015
Copy link

reproduction steps

using Scala 2.13.5, scala-parser-combinators 1.1.2,

the exmaple code is modified from scala-parser-combinators project.

Welcome to Scala 2.13.5 (OpenJDK 64-Bit Server VM, Java 11.0.9.1).
Type in expressions for evaluation. Or try :help.

scala> import scala.util.parsing.combinator.RegexParsers
     | 
     | case class WordFreq(word: String, count: Int) {
     |   override def toString = s"Word <$word> occurs with frequency $count"
     | }
     | 
     | class SimpleParser extends RegexParsers {
     |   def word: Parser[String]   = """[a-z]+""".r       ^^ { _.toString }
     |   def number: Parser[Int]    = """(0|[1-9]\d*)""".r ^^ { _.toInt }
     |   def freq: Parser[WordFreq] = word ~ number        ^^ { case wd ~ fr => WordFreq(wd,fr) }
     | }
     | 
     | object TestSimpleParser extends SimpleParser {
     |   def main(args: Array[String]) = {
     |     parse(freq, "johnny 121") match {
     |       case Success(matched,_) => println(matched)
     |       case NoSuccess(msg,_) => println(s"NoSuccess: $msg")
     |     }
     |   }
     | }
           parse(freq, "johnny 121") match {
                ^
On line 15: warning: match may not be exhaustive.
       It would fail on the following inputs: Error(_, _), Failure(_, _)
import scala.util.parsing.combinator.RegexParsers
class WordFreq
class SimpleParser
object TestSimpleParser

problem

To simplicity, it seems like something following (not exactly)

sealed abstract class ParseResult
case class Success(result: String) extends ParseResult
sealed abstract class NoSuccess(msg: String) extends ParseResult
case class Failure(msg: String) extends NoSuccess(msg)
case class Error(msg: String) extends NoSuccess(msg)
object NoSuccess {
  def unapply[T](x: ParseResult): Option[String] = x match {
    case Failure(msg)   => Some(msg)
    case Error(msg)     => Some(msg)
    case _              => None
  }
}

The NoSuccess is a sealed abstact class and only has two sub-class Failure and Error.
The ParseResult is a sealed abstact class and only has two sub-class Success and NoSuccess

The matching here for Success and NotSuccess should be exhaustived already.

@counter2015 counter2015 changed the title Incorrect match inexhaustive warnings in Scala 2.13.5 in parser result. Incorrect match inexhaustive warnings in Scala 2.13.5. Apr 26, 2021
@dwijnand
Copy link
Member

dwijnand commented Apr 26, 2021

There's nothing unexpected here. With NoSuccess not being a case class case NoSuccess(msg,_) is using NoSuccess's unapply, which is a refutable custom extractor (you can tell because it returns an Option[String]). It's only by your analysis of the body of the unapply do you know that it extracts for both Error and Failure.

There's a few ways this could be fixed, at least in theory (backwards compatibility of scala-parser-combinators might impede parts of these):

  • define NoSuccess's unapply as def unapply[T](x: NoSuccess): Some[String], which I think should be fine
  • make NoSuccess the case class, and Error and Failure subclasses, and recreate their apply/unapply/toString/copy/etc methods

@counter2015
Copy link
Author

@dwijnand Thanks your explanation!

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

2 participants