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

Regression: Opaque types aliasing context functions are crashing the compiler #16035

Closed
Kordyjan opened this issue Sep 13, 2022 · 3 comments · Fixed by #16041
Closed

Regression: Opaque types aliasing context functions are crashing the compiler #16035

Kordyjan opened this issue Sep 13, 2022 · 3 comments · Fixed by #16041
Assignees
Labels
area:opaque-types itype:bug itype:crash regression This worked in a previous version but doesn't anymore
Milestone

Comments

@Kordyjan
Copy link
Contributor

Kordyjan commented Sep 13, 2022

Compiler version

3.1.2-RC1 up to 3.2.2-RC1-bin-20220910-ac6cd1c-NIGHTLY
The code was working in the range 3.0.0 - 3.1.1

Minimized code

object Scope:
  opaque type Uses[A, B] = A ?=> B

  object Uses:
    def apply[A, B](fn: A ?=> B): Uses[A, B] = fn

import Scope.*
val uses = Uses[Int, String](i ?=> s"*$i*")

Output (click arrow to expand)

exception while typing def uses: Scope.Uses[Int, String] =
  Scope.Uses.apply[Int, String](
    {
      def $anonfun(using i: Int): String = "*".+(i).+("*")
      closure($anonfun)
    }
  ) of class class dotty.tools.dotc.ast.Trees$DefDef # -1
exception while typing @SourceFile("rep.scala") final module class rep$package() extends Object() {
  private def writeReplace(): AnyRef =
    new scala.runtime.ModuleSerializationProxy(classOf[rep$package.type])
  def uses: Scope.Uses[Int, String] =
    Scope.Uses.apply[Int, String](
      {
        def $anonfun(using i: Int): String = "*".+(i).+("*")
        closure($anonfun)
      }
    )
} of class class dotty.tools.dotc.ast.Trees$TypeDef # -1
exception while typing package <empty> {
  final lazy module val Scope: Scope = new Scope()
  @SourceFile("rep.scala") final module class Scope() extends Object() {
    private def writeReplace(): AnyRef =
      new scala.runtime.ModuleSerializationProxy(classOf[Scope.type])
    type Uses = [A, B] =>> (A) ?=> B
    final lazy module val Uses: Scope.Uses = new Scope.Uses()
    final module class Uses() extends Object() {
      private def writeReplace(): AnyRef =
        new scala.runtime.ModuleSerializationProxy(classOf[Scope.Uses.type])
      @ContextResultCount(1) def apply[A, B](fn: (A) ?=> B): Scope.Uses[A, B] =
        {
          def $anonfun(using evidence$1: A): B = fn.apply(evidence$1)
          closure($anonfun)
        }
    }
  }
  import Scope.*
  final lazy module val rep$package: rep$package = new rep$package()
  @SourceFile("rep.scala") final module class rep$package() extends Object() {
    private def writeReplace(): AnyRef =
      new scala.runtime.ModuleSerializationProxy(classOf[rep$package.type])
    def uses: Scope.Uses[Int, String] =
      Scope.Uses.apply[Int, String](
        {
          def $anonfun(using i: Int): String = "*".+(i).+("*")
          closure($anonfun)
        }
      )
  }
} of class class dotty.tools.dotc.ast.Trees$PackageDef # -1
java.lang.AssertionError: assertion failed while running erasure on /Users/pmarks/projs/context/rep.scala
exception occurred while compiling /Users/pmarks/projs/context/rep.scala
java.lang.AssertionError: assertion failed while compiling /Users/pmarks/projs/context/rep.scala
Exception in thread "main" java.lang.AssertionError: assertion failed
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:11)
	at dotty.tools.dotc.transform.Erasure$Boxing$.adaptToType(Erasure.scala:389)
	at dotty.tools.dotc.transform.Erasure$Typer.adapt(Erasure.scala:1061)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3016)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3020)
	at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3136)
	at dotty.tools.dotc.typer.Typer.$anonfun$51(Typer.scala:2351)
	at dotty.tools.dotc.inlines.PrepareInlineable$.dropInlineIfError(PrepareInlineable.scala:249)
	at dotty.tools.dotc.typer.Typer.typedDefDef(Typer.scala:2351)
	at dotty.tools.dotc.transform.Erasure$Typer.typedDefDef(Erasure.scala:944)
	at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2862)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2948)
	at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:126)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3016)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3020)
	at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3042)
	at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3092)
	at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1043)
	at dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:2526)
	at dotty.tools.dotc.transform.Erasure$Typer.typedClassDef(Erasure.scala:1032)
	at dotty.tools.dotc.typer.Typer.typedTypeOrClassDef$1(Typer.scala:2874)
	at dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2878)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2948)
	at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:126)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3016)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3020)
	at dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:3042)
	at dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:3092)
	at dotty.tools.dotc.transform.Erasure$Typer.typedStats(Erasure.scala:1043)
	at dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:2653)
	at dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2919)
	at dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2949)
	at dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:126)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3016)
	at dotty.tools.dotc.typer.Typer.typed(Typer.scala:3020)
	at dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:3136)
	at dotty.tools.dotc.transform.Erasure.run(Erasure.scala:144)
	at dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:316)
	at scala.collection.immutable.List.map(List.scala:246)
	at dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:320)
	at dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:233)
	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:1328)
	at dotty.tools.dotc.Run.runPhases$1(Run.scala:244)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:252)
	at dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:261)
	at dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:68)
	at dotty.tools.dotc.Run.compileUnits(Run.scala:261)
	at dotty.tools.dotc.Run.compileSources(Run.scala:185)
	at dotty.tools.dotc.Run.compile(Run.scala:169)
	at dotty.tools.dotc.Driver.doCompile(Driver.scala:35)
	at dotty.tools.dotc.Driver.process(Driver.scala:195)
	at dotty.tools.dotc.Driver.process(Driver.scala:163)
	at dotty.tools.dotc.Driver.process(Driver.scala:175)
	at dotty.tools.dotc.Driver.main(Driver.scala:205)
	at dotty.tools.dotc.Main.main(Main.scala)
Compilation failed
@Kordyjan Kordyjan added itype:bug itype:crash regression This worked in a previous version but doesn't anymore stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 13, 2022
@Kordyjan
Copy link
Contributor Author

Workaround:

object Scope:
  opaque type Uses[A, B] = A => B

  object Uses:
    def apply[A, B](fn: A ?=> B): Uses[A, B] = a => fn(using a)

import Scope.*
val uses = Uses[Int, String](i ?=> s"*$i*")

I will try to bisect and investigate it tomorrow if nobody gets to it earlier.

@Kordyjan Kordyjan added area:opaque-types and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Sep 13, 2022
@Kordyjan
Copy link
Contributor Author

Even more interesting is that this works:

object Scope:
  opaque type Uses[A, B] = A ?=> B

  object Uses:
    inline def apply[A, B](fn: A ?=> B): Uses[A, B] = fn

import Scope.*
val uses = Uses[Int, String](i ?=> s"*$i*")

The only difference being inline modifier for the apply method.

@Kordyjan
Copy link
Contributor Author

Bisect points to f50b55c as first bad commit.

odersky added a commit to dotty-staging/dotty that referenced this issue Sep 14, 2022
We could allow them but they would not do what one probably expects (i.e. create
context closures). This is because abstract types upper-bounded by context functions
don't do that either (see neg/i16035a.scala), and we have to keep semantic equivalence
between the two.

Therefore, it's better to disallow them.

Fixes scala#16035
odersky added a commit to dotty-staging/dotty that referenced this issue Sep 14, 2022
We could allow them but they would not do what one probably expects (i.e. create
context closures). This is because abstract types upper-bounded by context functions
don't do that either (see neg/i16035a.scala), and we have to keep semantic equivalence
between the two.

Therefore, it's better to disallow them.

Fixes scala#16035
Kordyjan added a commit that referenced this issue Sep 15, 2022
We could allow them but they would not do what one probably expects
(i.e. create context closures). This is because abstract types
upper-bounded by context functions don't do that either (see
neg/i16035a.scala), and we have to keep semantic equivalence between the
two.

Therefore, it's better to disallow them.

Fixes #16035
mpollmeier pushed a commit to mpollmeier/dotty that referenced this issue Oct 16, 2022
We could allow them but they would not do what one probably expects (i.e. create
context closures). This is because abstract types upper-bounded by context functions
don't do that either (see neg/i16035a.scala), and we have to keep semantic equivalence
between the two.

Therefore, it's better to disallow them.

Fixes scala#16035
@Kordyjan Kordyjan added this to the 3.2.2 milestone Aug 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:opaque-types 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.

2 participants