Skip to content

Objects in traits are instantiated on every access #3624

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

Closed
OlivierBlanvillain opened this issue Dec 2, 2017 · 0 comments
Closed

Objects in traits are instantiated on every access #3624

OlivierBlanvillain opened this issue Dec 2, 2017 · 0 comments

Comments

@OlivierBlanvillain
Copy link
Contributor

trait T {
  case object Foo
}

object Bar extends T

object Test {
  def main(args: Array[String]): Unit = {
    assert(Bar.Foo == Bar.Foo) // false
  }
}

Looking at the bytecode we see than Bar.Foo calls T.Foo which creates a new instance on every call:

public interface T {
    default public void $init$() {
    }

    default public Foo. Foo() {
        return new Foo.();
    }
}

public final class Bar$
implements T {
    public static final Bar$ MODULE$;

    public static {
        new Bar$();
    }

    public Bar$() {
        MODULE$ = this;
    }

    @Override
    public final T.Foo. Foo() {
        return T.super.Foo();
    }
}

For comparison, this the code generated by scalac:

public interface T {
    public Foo. Foo();

    default public static void $init$(T $this) {
    }
}

public final class Bar$
implements T {
    public static Bar$ MODULE$;
    private volatile T.Foo. Foo$module;

    public static {
        new Bar$();
    }

    @Override
    public T.Foo. Foo() {
        if (this.Foo$module == null) {
            this.Foo$lzycompute$1();
        }
        return this.Foo$module;
    }

    private final void Foo$lzycompute$1() {
        Bar$ bar$ = this;
        synchronized (bar$) {
            if (this.Foo$module == null) {
                this.Foo$module = new T.Foo.(null);
            }
        }
    }

    private Bar$() {
        MODULE$ = this;
        T.$init$(this);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants