Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pickling crash compiling perspective from community build #13660

Closed
griggt opened this issue Oct 3, 2021 · 3 comments · Fixed by #13663
Closed

Pickling crash compiling perspective from community build #13660

griggt opened this issue Oct 3, 2021 · 3 comments · Fixed by #13663
Assignees
Labels
itype:bug itype:crash regression This worked in a previous version but doesn't anymore
Milestone

Comments

@griggt
Copy link
Contributor

griggt commented Oct 3, 2021

Since #13650, compiling perspective results in a crash (it was disabled in the community build by 5793f90)

A self-contained version of the offending code is below.

/cc @Katrix

Compiler version

3.1.1-RC1-bin-SNAPSHOT-git-8c3e7a2

Minimized code

type Const[A] = [_] =>> A
type FunctionK[A[_], B[_]] = [Z] => A[Z] => B[Z]

type ~>:[A[_], B[_]] = FunctionK[A, B]
type ~>#:[F[_], R] = F ~>: Const[R]
type #~>#:[T, R] = Const[T] ~>: Const[R]

object FunctionK:
  def liftConst[A, B](f: A => B): A #~>#: B = [Z] => (a: A) => f(a)

trait FoldableK[F[_[_], _]]:
  extension[A[_], C](fa: F[A, C]) 
    def foldMapK[B](f: A ~>#: B): B

  extension[A, C](fa: F[Const[A], C])
    def toListK: List[A] = fa.foldMapK(FunctionK.liftConst(List(_: A)))

Output (click arrow to expand)

error when pickling type Z
error when pickling type Const[List[A]][Z]
error when pickling tree Const[List[A]][Z]
error when pickling tree FoldableK.this.foldMapK[([_] =>> A), C](fa)[Const[List[A]][Z]]
error when pickling tree FoldableK.this.foldMapK[([_] =>> A), C](fa)[Const[List[A]][Z]](
  FunctionK.liftConst[A, List[A]](
    {
      def $anonfun(_$11: A): List[A] = List.apply[A]([_$11:A : A]*)
      closure($anonfun)
    }
  )
)
error when pickling tree extension [A >: Nothing <: Any, C >: Nothing <: Any](fa: FoldableK.this.F[Const[A], C]) def toListK: List[A] = 
  this.foldMapK[([_] =>> A), C](fa)[Const[List[A]][Z]](
    FunctionK.liftConst[A, List[A]](
      {
        def $anonfun(_$11: A): List[A] = List.apply[A]([_$11:A : A]*)
        closure($anonfun)
      }
    )
  )
error when pickling tree [F[_[_ >: Nothing <: Any] >: Nothing <: Any, _ >: Nothing <: Any] >: Nothing <: Any]() extends Object {
  F[_$7[_$8],_$9]
  extension [A[_ >: Nothing <: Any] >: Nothing <: Any, C >: Nothing <: Any](fa: FoldableK.this.F[A, C]) def foldMapK[
    B >: Nothing <: Any
  ](f: ~>#:[A, B]): B
  extension [A >: Nothing <: Any, C >: Nothing <: Any](fa: FoldableK.this.F[Const[A], C]) def toListK: List[A] = 
    this.foldMapK[([_] =>> A), C](fa)[Const[List[A]][Z]](
      FunctionK.liftConst[A, List[A]](
        {
          def $anonfun(_$11: A): List[A] = List.apply[A]([_$11:A : A]*)
          closure($anonfun)
        }
      )
    )
}
error when pickling tree @SourceFile("FoldableK.scala") trait FoldableK[F[_[_ >: Nothing <: Any] >: Nothing <: Any, _ >: Nothing <: Any] >: Nothing <: Any
  ]
() extends Object {
  F[_$7[_$8],_$9]
  extension [A[_ >: Nothing <: Any] >: Nothing <: Any, C >: Nothing <: Any](fa: FoldableK.this.F[A, C]) def foldMapK[
    B >: Nothing <: Any
  ](f: ~>#:[A, B]): B
  extension [A >: Nothing <: Any, C >: Nothing <: Any](fa: FoldableK.this.F[Const[A], C]) def toListK: List[A] = 
    this.foldMapK[([_] =>> A), C](fa)[Const[List[A]][Z]](
      FunctionK.liftConst[A, List[A]](
        {
          def $anonfun(_$11: A): List[A] = List.apply[A]([_$11:A : A]*)
          closure($anonfun)
        }
      )
    )
}
error when pickling tree package <empty> {
  @SourceFile("FoldableK.scala") trait FoldableK[
    F[_[_ >: Nothing <: Any] >: Nothing <: Any, _ >: Nothing <: Any] >: Nothing <: Any
  ]() extends Object {
    F[_$7[_$8],_$9]
    extension [A[_ >: Nothing <: Any] >: Nothing <: Any, C >: Nothing <: Any](fa: FoldableK.this.F[A, C]) def foldMapK[
      B >: Nothing <: Any
    ](f: ~>#:[A, B]): B
    extension [A >: Nothing <: Any, C >: Nothing <: Any](fa: FoldableK.this.F[Const[A], C]) def toListK: List[A] = 
      this.foldMapK[([_] =>> A), C](fa)[Const[List[A]][Z]](
        FunctionK.liftConst[A, List[A]](
          {
            def $anonfun(_$11: A): List[A] = List.apply[A]([_$11:A : A]*)
            closure($anonfun)
          }
        )
      )
  }
}
exception occurred while compiling FoldableK.scala
java.lang.AssertionError: assertion failed: orphan parameter reference: TypeParamRef(Z) while compiling FoldableK.scala
Exception in thread "main" java.lang.AssertionError: assertion failed: orphan parameter reference: TypeParamRef(Z)
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:289)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:160)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType$$anonfun$11$$anonfun$1(TreePickler.scala:181)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType$$anonfun$2(TreePickler.scala:181)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:181)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:160)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:604)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTpt(TreePickler.scala:316)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$39$$anonfun$1(TreePickler.scala:435)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$4(TreePickler.scala:435)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:436)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$3(TreePickler.scala:427)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:429)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTreeUnlessEmpty(TreePickler.scala:319)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef$$anonfun$1(TreePickler.scala:335)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef(TreePickler.scala:337)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:560)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats$$anonfun$2(TreePickler.scala:360)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats(TreePickler.scala:360)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$26(TreePickler.scala:586)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:587)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef$$anonfun$1(TreePickler.scala:332)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef(TreePickler.scala:337)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:562)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats$$anonfun$2(TreePickler.scala:360)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats(TreePickler.scala:360)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$29(TreePickler.scala:602)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:602)
	at dotty.tools.dotc.core.tasty.TreePickler.pickle$$anonfun$1(TreePickler.scala:773)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.dotc.core.tasty.TreePickler.pickle(TreePickler.scala:773)
	at dotty.tools.dotc.transform.Pickler.run$$anonfun$3$$anonfun$2(Pickler.scala:69)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.dotc.transform.Pickler.run$$anonfun$1(Pickler.scala:106)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.immutable.List.foreach(List.scala:333)
	at dotty.tools.dotc.transform.Pickler.run(Pickler.scala:106)
	at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:308)
	at scala.collection.immutable.List.map(List.scala:246)
	at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:309)
	at dotty.tools.dotc.transform.Pickler.runOn(Pickler.scala:111)
	at dotty.tools.dotc.Run.runPhases$4$$anonfun$4(Run.scala:261)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:15)
	at scala.runtime.function.JProcedure1.apply(JProcedure1.java:10)
	at scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
	at dotty.tools.dotc.Run.runPhases$5(Run.scala:272)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:280)
	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:68)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:289)
	at dotty.tools.dotc.Run.compileSources(Run.scala:222)
	at dotty.tools.dotc.Run.compile(Run.scala:206)
	at dotty.tools.dotc.Driver.doCompile(Driver.scala:39)
	at dotty.tools.dotc.Driver.process(Driver.scala:199)
	at dotty.tools.dotc.Driver.process(Driver.scala:167)
	at dotty.tools.dotc.Driver.process(Driver.scala:179)
	at dotty.tools.dotc.Driver.main(Driver.scala:209)
	at dotty.tools.dotc.Main.main(Main.scala)
@griggt griggt added itype:bug itype:crash regression This worked in a previous version but doesn't anymore labels Oct 3, 2021
@odersky
Copy link
Contributor

odersky commented Oct 3, 2021

I minimized further to

type Const[A] = [_] =>> A
type FunctionK[A[_], B[_]] = [Z] => A[Z] => B[Z]

type #~>#:[T, R] = FunctionK[Const[T], Const[R]]

object FunctionK:
  def liftConst[A, B](f: A => B): /*FunctionK[Const[A], Const[B]]*/ A #~>#: B =
    [Z1] => (a: A) => f(a)

trait FoldableK[F[_[_], _]]:

  def foldMapK1[A[_], C, B](fa: F[A, C])(f: FunctionK[A, Const[B]]): B

  def toListK[A, C](fa: F[Const[A], C]): List[A] =
    foldMapK1(fa)(FunctionK.liftConst(List(_: A)))

Interestingly, if I expand the alias A #~>#: B in the definition of liftConst to FunctionK[Const[A], Const[B]] everything compiles.

What happens is:

  1. We compare at some stage a polymorphic function with the poly function type [Z] => A[Z] => B[Z].
  2. This causes a constraint B >: Const[List[A]][Z] to be added.
  3. The comparison returns true with this added constraint.
  4. But the Z binding goes out of scope after the comparison.

Hence the orphan parameter. It looks like another instance of the problem where we have to avoid certain parameters in a constraint. @smarter, do we have a solution for that yet?

@smarter
Copy link
Member

smarter commented Oct 3, 2021

Thanks for the minimization, I have wip branch where I'm working on this sort of issues so I'll keep this in mind.

@smarter smarter self-assigned this Oct 3, 2021
odersky added a commit to dotty-staging/dotty that referenced this issue Oct 3, 2021
Remember comparisons of PolyTypes in `comparedTypeLambdas`. This means that parameters
of such types will not be added to the constraint. We already do the same for HkTypeLambdas
but for some reason we forgot to do it for PolyTypes, which are the other kind of type lambdas.

Fixes scala#13660

Allows perspective to be re-enabled in CB
@odersky
Copy link
Contributor

odersky commented Oct 3, 2021

It turns out this had a more obvious fix: Just treat PolyTypes like HKTypeLambdas.

olsdavis pushed a commit to olsdavis/dotty that referenced this issue Apr 4, 2022
Remember comparisons of PolyTypes in `comparedTypeLambdas`. This means that parameters
of such types will not be added to the constraint. We already do the same for HkTypeLambdas
but for some reason we forgot to do it for PolyTypes, which are the other kind of type lambdas.

Fixes scala#13660

Allows perspective to be re-enabled in CB
@Kordyjan Kordyjan added this to the 3.1.1 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
itype:bug itype:crash regression This worked in a previous version but doesn't anymore
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants