Skip to content

Incorrect match inexhaustive warnings in Scala 2.13.5. #12384

New issue

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

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

Already on GitHub? Sign in 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!

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

No branches or pull requests

2 participants