Skip to content

Possible to capture null reference to case object before initialisation, under certain conditions #3342

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
scabug opened this issue Apr 22, 2010 · 9 comments
Assignees

Comments

@scabug
Copy link

scabug commented Apr 22, 2010

The following code produces a set 'values' that contains null when it shouldn't:

object Foo {

  case object F1 extends Foo
  case object F2 extends Foo

  val values = Set(F1,F2)

}

// remove default and no problem
sealed abstract class Foo private(val bar:Boolean=false) {}

object Bug {

  val foo = Foo.F1 // remove and no problem

  def main(args:Array[String]):Unit = {
	Foo.values contains Foo.F1      // expect true but is false!
	println(Foo.values)	        // contains null instead of F1?!
  }
}

class Bug {}

Appears to be caused by the combination of referencing F1 from another companion object AND the default constructor argument.

scala:2.8.0.RC1

java:1.6.0_16-b01

os:linux

@scabug
Copy link
Author

scabug commented Apr 22, 2010

Imported From: https://issues.scala-lang.org/browse/SI-3342?orig=1
Reporter: adam77

@scabug
Copy link
Author

scabug commented Apr 26, 2010

@dubochet said:
The code you provide doesn't compile (F1, F2 cannot extend an object).

Can you provide a correct example that displays the bug. Please, reopen the bug once you have done that.

@scabug
Copy link
Author

scabug commented Apr 26, 2010

adam77 said:
I copied the code from above and it compiled and ran using the following commands...

adam@laptop:~/progs/scala-2.8.0.RC1/bin$$ ./scalac bug.scala
adam@laptop:~/progs/scala-2.8.0.RC1/bin$$ ./scala Bug
Set(null, F2)

Here's the verbose version...

adam@laptop:~/progs/scala-2.8.0.RC1/bin$$ ./scalac -verbose bug.scala
[Classpath = /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/resources.jar:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/jsse.jar:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/jce.jar:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/charsets.jar:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/ext/sunjce_provider.jar:/home/adam/progs/scala-2.8.0.RC1/lib/scala-compiler.jar:/home/adam/progs/scala-2.8.0.RC1/lib/jline.jar:/home/adam/progs/scala-2.8.0.RC1/lib/scala-dbc.jar:/home/adam/progs/scala-2.8.0.RC1/lib/scala-swing.jar:/home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar:/home/adam/progs/scala-2.8.0.RC1/lib/scalap.jar:.]
[loaded package loader resources.jar in 1643ms]
[loaded package loader java in 1ms]
[loaded package loader lang in 16ms]
[loaded package loader reflect in 18ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/package.class) in 294ms]
[loaded package loader scala in 775ms]
[loaded package loader runtime in 8ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/Object.class) in 35ms]
[loaded package loader io in 8ms]
[loaded package loader util in 50ms]
[loaded package loader nio in 7ms]
[loaded package loader charset in 1ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/String.class) in 183ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/package.class) in 15ms]
[loaded package loader collection in 24ms]
[loaded plugin continuations]
[dropping dependency on node with no phase object: msil]
[promote the dependency of explicitouter: tailcalls => specialize]
[parsing bug.scala]
[parser in 195ms]
[loaded package loader annotation in 0ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Predef.class) in 27ms]
[namer in 169ms]
[packageobjects in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/ScalaObject.class) in 8ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/LowPriorityImplicits.class) in 3ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/Boolean.class) in 6ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/ClassfileAnnotation.class) in 12ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Annotation.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/StaticAnnotation.class) in 3ms]
[loaded package loader immutable in 10ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/Set.class) in 42ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/package.class) in 4ms]
[loaded package loader generic in 9ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/SetFactory.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/GenericCompanion.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Product.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Equals.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/List.class) in 18ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/SeqFactory.class) in 5ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/TraversableFactory.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Array.class) in 9ms]
[loaded package loader target in 0ms]
[loaded package loader unchecked in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/annotation/unchecked/uncheckedVariance.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/TypeConstraint.class) in 2ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/IndexOutOfBoundsException.class) in 1ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/RuntimeException.class) in 2ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/Exception.class) in 3ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/Throwable.class) in 4ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/io/Serializable.class) in 1ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/Comparable.class) in 11ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/CharSequence.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/Iterable.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/Traversable.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/Traversable.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/TraversableLike.class) in 22ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/HasNewBuilder.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/TraversableOnce.class) in 6ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/GenericTraversableTemplate.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Immutable.class) in 15ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/Iterable.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/IterableLike.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/Set.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Function1.class) in 5ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/GenericSetTemplate.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/SetLike.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/Addable.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/Subtractable.class) in 1ms]
[typer in 1237ms]
[superaccessors in 49ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/serializable.class) in 2ms]
[pickler in 87ms]
[refchecks in 122ms]
[selectiveanf in 7ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/reflect/Code.class) in 2ms]
[liftcode in 7ms]
[selectivecps in 27ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/Seq.class) in 3ms]
[loaded package loader mutable in 13ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/WrappedArray.class) in 33ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/IndexedSeq.class) in 13ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/ArrayLike.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/PartialFunction.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/SeqLike.class) in 7ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/LinearSeq.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/LinearSeqOptimized.class) in 19ms]
[uncurry in 202ms]
[tailcalls in 37ms]
[loaded package loader reflect in 1ms]
[loaded package loader net in 2ms]
[loaded package loader security in 6ms]
[loaded package loader sun in 2ms]
[loaded package loader reflect in 11ms]
[loaded package loader annotation in 1ms]
[loaded package loader annotation in 1ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/Class.class) in 86ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/Iterator.class) in 14ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Some.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/generic/CanBuildFrom.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/Builder.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple2.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Either.class) in 6ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Function2.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Function3.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Function0.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Function4.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Function5.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/Seq.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/LinearSeq.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/LinearSeqLike.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/Stream.class) in 10ms]
[specialize in 572ms]
[explicitouter in 208ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/Map.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Option.class) in 12ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/TraversableView.class) in 7ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/math/package.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/MathCommon.class) in 12ms]
[loaded package loader math in 16ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/math/Numeric.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/math/Ordering.class) in 6ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/Buffer.class) in 11ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/reflect/ClassManifest.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/Map.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/IterableView.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/Map.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/SeqView.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/immutable/IndexedSeq.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/reflect/Manifest.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple3.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/ArrayOps.class) in 10ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/IndexedSeq.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/xml/package.class) in 2ms]
[loaded package loader xml in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple1.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple4.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple5.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple6.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple7.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple8.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple9.class) in 53ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple10.class) in 3ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple11.class) in 17ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple12.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple13.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple14.class) in 12ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple15.class) in 5ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple16.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple17.class) in 4ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple18.class) in 22ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple19.class) in 20ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple20.class) in 5ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple21.class) in 5ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Tuple22.class) in 5ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/Seq.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/IndexedSeqLike.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/IndexedSeqOptimized.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/Iterable.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/IndexedSeqLike.class) in 33ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/Traversable.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/Mutable.class) in 1ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/mutable/IndexedSeqView.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/IndexedSeqOptimized.class) in 3ms]
[erasure in 1501ms]
[lazyvals in 12ms]
[lambdalift in 91ms]
[constructors in 47ms]
[flatten in 9ms]
[mixin in 144ms]
[cleanup in 26ms]
[Generating icode for bug.scala]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/collection/BufferedIterator.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/CountedIterator.class) in 1ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/Integer.class) in 12ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/Number.class) in 1ms]
[Generate ICode from the AST in 407ms]
[inliner in 1ms]
[closelim in 0ms]
[dce in 0ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/deprecated.class) in 1ms]
[wrote ./Foo$$F1$$.class]
[wrote ./Foo$$F2$$.class]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/annotation/RetentionPolicy.class) in 1ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/annotation/ElementType.class) in 2ms]
[loaded class file /home/adam/progs/scala-2.8.0.RC1/lib/scala-library.jar(scala/reflect/ScalaSignature.class) in 11ms]
[loaded class file /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/rt.jar(java/lang/annotation/Annotation.class) in 1ms]
[wrote ./Bug.class]
[wrote ./Bug$$.class]
[wrote ./Foo$$.class]
[wrote ./Foo.class]
[jvm in 446ms]
[total in 5617ms]

