Skip to content

strange MatchError if match body has generic method call without explicit type param #12976

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
xuwei-k opened this issue Jun 29, 2021 · 3 comments · Fixed by #12977
Closed

strange MatchError if match body has generic method call without explicit type param #12976

xuwei-k opened this issue Jun 29, 2021 · 3 comments · Fixed by #12977
Assignees
Milestone

Comments

@xuwei-k
Copy link
Contributor

xuwei-k commented Jun 29, 2021

Compiler version

3.0.0, 3.0.1-RC2 and 3.0.2-RC1-bin-20210626-f33bc8d-NIGHTLY

Minimized code

package example

case class A(s: String)

class B {
  def b1[X](str: String): String = str

  def b2[X](str: String): X = null.asInstanceOf[X]
}

object Main {

  def main(args: Array[String]): Unit = {
    val a = A("aaa")
    val b = new B

    // no error
    a match {
      case A(s) =>
        b.b1(s)
    }

    // no error if add explicit type param
    a match {
      case A(s) =>
        b.b2[Boolean](s)
    }

    // scala.MatchError: A(aaa)
    a match {
      case A(s) =>
        b.b2(s)
    }
  }

}

Output

[info] running example.Main 
[error] (run-main-5) scala.MatchError: A(aaa) (of class example.A)
[error] scala.MatchError: A(aaa) (of class example.A)
[error] 	at example.Main$.main(Main.scala:32)
[error] 	at example.Main.main(Main.scala)
[error] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] 	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] 	at java.lang.reflect.Method.invoke(Method.java:498)

Expectation

@dwijnand
Copy link
Member

Is the expected type Unit of main propagating backwards to b2? And is that then affecting the match translation? Or is the problem elsewhere? 🤔

@odersky
Copy link
Contributor

odersky commented Jun 29, 2021

Here's the code of the main method after pattern matcher:

    def main(args: Array[String]): Unit = 
      {
        val a: A = A.apply("aaa")
        val b: B = new B()
        matchResult4[String]: 
          {
            case val x5: (a : A) = a
            if x5.ne(null) then 
              {
                case val x6: A = A.unapply(x5)
                case val x7: String = x6._1
                case val s: String = x7
                return[matchResult4] 
                  {
                    b.b1[Any](s)
                  }
              }
             else ()
            throw new MatchError(x5)
          }
        matchResult5[Boolean]: 
          {
            case val x8: (a : A) = a
            if x8.ne(null) then 
              {
                case val x9: A = A.unapply(x8)
                case val x10: String = x9._1
                case val s: String = x10
                return[matchResult5] 
                  {
                    b.b2[Boolean](s)
                  }
              }
             else ()
            throw new MatchError(x8)
          }
        matchResult6[Nothing]: 
          {
            case val x11: (a : A) = a
            if x11.ne(null) then 
              {
                case val x12: A = A.unapply(x11)
                case val x13: String = x12._1
                case val s: String = x13
                b.b2[Nothing](s)
              }
             else ()
            throw new MatchError(x11)
          }
      }

In the third case, the return around the body of the case is missing, which means that we run into the MatchError that follows.

I think we should either reject that case statically, or not leave out the return.

@odersky
Copy link
Contributor

odersky commented Jun 29, 2021

The case where it happens is here (line 931 of Pattern Matcher)

        case ResultPlan(tree) =>
          if (tree.tpe <:< defn.NothingType) tree // For example MatchError
          else Return(tree, ref(resultLabel))

The commit is from #5082.

odersky added a commit to dotty-staging/dotty that referenced this issue Jun 29, 2021
BarkingBad pushed a commit to BarkingBad/dotty that referenced this issue Jul 23, 2021
@Kordyjan Kordyjan added this to the 3.0.2 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants