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

assertion failure in typer with nested match and existentials

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: Scala 2.8.0
    • Component/s: Misc Compiler
    • Labels:
      None
    • Environment:

      compiler, crash

      Description

      This occurred against 2.7.2 RC2 (and RC1). See attached file for code.

      java.lang.AssertionError: assertion failed: NonEmptyCons((head @ _), (tail @ _)) ==> NonEmptyCons.unapply[Nothing, Nothing](<unapply-selector>) <unapply> ((head @ _), (tail @ _)), pt = ?
      at scala.Predef$$.assert(Predef.scala:92)
      at scala.tools.nsc.typechecker.Typers$$Typer.doTypedApply(Typers.scala:1892)
      at scala.tools.nsc.typechecker.Typers$$Typer.doTypedApply(Typers.scala:1811)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedApply$$1(Typers.scala:2619)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3219)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3323)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedPattern(Typers.scala:3390)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedCase(Typers.scala:1419)
      at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$typedCases$$1.apply(Typers.scala:1442)
      at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$typedCases$$1.apply(Typers.scala:1440)
      at scala.List$$.loop$$1(List.scala:293)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedCases(Typers.scala:1440)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3135)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3323)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedBlock(Typers.scala:1405)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3083)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3323)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3371)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedCase(Typers.scala:1422)
      at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$typedCases$$1.apply(Typers.scala:1442)
      at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$typedCases$$1.apply(Typers.scala:1440)
      at scala.List$$.loop$$1(List.scala:293)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedCases(Typers.scala:1440)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3135)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3323)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3371)
      at scala.tools.nsc.typechecker.Typers$$Typer.transformedOrTyped(Typers.scala:3429)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedDefDef(Typers.scala:1342)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3059)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3323)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3360)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedStat$$1(Typers.scala:1570)
      at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$19.apply(Typers.scala:1615)
      at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$19.apply(Typers.scala:1615)
      at scala.List$$.loop$$1(List.scala:293)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.List$$.loop$$1(List.scala:297)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.List$$.loop$$1(List.scala:297)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedStats(Typers.scala:1615)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedTemplate(Typers.scala:1193)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedModuleDef(Typers.scala:1086)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3053)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3323)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3360)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedStat$$1(Typers.scala:1570)
      at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$19.apply(Typers.scala:1615)
      at scala.tools.nsc.typechecker.Typers$$Typer$$$$anonfun$$19.apply(Typers.scala:1615)
      at scala.List$$.loop$$1(List.scala:293)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.List$$.loop$$1(List.scala:297)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.List$$.loop$$1(List.scala:297)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.List$$.loop$$1(List.scala:297)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.List$$.loop$$1(List.scala:297)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.List$$.loop$$1(List.scala:297)
      at scala.List$$.mapConserve(List.scala:310)
      at scala.tools.nsc.typechecker.Typers$$Typer.typedStats(Typers.scala:1615)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed1(Typers.scala:3046)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3323)
      at scala.tools.nsc.typechecker.Typers$$Typer.typed(Typers.scala:3360)
      at scala.tools.nsc.typechecker.Analyzer$$typerFactory$$$$anon$$2.apply(Analyzer.scala:40)
      at scala.tools.nsc.Global$$GlobalPhase.applyPhase(Global.scala:268)
      at scala.tools.nsc.Global$$GlobalPhase$$$$anonfun$$run$$1.apply(Global.scala:247)
      at scala.tools.nsc.Global$$GlobalPhase$$$$anonfun$$run$$1.apply(Global.scala:247)
      at scala.Iterator$$class.foreach(Iterator.scala:410)
      at scala.collection.mutable.ListBuffer$$$$anon$$1.foreach(ListBuffer.scala:266)
      at scala.tools.nsc.Global$$GlobalPhase.run(Global.scala:247)
      at scala.tools.nsc.Global$$Run.compileSources(Global.scala:579)
      at scala.tools.nsc.Global$$Run.compile(Global.scala:663)
      at scala.tools.ant.Scalac.execute(Scalac.scala:574)
      at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
      at sun.reflect.GeneratedMethodAccessor90.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
      at org.apache.tools.ant.Task.perform(Task.java:348)
      at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:62)
      at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
      at sun.reflect.GeneratedMethodAccessor90.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
      at org.apache.tools.ant.Task.perform(Task.java:348)
      at org.apache.tools.ant.taskdefs.MacroInstance.execute(MacroInstance.java:394)
      at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
      at sun.reflect.GeneratedMethodAccessor90.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:585)
      at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
      at org.apache.tools.ant.Task.perform(Task.java:348)
      at org.apache.tools.ant.Target.execute(Target.java:357)
      at org.apache.tools.ant.Target.performTasks(Target.java:385)
      at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
      at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
      at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
      at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
      at org.apache.tools.ant.module.bridge.impl.BridgeImpl.run(BridgeImpl.java:273)
      at org.apache.tools.ant.module.run.TargetExecutor.run(TargetExecutor.java:486)
      at org.netbeans.core.execution.RunClassThread.run(RunClassThread.java:151)

        Activity

        Hide
        Erik Engbrecht added a comment -

        // I can't seem to find the "Attach file" button, so here's the code

        package constreecompilercrash

        object ConsCell {
        // Here I'm trying to fake out the compiler into letting me define
        // what would more logically be a recursive type. It could be that this
        // should be illegal and that's why it is crashing the typer later on.
        type BT[+H, +T <: ConsCell[ConsCell[H, T], ConsCell[H, T]]] = ConsCell[H, T]
        type BinaryTree[+E] = BT[E, T forSome

        {type T <: ConsCell[BT[E, T], BT[E, T]]}

        ]

        def apply[H, T](h: H, t: T): ConsCell[H, T] = BasicConsCell(h, t)

        private case class BasicConsCell[+H, +T](val head: H, val tail: T) extends ConsCell[H, T]
        }

        sealed trait ConsCell[+H, +T]

        { def ::[A](obj: A): ConsCell[A, ConsCell[H, T]] = ConsCell(obj, this) }

        object NonEmptyCons {
        def unapply[H, T](c: ConsCell[H, T]): Option[(H, T)] = c match

        { case Nil => None case c: NonEmptyCons[H, T] => Some(c.head, c.tail) }

        }

        trait NonEmptyCons[+H, +T] extends ConsCell[H, T]

        { def head: H def tail: T }

        object Nil extends ConsCell[Nothing, Nothing]

        object Main {

        import ConsCell._

        def main(args: Array[String])

        { val t1 = 1 :: Nil // looks like a list, doesn't it? val t2 = 1 :: ConsCell((2 :: Nil), (3 :: Nil)) walkTree(t1, println) walkTree(t2, println) }

        def walkTree[E](tree: BinaryTree[E], op: E => Unit): Unit = tree match {
        case Nil => ()
        case NonEmptyCons(head, tail) => {
        op(head)
        tail match {
        case Nil => ()
        case NonEmptyCons(head, tail) =>

        { walkTree(tail.head, op) walkTree(tail.tail, op) }

        }
        }
        }
        }

        Show
        Erik Engbrecht added a comment - // I can't seem to find the "Attach file" button, so here's the code package constreecompilercrash object ConsCell { // Here I'm trying to fake out the compiler into letting me define // what would more logically be a recursive type. It could be that this // should be illegal and that's why it is crashing the typer later on. type BT[+H, +T <: ConsCell[ConsCell [H, T] , ConsCell [H, T] ]] = ConsCell [H, T] type BinaryTree [+E] = BT[E, T forSome {type T <: ConsCell[BT[E, T], BT[E, T]]} ] def apply [H, T] (h: H, t: T): ConsCell [H, T] = BasicConsCell(h, t) private case class BasicConsCell [+H, +T] (val head: H, val tail: T) extends ConsCell [H, T] } sealed trait ConsCell [+H, +T] { def ::[A](obj: A): ConsCell[A, ConsCell[H, T]] = ConsCell(obj, this) } object NonEmptyCons { def unapply [H, T] (c: ConsCell [H, T] ): Option [(H, T)] = c match { case Nil => None case c: NonEmptyCons[H, T] => Some(c.head, c.tail) } } trait NonEmptyCons [+H, +T] extends ConsCell [H, T] { def head: H def tail: T } object Nil extends ConsCell [Nothing, Nothing] object Main { import ConsCell._ def main(args: Array [String] ) { val t1 = 1 :: Nil // looks like a list, doesn't it? val t2 = 1 :: ConsCell((2 :: Nil), (3 :: Nil)) walkTree(t1, println) walkTree(t2, println) } def walkTree [E] (tree: BinaryTree [E] , op: E => Unit): Unit = tree match { case Nil => () case NonEmptyCons(head, tail) => { op(head) tail match { case Nil => () case NonEmptyCons(head, tail) => { walkTree(tail.head, op) walkTree(tail.tail, op) } } } } }
        Hide
        Tiark Rompf added a comment -

        Here's a reduced version that also fails. Removing the inner match makes it pass the typer. Replacing the extractors with tuple patterns makes it pass the typer but will cause a crash in ParallelMatching during explicit outer.

        object NonEmptyCons {
          def unapply[H, T](c: (H, T)): Option[(H, T)] = Some(c)
        }
        
        
        object Main {
        
          type BT[+H, +T <: Tuple2[Tuple2[H, T], Tuple2[H, T]]] = Tuple2[H, T]
          
          type BinaryTree[+E] = BT[E, T forSome {type T <: Tuple2[BT[E, T], BT[E, T]]}]
        
          def foo[E](tree: BinaryTree[E]): Unit = tree match {
            case NonEmptyCons(_, tail) => {
              tail match {
                case NonEmptyCons(_, _) => {
                }
              }
            }
          }
        }
        
        
        Show
        Tiark Rompf added a comment - Here's a reduced version that also fails. Removing the inner match makes it pass the typer. Replacing the extractors with tuple patterns makes it pass the typer but will cause a crash in ParallelMatching during explicit outer. object NonEmptyCons { def unapply[H, T](c: (H, T)): Option[(H, T)] = Some(c) } object Main { type BT[+H, +T <: Tuple2[Tuple2[H, T], Tuple2[H, T]]] = Tuple2[H, T] type BinaryTree[+E] = BT[E, T forSome {type T <: Tuple2[BT[E, T], BT[E, T]]}] def foo[E](tree: BinaryTree[E]): Unit = tree match { case NonEmptyCons(_, tail) => { tail match { case NonEmptyCons(_, _) => { } } } } }
        Hide
        Paul Phillips added a comment -

        Once again I can't pin which commit fixed a ticket, but the test case is in r18937.

        Show
        Paul Phillips added a comment - Once again I can't pin which commit fixed a ticket, but the test case is in r18937.
        Hide
        Martin Odersky added a comment -

        This re-surfaced with the fix to SI-2635. The problem seems to be deep in the constraint variable solver which can produce solutions that then do not conform to bounds. A simpler test case is here (in pending/pos/depexists.scala):

         val c: Cell[(a, b)] forSome { type a <: Number; type b <: (a, a) } = null
         val d = c
        

        I defer until we redo the whole approach to constraint solving (which we should do, soon).

        Show
        Martin Odersky added a comment - This re-surfaced with the fix to SI-2635 . The problem seems to be deep in the constraint variable solver which can produce solutions that then do not conform to bounds. A simpler test case is here (in pending/pos/depexists.scala): val c: Cell[(a, b)] forSome { type a <: Number; type b <: (a, a) } = null val d = c I defer until we redo the whole approach to constraint solving (which we should do, soon).
        Hide
        Paul Phillips added a comment -

        That test has been in files/pos for a year now so I think it's time to close this ticket; I'm sure we'll have no trouble finding issues of more recent vintage.

        Show
        Paul Phillips added a comment - That test has been in files/pos for a year now so I think it's time to close this ticket; I'm sure we'll have no trouble finding issues of more recent vintage.

          People

          • Assignee:
            Martin Odersky
            Reporter:
            Erik Engbrecht
            TracCC:
            Paul Phillips
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development