@scabug
Copy link
Author

scabug commented Apr 27, 2010

@dubochet said:
Ok, I got it. I was testing the bug with the interpreter and forgot to compile the Foo class before the object. Sorry.

@scabug
Copy link
Author

scabug commented Apr 28, 2010

@lrytz said:
As iulian suggested, this is a consequence of how objects are compiled. For every object, Scala generates a class which looks like this (java-syntax):

class Obj {
  public static Obj MODULE$$ = null;
  static this() { MODULE$$ = new Obj(); }
  this() { /* module constructor code */ }
}

The static initializer is executed exactly once, when the class is loaded.

Every reference to the object Obj is compiled to an access to the static field Obj.MODULE$$.

Now for your example, here's the initialization sequence. Note that classes are flattened, so Foo.F1 is Foo$$F1.

Bug.<static-init> -> Bug.this() -> foo = Foo$$F1.MODULE$$ -> Foo$$F1.<static-init> ->
Foo$$F1.this() -> Foo.Foo$$$$init$$default$$1() -> Foo.<staic-init> ->
Foo.this() -> values = Set(Foo$$F1.MODULE$$ [*], Foo$$F2.MODULE$$) ->
Foo$$F2.<static-init> -> Foo$$F2.this() -> Foo.Foo$$$$init$$default$$2() [%] ->

OK for Foo$$F2, the super constructor is called, an object is created,
the access to Foo$$F2.MODULE$$ returns the instance.

[*] static init of Foo$$F1 has already been launched, so just get to the field.
    Since the constructor is still running, the MODULE$$ filed is still null.
[%] static init of Foo has already been launched, so just run to the init$$default$$2 method

I don't think there's a way to fix this issue. Iulian, please let me know if you agree.

@scabug
Copy link
Author

scabug commented Apr 28, 2010

adam77 said:
Thanks for the explanation.

How come there is no problem when the default is removed from the constructor parameter?

Also, I don't think its a good idea to just leave a gotcha in the language like this.

Thanks again.

@scabug
Copy link
Author

scabug commented Apr 29, 2010

@lrytz said:
Replying to [comment:8 adam77]:

How come there is no problem when the default is removed from the constructor parameter?

Without the default argument, the constructor of Foo$$F1[object] does not need to call the constructor of Foo[object], which breaks the chain described above.

You can reproduce the problem without default arguments:

object Foo {
  case object F1 extends Foo(getBool)
  case object F2 extends Foo(getBool)

  val values = Set(F1,F2)

  def getBool = false
}

abstract class Foo private(bar: Boolean)

object Bug {
  val foo = Foo.F1

  def main(args:Array[String]):Unit = {
	println(Foo.values)
  }
}

@scabug
Copy link
Author

scabug commented Apr 29, 2010

@dragos said:
I agree there is no fix, or at least I don't see one either. The problem is the lazy nature of objects, and the cyclic dependency you silently introduced. The cycle appears because the default argument (ant this may be the unintuitive part) is evaluated at the call site, that is, inside `Foo'. To break the cycle you need to either see uninitialized values, or crash. :)

It would be nice if we could have a warning for this situation. I'm not sure how hard it is.

@som-snytt
Copy link

Answer to previous question is -Ysafe-init-global in Scala 3.

@som-snytt som-snytt closed this as not planned Won't fix, can't repro, duplicate, stale May 13, 2024
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