Uploaded image for project: 'Scala Programming Language'
  1. Scala Programming Language
  2. SI-5629

Endless recursion as a result of incorrect specialization

    Details

      Description

      test.scala

      object test extends App {
       
        trait MyPF[@specialized(Int) -A] extends (A => Unit) {
          def isDefinedAt(x: A): Boolean
          def applyOrElse[A1 <: A](x: A1, default: A1 => Unit): Unit = {
            println("MyPF.applyOrElse entered...")
            if (isDefinedAt(x)) apply(x) else default(x)
          }
        }
       
        trait MySmartPF[@specialized(Int) -A] extends MyPF[A] {
          def apply(x: A): Unit = {
            println("MySmartPF.apply entered...")
            applyOrElse(x, { _: Any => throw new MatchError })
          }
        }
       
        type T = Int
        //type T = Any
       
        def newPF(test: T): MyPF[T] = new MySmartPF[T] {
          def isDefinedAt(x: T): Boolean = x != test
          override def applyOrElse[A1 <: T](x: A1, default: A1 => Unit): Unit = {
            println("newPF.applyOrElse entered...")
            if (x != test) { println("ok"); () } else { println("default"); default(x) } 
          }
        }
        
        val pf = newPF(1)
        println("=== pf(1):")
        try { pf(1) } catch { case x => println(x) }
        println("=== pf(42):")
        pf(42)
        println("=== done")
      }
      

      Expected output:

      === pf(1):
      MySmartPF.apply entered...
      newPF.applyOrElse entered...
      default
      scala.MatchError: () (of class scala.runtime.BoxedUnit)
      === pf(42):
      MySmartPF.apply entered...
      newPF.applyOrElse entered...
      ok
      === done
      

      Actual output:

      === pf(1):
      MySmartPF.apply entered...
      MyPF.applyOrElse entered...
      scala.MatchError: () (of class scala.runtime.BoxedUnit)
      === pf(42):
      MySmartPF.apply entered...
      MyPF.applyOrElse entered...
      MySmartPF.apply entered...
      MyPF.applyOrElse entered...
      ...
      java.lang.StackOverflowError
      

      The bug is no longer reproduced when we replace `type T = Int` by `type T = Any` or remove @specialized.

      Now this prevents partial functions to be specialized.

        Attachments

          Activity

            People

            • Assignee:
              prokopec Aleksandar Prokopec
              Reporter:
              ppavlov Pavel Pavlov
            • Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: