Skip to content

Unnecessary allocation in name-based matching on value class #12405

@lrytz

Description

@lrytz
final class OptionVal[+A](val x: A) extends AnyVal {
  def isEmpty: Boolean =
    x == null
  def get: A =
    if (x == null) throw new NoSuchElementException("OptionVal.None.get")
    else x
}

object OptionVal {
  object Some {
    def apply[A](x: A): OptionVal[A] = new OptionVal(x)
    def unapply[A](x: OptionVal[A]): OptionVal[A] = x
  }
  def none[A]: OptionVal[A] = None.asInstanceOf[OptionVal[A]]
  val None = new OptionVal[Null](null)
}

class Test {
  def foo: OptionVal[String] = ???
  def bar = foo match {
    case OptionVal.Some(s) => s
    case _ => ""
  }
}

The 2.13 compiler emits a redunand null check on a freshly created OptionVal instance.

    public String bar() {
        String s;
        String string;
        String string2 = this.foo();
        String string3 = new OptionVal<String>(string2) != null && !OptionVal$.MODULE$.isEmpty$extension(string = OptionVal.Some$.MODULE$.unapply(string2)) ? (s = OptionVal$.MODULE$.get$extension(string)) : "";
        return string3;
    }

This was not the case in 2.12:

    public String bar() {
        String s;
        String string = this.foo();
        String string2 = OptionVal.Some$.MODULE$.unapply(string);
        String string3 = !OptionVal$.MODULE$.isEmpty$extension(string2) ? (s = OptionVal$.MODULE$.get$extension(string2)) : "";
        return string3;
    }

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions