Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: Scala 2.11.0-M5
    • Fix Version/s: Scala 2.11.0-M8
    • Component/s: Pattern Matcher
    • Labels:
      None

      Description

      class Casey(a: Int) { def isEmpty = false; def get = this }
      object Casey { def unapply(a: Casey) = a }
      
      object Test {
        def main(args: Array[String]) {
          val Casey(x) = new Casey(1)
          assert(x == 1, x)
        }
      }
      
      /*
           val x: Int = {
              case <synthetic> val x1: Casey = (new Casey(1): Casey @unchecked);
              case5(){
                <synthetic> val o7: Casey = Casey.unapply(x1);
                if (o7.isEmpty.unary_!)
                  {
                    val x: Casey = o7.get;
                    matchEnd4(x)
                  }
                else
                  case6()
              };
              case6(){
                matchEnd4(throw new MatchError(x1))
              };
              matchEnd4(x: Int){
                x
              }
      */
      

      ClassCastException ensues.

        Issue Links

          Activity

          Hide
          Grzegorz Kossakowski added a comment -

          Unassigning and rescheduling to M7 as previous deadline was missed.

          Show
          Grzegorz Kossakowski added a comment - Unassigning and rescheduling to M7 as previous deadline was missed.
          Hide
          Paul Phillips added a comment -

          Cannot reproduce or figure out what the bug is. You have get returning a Casey. When I compile this, matchEnd4 takes a "Casey" parameter as expected. The assertion fails of course because new Casey(1) != 1, but no CCE. Same thing with M5 or trunk. Can you explain?

          test/files/neg/t7850.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal
              assert(x == 1, x)
                       ^
          one warning found
          java.lang.AssertionError: assertion failed: Casey@3173175
          /*
                val x: Casey = {
                  case <synthetic> val x1: Casey = (new Casey(1): Casey @unchecked);
                  case5(){
                    <synthetic> val o7: Casey = Casey.unapply(x1);
                    if (o7.isEmpty.unary_!)
                      {
                        val x: Casey = o7.get;
                        matchEnd4(x)
                      }
                    else
                      case6()
                  };
                  case6(){
                    matchEnd4(throw new MatchError(x1))
                  };
                  matchEnd4(x: Casey){
                    x
                  }
                };
          */
          
          Show
          Paul Phillips added a comment - Cannot reproduce or figure out what the bug is. You have get returning a Casey. When I compile this, matchEnd4 takes a "Casey" parameter as expected. The assertion fails of course because new Casey(1) != 1, but no CCE. Same thing with M5 or trunk. Can you explain? test/files/neg/t7850.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal assert(x == 1, x) ^ one warning found java.lang.AssertionError: assertion failed: Casey@3173175 /* val x: Casey = { case <synthetic> val x1: Casey = (new Casey(1): Casey @unchecked); case5(){ <synthetic> val o7: Casey = Casey.unapply(x1); if (o7.isEmpty.unary_!) { val x: Casey = o7.get; matchEnd4(x) } else case6() }; case6(){ matchEnd4(throw new MatchError(x1)) }; matchEnd4(x: Casey){ x } }; */
          Hide
          Paul Phillips added a comment -

          Ping retronym. I still have a patch in play which roams this neighborhood but I can't tell what the bug in this ticket is or whether it is real.

          Show
          Paul Phillips added a comment - Ping retronym. I still have a patch in play which roams this neighborhood but I can't tell what the bug in this ticket is or whether it is real.
          Hide
          Jason Zaugg added a comment -
          (export V=v2.11.0-M7 && scalac-hash $V sandbox/test.scala && scala-hash $V Test)
          sandbox/test.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal
              assert(x == 1, x)
                       ^
          one warning found
          java.lang.AssertionError: assertion failed: Casey@c5a67c9
          	at scala.Predef$.assert(Predef.scala:169)
          	at Test$.main(test.scala:7)
          	at Test.main(test.scala)
          	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
          	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
          	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
          	at java.lang.reflect.Method.invoke(Method.java:597)
          	at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:68)
          	at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31)
          	at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:99)
          	at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:68)
          	at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:99)
          	at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
          	at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
          	at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
          	at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
          	at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:72)
          	at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:94)
          	at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
          	at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
            ~/code/scala3 cat sandbox/test.scala
          class Casey(a: Int) { def isEmpty = false; def get = this }
          object Casey { def unapply(a: Casey) = a }
          
          object Test {
            def main(args: Array[String]) {
              val Casey(x) = new Casey(1)
              assert(x == 1, x)
            }
          }
          
          Show
          Jason Zaugg added a comment - (export V=v2.11.0-M7 && scalac-hash $V sandbox/test.scala && scala-hash $V Test) sandbox/test.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal assert(x == 1, x) ^ one warning found java.lang.AssertionError: assertion failed: Casey@c5a67c9 at scala.Predef$.assert(Predef.scala:169) at Test$.main(test.scala:7) at Test.main(test.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at scala.reflect.internal.util.ScalaClassLoader$$anonfun$run$1.apply(ScalaClassLoader.scala:68) at scala.reflect.internal.util.ScalaClassLoader$class.asContext(ScalaClassLoader.scala:31) at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:99) at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:68) at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:99) at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22) at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39) at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29) at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39) at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:72) at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:94) at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103) at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) ~/code/scala3 cat sandbox/test.scala class Casey(a: Int) { def isEmpty = false; def get = this } object Casey { def unapply(a: Casey) = a } object Test { def main(args: Array[String]) { val Casey(x) = new Casey(1) assert(x == 1, x) } }
          Hide
          Jason Zaugg added a comment -

          In earlier versions:

          (export V=v2.11.0-M4 && scalac-hash $V sandbox/test.scala && scala-hash $V Test)
          sandbox/test.scala:6: error: result type Casey of unapply defined in method unapply in object Casey does not conform to Option[_] or Boolean
              val Casey(x) = new Casey(1)
                       ^
          one error found
          
          Show
          Jason Zaugg added a comment - In earlier versions: (export V=v2.11.0-M4 && scalac-hash $V sandbox/test.scala && scala-hash $V Test) sandbox/test.scala:6: error: result type Casey of unapply defined in method unapply in object Casey does not conform to Option[_] or Boolean val Casey(x) = new Casey(1) ^ one error found
          Hide
          Paul Phillips added a comment -

          @retronym I still don't understand what the bug is. You're doing an unchecked pattern match in the val assignment, that's how it works. The behavior is exactly the same in earlier versions if the unapply returns the type which was understood in earlier versions.

          % cat test/files/neg/t7850.scala
          class Casey(a: Int) { def isEmpty = false; def get = this }
          object Casey { def unapply(a: Casey) = Some(a) }
          
          object Test {
            def main(args: Array[String]) {
              val Casey(x) = new Casey(1)
              assert(x == 1, x)
            }
          }
          
          % scalac210 -d /tmp test/files/neg/t7850.scala
          test/files/neg/t7850.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal
              assert(x == 1, x)
                       ^
          scalone warning found
          % scala210 -cp /tmp Test
          java.lang.AssertionError: assertion failed: Casey@1495c8c2
            at scala.Predef$.assert(Predef.scala:179)
            at Test$.main(t7850.scala:7)
            at Test.main(t7850.scala)
            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:606)
          
          Show
          Paul Phillips added a comment - @retronym I still don't understand what the bug is. You're doing an unchecked pattern match in the val assignment, that's how it works. The behavior is exactly the same in earlier versions if the unapply returns the type which was understood in earlier versions. % cat test/files/neg/t7850.scala class Casey(a: Int) { def isEmpty = false; def get = this } object Casey { def unapply(a: Casey) = Some(a) } object Test { def main(args: Array[String]) { val Casey(x) = new Casey(1) assert(x == 1, x) } } % scalac210 -d /tmp test/files/neg/t7850.scala test/files/neg/t7850.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal assert(x == 1, x) ^ scalone warning found % scala210 -cp /tmp Test java.lang.AssertionError: assertion failed: Casey@1495c8c2 at scala.Predef$.assert(Predef.scala:179) at Test$.main(t7850.scala:7) at Test.main(t7850.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606)
          Hide
          Jason Zaugg added a comment - - edited

          Looks like a few bits were twiddled between the original bug and this report. Sorry for the noise. Must have been a strong set of solar flares that day.

          Here's a CCE. We should check that `isEmpty` returns boolean.

          class Casey(a: Int) { def isEmpty = this; def get = this }
          object Casey { def unapply(a: Casey) = a }
           
          object Test {
            def main(args: Array[String]) {
              val Casey(x) = new Casey(1)
            }
          }
          
           (export V=v2.11.0-M5 && scalac-hash $V sandbox/test.scala && scala-hash $V Test)
          sandbox/test.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal
              assert(x == 1, x)
                       ^
          one warning found
          java.lang.ClassCastException: Casey cannot be cast to java.lang.Boolean
          
          (export V=origin/master && scalac-hash $V sandbox/test.scala && scala-hash $V Test)
          sandbox/test.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal
              assert(x == 1, x)
                       ^
          one warning found
          java.lang.ClassCastException: Casey cannot be cast to java.lang.Boolean
          
          Show
          Jason Zaugg added a comment - - edited Looks like a few bits were twiddled between the original bug and this report. Sorry for the noise. Must have been a strong set of solar flares that day. Here's a CCE. We should check that `isEmpty` returns boolean. class Casey(a: Int) { def isEmpty = this; def get = this } object Casey { def unapply(a: Casey) = a } object Test { def main(args: Array[String]) { val Casey(x) = new Casey(1) } } (export V=v2.11.0-M5 && scalac-hash $V sandbox/test.scala && scala-hash $V Test) sandbox/test.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal assert(x == 1, x) ^ one warning found java.lang.ClassCastException: Casey cannot be cast to java.lang.Boolean (export V=origin/master && scalac-hash $V sandbox/test.scala && scala-hash $V Test) sandbox/test.scala:7: warning: Casey and Int are unrelated: they will most likely never compare equal assert(x == 1, x) ^ one warning found java.lang.ClassCastException: Casey cannot be cast to java.lang.Boolean
          Hide
          Paul Phillips added a comment -

          OOOOOOOOOOOOOOOHHHHHHH, it doesn't check the return type of isEmpty. This I can work with.

          Show
          Paul Phillips added a comment - OOOOOOOOOOOOOOOHHHHHHH, it doesn't check the return type of isEmpty. This I can work with.
          Show
          Paul Phillips added a comment - https://github.com/scala/scala/pull/3275

            People

            • Assignee:
              Paul Phillips
              Reporter:
              Jason Zaugg
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development