Skip to content

Passing a Function0 by-name generates an (unnecessary?) wrapper #14623

Closed
@armanbilge

Description

@armanbilge

Initially discussed in:

after being discovered in:

Additional background:

Minimized example

object Thunk {
  private[this] val impl =
    ((x: Any) => x).asInstanceOf[(=> Any) => Function0[Any]]

  def asFunction0[A](thunk: => A): Function0[A] = impl(thunk).asInstanceOf[Function0[A]]
}

"Thunk.asFunction0" should {
  "return the same function" in {
    var i = 0
    val f = () => i += 1
    Thunk.asFunction0(f()) eq f
  }
}

Output

3.0.2

 private static final boolean $init$$$anonfun$2$$anonfun$1() {
    IntRef i = IntRef.create(0);
    Function0 f = () -> {
       int var1 = i.elem + 1;
       i.elem = var1;
    };
    return cats.effect.Thunk..MODULE$.asFunction0(f) == f; // true
 }

3.1.3-RC1-bin-20220207-74c2954-NIGHTLY

Following changes in:

 private static final void $init$$$anonfun$1$$anonfun$1$$anonfun$1(final Function0 f$1) {
    f$1.apply$mcV$sp();
 }

 private static final boolean $init$$$anonfun$1$$anonfun$1() {
    IntRef i = IntRef.create(0);
    Function0 f = () -> {
       int var1 = i.elem + 1;
       i.elem = var1;
    };
    return cats.effect.Thunk..MODULE$.asFunction0(() -> {
       $init$$$anonfun$1$$anonfun$1$$anonfun$1(f);
       return BoxedUnit.UNIT;
    }) == f; // false
 }

Expectation

In 2.13.8, this optimization occurs without any ceremony on our part.

object Thunk {
  def asFunction0[A](thunk: => A): Function0[A] = () => thunk
}

"Thunk.asFunction0" should {
  "return the same function" in {
    var i = 0
    val f = () => i += 1
    Thunk.asFunction0(f()) eq f // true
  }
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions