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

Orphan parameter reference in capture set #15922

Closed
Linyxus opened this issue Aug 26, 2022 · 1 comment · Fixed by #15948
Closed

Orphan parameter reference in capture set #15922

Linyxus opened this issue Aug 26, 2022 · 1 comment · Fixed by #15948
Milestone

Comments

@Linyxus
Copy link
Contributor

Linyxus commented Aug 26, 2022

Compiler version

cc-experiment

Minimized code

trait Cap { def use(): Int }
type Id[X] = [T] -> (op: X => T) -> T
def mkId[X](x: X): Id[X] = [T] => (op: X => T) => op(x)

def withCap[X](op: ({*} Cap) => X): X = {
  val cap: {*} Cap = new Cap { def use() = { println("cap is used"); 0 } }
  val result = op(cap)
  result
}

def leaking(c: {*} Cap): Id[{c} Cap] = mkId(c)

val bad = withCap(leaking)

Output

error when pickling type c.type
error when pickling tree c
error when pickling tree [c : Any]
error when pickling tree [c : Any]*
error when pickling tree new _root_.scala.annotation.retains([c : Any]*)
error when pickling type {c} Cap
error when pickling type Id[{c} Cap]
error when pickling tree Id[{c} Cap]
error when pickling tree val bad: Id[{c} Cap] = 
  withCap[Id[{c} Cap]](
    {
      def $anonfun(c: {*} Cap): Id[{c} Cap] = leaking(c)
      closure($anonfun)
    }
  )
error when pickling tree () extends Object() { this: orphan-parameref$package.type =>
  private def writeReplace(): AnyRef = new scala.runtime.ModuleSerializationProxy(classOf[orphan-parameref$package.type])
  type Id[X >: Nothing <: Any] = 
    PolyFunction 
      {
        def apply[T >: Nothing <: Any](op: X => T): T
      }
  def mkId[X >: Nothing <: Any](x: X): Id[X] = 
    {
      final class $anon() extends Object(), PolyFunction {
        def apply[T >: Nothing <: Any](op: X => T): T = op.apply(x)
      }
      new $anon():([T] => (op: X => T) -> T)
    }
  def withCap[X >: Nothing <: Any](op: ({*} Cap) => X): X = 
    {
      val cap: {*} Cap = 
        {
          final class $anon() extends Object(), Cap {
            def use(): Int = 
              {
                println("cap is used")
                0
              }
          }
          new $anon():Cap
        }
      val result: X = op.apply(cap)
      result:X
    }
  def leaking(c: {*} Cap): Id[{c} Cap] = mkId[({*} Cap)](c)
  val bad: Id[{c} Cap] = 
    withCap[Id[{c} Cap]](
      {
        def $anonfun(c: {*} Cap): Id[{c} Cap] = leaking(c)
        closure($anonfun)
      }
    )
}
error when pickling tree @CaptureChecked @SourceFile("issues/orphan-parameref.scala") final module class orphan-parameref$package() extends Object() { this: orphan-parameref$package.type =>
  private def writeReplace(): AnyRef = new scala.runtime.ModuleSerializationProxy(classOf[orphan-parameref$package.type])
  type Id[X >: Nothing <: Any] = 
    PolyFunction 
      {
        def apply[T >: Nothing <: Any](op: X => T): T
      }
  def mkId[X >: Nothing <: Any](x: X): Id[X] = 
    {
      final class $anon() extends Object(), PolyFunction {
        def apply[T >: Nothing <: Any](op: X => T): T = op.apply(x)
      }
      new $anon():([T] => (op: X => T) -> T)
    }
  def withCap[X >: Nothing <: Any](op: ({*} Cap) => X): X = 
    {
      val cap: {*} Cap = 
        {
          final class $anon() extends Object(), Cap {
            def use(): Int = 
              {
                println("cap is used")
                0
              }
          }
          new $anon():Cap
        }
      val result: X = op.apply(cap)
      result:X
    }
  def leaking(c: {*} Cap): Id[{c} Cap] = mkId[({*} Cap)](c)
  val bad: Id[{c} Cap] = 
    withCap[Id[{c} Cap]](
      {
        def $anonfun(c: {*} Cap): Id[{c} Cap] = leaking(c)
        closure($anonfun)
      }
    )
}
error when pickling tree package <empty> {
  final lazy module val orphan-parameref$package: orphan-parameref$package = new orphan-parameref$package()
  @CaptureChecked @SourceFile("issues/orphan-parameref.scala") final module class orphan-parameref$package() extends Object() { this: orphan-parameref$package.type =>
    private def writeReplace(): AnyRef = new scala.runtime.ModuleSerializationProxy(classOf[orphan-parameref$package.type])
    type Id[X >: Nothing <: Any] = 
      PolyFunction 
        {
          def apply[T >: Nothing <: Any](op: X => T): T
        }
    def mkId[X >: Nothing <: Any](x: X): Id[X] = 
      {
        final class $anon() extends Object(), PolyFunction {
          def apply[T >: Nothing <: Any](op: X => T): T = op.apply(x)
        }
        new $anon():([T] => (op: X => T) -> T)
      }
    def withCap[X >: Nothing <: Any](op: ({*} Cap) => X): X = 
      {
        val cap: {*} Cap = 
          {
            final class $anon() extends Object(), Cap {
              def use(): Int = 
                {
                  println("cap is used")
                  0
                }
            }
            new $anon():Cap
          }
        val result: X = op.apply(cap)
        result:X
      }
    def leaking(c: {*} Cap): Id[{c} Cap] = mkId[({*} Cap)](c)
    val bad: Id[{c} Cap] = 
      withCap[Id[{c} Cap]](
        {
          def $anonfun(c: {*} Cap): Id[{c} Cap] = leaking(c)
          closure($anonfun)
        }
      )
  }
}
exception occurred while compiling issues/orphan-parameref.scala
java.lang.AssertionError: assertion failed: orphan parameter reference: TermParamRef(c) while compiling issues/orphan-parameref.scala
Exception in thread "main" java.lang.AssertionError: assertion failed: orphan parameter reference: TermParamRef(c)
	at scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:291)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:160)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:384)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$17$$anonfun$1(TreePickler.scala:513)
	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$17(TreePickler.scala:513)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$adapted$16(TreePickler.scala:513)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:513)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$6(TreePickler.scala:463)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$adapted$6(TreePickler.scala:463)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:463)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$3$$anonfun$1(TreePickler.scala:433)
	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$3(TreePickler.scala:433)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$adapted$3(TreePickler.scala:434)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:434)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType$$anonfun$6(TreePickler.scala:263)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType$$anonfun$adapted$6(TreePickler.scala:263)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType(TreePickler.scala:263)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleType(TreePickler.scala:160)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleNewType$$anonfun$2$$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.pickleNewType$$anonfun$adapted$2(TreePickler.scala:181)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	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:609)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTpt(TreePickler.scala:318)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef$$anonfun$1(TreePickler.scala:336)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef$$anonfun$adapted$1(TreePickler.scala:340)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef(TreePickler.scala:340)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:550)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats$$anonfun$2(TreePickler.scala:365)
	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:365)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$26(TreePickler.scala:591)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$adapted$24(TreePickler.scala:592)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:592)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef$$anonfun$1(TreePickler.scala:335)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef$$anonfun$adapted$1(TreePickler.scala:340)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleDef(TreePickler.scala:340)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:567)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleStats$$anonfun$2(TreePickler.scala:365)
	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:365)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$29(TreePickler.scala:607)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree$$anonfun$adapted$27(TreePickler.scala:607)
	at scala.Function0.apply$mcV$sp(Function0.scala:39)
	at dotty.tools.dotc.core.tasty.TreePickler.withLength(TreePickler.scala:58)
	at dotty.tools.dotc.core.tasty.TreePickler.pickleTree(TreePickler.scala:607)
	at dotty.tools.dotc.core.tasty.TreePickler.pickle$$anonfun$1(TreePickler.scala:779)
	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:779)
	at dotty.tools.dotc.transform.Pickler.run$$anonfun$1$$anonfun$1(Pickler.scala:72)
	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:110)
	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:110)
	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:317)
	at dotty.tools.dotc.transform.Pickler.runOn(Pickler.scala:115)
	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)

Expectation

It should not trigger AssertionError.

@Linyxus Linyxus added itype:bug stat:needs triage Every issue needs to have an "area" and "itype" label cc-experiment Intended to be merged with cc-experiment branch on origin and removed stat:needs triage Every issue needs to have an "area" and "itype" label labels Aug 26, 2022
@odersky
Copy link
Contributor

odersky commented Sep 1, 2022

Minimization without -Ycc:

trait Cap
class Id[X]

object Test:
  def withCap[X](op: Cap => X): X = ???

  class retains1(xs: Any*) extends annotation.StaticAnnotation

  def leaking(c: Cap): Id[Cap @retains1(c)] = ???

  val bad = withCap(leaking)

@bishabosha bishabosha removed the cc-experiment Intended to be merged with cc-experiment branch on origin label Sep 1, 2022
odersky added a commit to dotty-staging/dotty that referenced this issue Sep 1, 2022
Avoids orphan parameters when pickling

Fixes scala#15922

I am not sure about the status of the test in custome-args/captures. Should it
pass or be rejected? But in any case it does not crash anymore.
Linyxus added a commit that referenced this issue Sep 3, 2022
Avoids orphan parameters when pickling

Fixes #15922

I am not sure about the status of the test in custome-args/captures. Should it
pass or be rejected? But in any case it does not crash anymore.
mpollmeier pushed a commit to mpollmeier/dotty that referenced this issue Oct 16, 2022
Avoids orphan parameters when pickling

Fixes scala#15922

I am not sure about the status of the test in custome-args/captures. Should it
pass or be rejected? But in any case it does not crash anymore.
@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
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants