Scala Programming Language
  1. Scala Programming Language
  2. SI-7369

"unreachable code" warning on reachable code

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: Scala 2.10.1
    • Fix Version/s: Scala 2.10.2-RC1
    • Component/s: Pattern Matcher
    • Labels:
      None
    • Environment:

      Ubuntu 12.10
      OpenJDK 64-Bit Server VM, Java 1.7.0_15

      Description

      Another "unreachable code" issue; I've reproduced it in 2.10.1 and a 2.11 nightly build.

      Welcome to Scala version 2.11.0-20130410-113912-f6323d866f (OpenJDK 64-Bit Server VM, Java 1.7.0_15).
      Type in expressions to have them evaluated.
      Type :help for more information.
      
      scala>     val X = true
      X: Boolean = true
      
      scala>     val O = false
      O: Boolean = false
      
      scala>     def classify(neighbourhood: (Boolean, Boolean, Boolean)): String = {
           |         neighbourhood match {
           |         case (X, X, X) => "middle"
           |         case (X, X, O) => "right"
           |         case (O, X, X) => "left"
           |         case _ => throw new IllegalArgumentException("Invalid")
           |       }
           |     }
      <console>:12: warning: unreachable code
                     case (X, X, O) => "right"
                                       ^
      classify: (neighbourhood: (Boolean, Boolean, Boolean))String
      
      scala> classify(true, true, false)
      res0: String = right
      
      scala> classify(false, true, true)
      res1: String = left
      
      Welcome to Scala version 2.10.1 (OpenJDK 64-Bit Server VM, Java 1.7.0_15).
      Type in expressions to have them evaluated.
      Type :help for more information.
      
      scala>     val X = true
      X: Boolean = true
      
      scala>     val O = false
      O: Boolean = false
      
      scala>     def classify(neighbourhood: (Boolean, Boolean, Boolean)): String = {
           |         neighbourhood match {
           |         case (X, X, X) => "middle"
           |         case (X, X, O) => "right"
           |         case (O, X, X) => "left"
           |         case _ => throw new IllegalArgumentException("Invalid")
           |       }
           |     }
      <console>:12: warning: unreachable code
                     case (X, X, O) => "right"
                                       ^
      classify: (neighbourhood: (Boolean, Boolean, Boolean))String
      
      scala> classify(true, true, false)
      res0: String = right
      

        Issue Links

          Activity

          Hide
          Jason Zaugg added a comment -

          Cut down a little:

          val X, Y = true
          (null: Tuple1[Boolean]) match {
            case Tuple1(X) =>
            case Tuple1(Y) => // unreachable
            case _      =>
          }
          
          val X, Y = ""
          (null: Tuple1[String]) match {
            case Tuple1(X) =>
            case Tuple1(Y) => // no warning
            case _      =>
          }
          
          
          Show
          Jason Zaugg added a comment - Cut down a little: val X, Y = true (null: Tuple1[Boolean]) match { case Tuple1(X) => case Tuple1(Y) => // unreachable case _ => } val X, Y = "" (null: Tuple1[String]) match { case Tuple1(X) => case Tuple1(Y) => // no warning case _ => }
          Hide
          Jason Zaugg added a comment -

          Also interesting for comparison:

          sealed abstract class B;
          case object True extends B;
          case object False extends B;
          
          object Test2 {
          
            val X: B = True
            val Y: B = False
          
            (null: Tuple1[B]) match {
              case Tuple1(X) =>
              case Tuple1(Y) => // no warning
              case _      =>
            }
          }
          
          reachable:
           -V1=null#1  /\
             V2=Y#3
          under prefix:
           V2=False.type#4  \/ V2=True.type#5 \/ V2=null#6  /\
               -V2=Y#3      \/    -V2=X#2     \/     /\
               -V2=Y#3      \/   -V2=null#6   \/     /\
           -V2=False.type#4 \/   -V2=null#6   \/     /\
               -V2=X#2      \/   -V2=null#6   \/     /\
           -V2=True.type#5  \/   -V2=null#6   \/     /\
              V1=null#1     \/    -V2=X#2     \/     via Map(V2=Y#3 -> true, V2=False.type#4 -> true, V2=X#2 -> false, V1=null#1 -> false, V2=null#6 -> false)
          

          Compare with the unsatisfiable model for:

          object Test {
            val X, Y = true
            (null: Tuple1[Boolean]) match {
              case Tuple1(X) =>
              case Tuple1(Y) => // unreachable
              case _      =>
            }
          }
          
          unreachable:
           -V1=null#1  /\
             V2=Y#3
          under prefix:
            V2=true#4  \/ V2=false#5   /\
             -V2=X#2   \/ -V2=false#5  /\
             -V2=X#2   \/   -V2=Y#3    /\
             -V2=X#2   \/ -V2=true#4   /\
           -V2=false#5 \/   -V2=Y#3    /\
           -V2=false#5 \/ -V2=true#4   /\
             -V2=Y#3   \/ -V2=true#4   /\
            V1=null#1  \/   -V2=X#2
          
          Show
          Jason Zaugg added a comment - Also interesting for comparison: sealed abstract class B; case object True extends B; case object False extends B; object Test2 { val X: B = True val Y: B = False (null: Tuple1[B]) match { case Tuple1(X) => case Tuple1(Y) => // no warning case _ => } } reachable: -V1=null#1 /\ V2=Y#3 under prefix: V2=False.type#4 \/ V2=True.type#5 \/ V2=null#6 /\ -V2=Y#3 \/ -V2=X#2 \/ /\ -V2=Y#3 \/ -V2=null#6 \/ /\ -V2=False.type#4 \/ -V2=null#6 \/ /\ -V2=X#2 \/ -V2=null#6 \/ /\ -V2=True.type#5 \/ -V2=null#6 \/ /\ V1=null#1 \/ -V2=X#2 \/ via Map(V2=Y#3 -> true, V2=False.type#4 -> true, V2=X#2 -> false, V1=null#1 -> false, V2=null#6 -> false) Compare with the unsatisfiable model for: object Test { val X, Y = true (null: Tuple1[Boolean]) match { case Tuple1(X) => case Tuple1(Y) => // unreachable case _ => } } unreachable: -V1=null#1 /\ V2=Y#3 under prefix: V2=true#4 \/ V2=false#5 /\ -V2=X#2 \/ -V2=false#5 /\ -V2=X#2 \/ -V2=Y#3 /\ -V2=X#2 \/ -V2=true#4 /\ -V2=false#5 \/ -V2=Y#3 /\ -V2=false#5 \/ -V2=true#4 /\ -V2=Y#3 \/ -V2=true#4 /\ V1=null#1 \/ -V2=X#2
          Show
          Jason Zaugg added a comment - https://github.com/scala/scala/pull/2439

            People

            • Assignee:
              Jason Zaugg
              Reporter:
              Joaquin Caraballo
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development