Applying a polymorphic identity function to itself

I tried making a polymorphic identity function in Scala 3:

val f = [T] => (x: T) => x

I can now apply it to itself (f(f)), but only once. f(f)(f) gives me the following error:

exception while typing f.apply[(f : Function1)](f).apply of class class dotty.tools.dotc.ast.Trees$Select # -1
exception while typing f.apply[(f : Function1)](f).apply[(f : Function1)] of class class dotty.tools.dotc.ast.Trees$TypeApply # -1
exception while typing f.apply[(f : Function1)](f).apply[(f : Function1)](f) of class class dotty.tools.dotc.ast.Trees$Apply # -1
exception while typing println(f.apply[(f : Function1)](f).apply[(f : Function1)](f)) of class class dotty.tools.dotc.ast.Trees$Apply # -1
exception while typing {
  val f: PolyFunction{apply: [T](x: T): T} = 
    {
      final class $anon() extends Object(), PolyFunction {
        def apply[T](x: T): T = x
      }
      new Object with PolyFunction {...}():PolyFunction{apply: [T](x: T): T}
    }
  println(f.apply[(f : Function1)](f).apply[(f : Function1)](f))
} of class class dotty.tools.dotc.ast.Trees$Block # -1
exception while typing @main() def main: Unit = 
  {
    val f: PolyFunction{apply: [T](x: T): T} = 
      {
        final class $anon() extends Object(), PolyFunction {
          def apply[T](x: T): T = x
        }
        new Object with PolyFunction {...}():PolyFunction{apply: [T](x: T): T}
      }
    println(f.apply[(f : Function1)](f).apply[(f : Function1)](f))
  } of class class dotty.tools.dotc.ast.Trees$DefDef # -1
exception while typing @scala.annotation.internal.SourceFile("src/main/scala/main.scala") final module 
  class
 main$package$() extends Object() {
  private def writeReplace(): AnyRef = 
    new scala.runtime.ModuleSerializationProxy(classOf[main$package.type])
  @main() def main: Unit = 
    {
      val f: PolyFunction{apply: [T](x: T): T} = 
        {
          final class $anon() extends Object(), PolyFunction {
            def apply[T](x: T): T = x
          }
          new Object with PolyFunction {...}():PolyFunction{apply: [T](x: T): T}
        }
      println(f.apply[(f : Function1)](f).apply[(f : Function1)](f))
    }
} of class class dotty.tools.dotc.ast.Trees$TypeDef # -1
exception while typing package <empty> {
  final lazy module val main$package: main$package$ = new main$package$()
  @scala.annotation.internal.SourceFile("src/main/scala/main.scala") final 
    module
   class main$package$() extends Object() {
    private def writeReplace(): AnyRef = 
      new scala.runtime.ModuleSerializationProxy(classOf[main$package.type])
    @main() def main: Unit = 
      {
        val f: PolyFunction{apply: [T](x: T): T} = 
          {
            final class $anon() extends Object(), PolyFunction {
              def apply[T](x: T): T = x
            }
            new Object with PolyFunction {...}():
              PolyFunction{apply: [T](x: T): T}
          }
        println(f.apply[(f : Function1)](f).apply[(f : Function1)](f))
      }
  }
  @scala.annotation.internal.SourceFile("src/main/scala/main.scala") final class
     
  main() extends Object() {
    <static> def main(args: Array[String]): Unit = 
      try main$package.main catch 
        {
          case error @ _:scala.util.CommandLineParser.ParseError => 
            scala.util.CommandLineParser.showError(error)
        }
  }
} of class class dotty.tools.dotc.ast.Trees$PackageDef # -1
java.lang.AssertionError: assertion failed:  <none> while compiling /tmp/scastie7318598556215452568/src/main/scala/main.scala
//Long stacktrace omitted

Scastie

Obviously, the compiler isn’t supposed to crash like that, but even so, is my code valid according to the language specs?

2 Likes

Yes I think that should work. And it definitely should never crash the compiler, so that’s a good issue to report IMO.

3 Likes

Wow, I didn’t realize Scala 3 allows polymorphic functions.